Improve the ergonomics of creating local buffers (#10347)
This PR renames `language::Buffer::new` to `language::Buffer::local` and simplifies its interface. Instead of taking a replica id (which should always be 0 for the local case) and a `BufferId`, which was awkward and verbose to construct, it simply takes text and a `cx`. It uses the `cx` to derive a `BufferId` from the `EntityId` associated with the `cx`, which should always be positive based on the following analysis... We convert the entity id to a u64 using this method on `EntityId`, which is defined by macros in the `slotmap` crate: ```rust pub fn as_ffi(self) -> u64 { (u64::from(self.version.get()) << 32) | u64::from(self.idx) } ``` If you look at the type of `version` in `KeyData`, it is non-zero: ```rust #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KeyData { idx: u32, version: NonZeroU32, } ``` This commit also adds `Context::reserve_model` and `Context::insert_model` to determine a model's entity ID before it is created, which we need in order to assign a `BufferId` in the background when loading a buffer asynchronously. Release Notes: - N/A --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
parent
664efef76b
commit
7abb63cfda
31 changed files with 376 additions and 519 deletions
|
@ -32,9 +32,9 @@ use crate::{
|
|||
AppMetadata, AssetCache, AssetSource, BackgroundExecutor, ClipboardItem, Context,
|
||||
DispatchPhase, DisplayId, Entity, EventEmitter, ForegroundExecutor, Global, KeyBinding, Keymap,
|
||||
Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point,
|
||||
PromptBuilder, PromptHandle, PromptLevel, Render, RenderablePromptHandle, SharedString,
|
||||
SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, View, ViewContext, Window,
|
||||
WindowAppearance, WindowContext, WindowHandle, WindowId,
|
||||
PromptBuilder, PromptHandle, PromptLevel, Render, RenderablePromptHandle, Reservation,
|
||||
SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, View, ViewContext,
|
||||
Window, WindowAppearance, WindowContext, WindowHandle, WindowId,
|
||||
};
|
||||
|
||||
mod async_context;
|
||||
|
@ -1251,6 +1251,22 @@ impl Context for AppContext {
|
|||
})
|
||||
}
|
||||
|
||||
fn reserve_model<T: 'static>(&mut self) -> Self::Result<Reservation<T>> {
|
||||
Reservation(self.entities.reserve())
|
||||
}
|
||||
|
||||
fn insert_model<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
|
||||
) -> Self::Result<Model<T>> {
|
||||
self.update(|cx| {
|
||||
let slot = reservation.0;
|
||||
let entity = build_model(&mut ModelContext::new(cx, slot.downgrade()));
|
||||
cx.entities.insert(slot, entity)
|
||||
})
|
||||
}
|
||||
|
||||
/// Updates the entity referenced by the given model. The function is passed a mutable reference to the
|
||||
/// entity along with a `ModelContext` for the entity.
|
||||
fn update_model<T: 'static, R>(
|
||||
|
@ -1266,6 +1282,18 @@ impl Context for AppContext {
|
|||
})
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let entity = self.entities.read(handle);
|
||||
read(entity, self)
|
||||
}
|
||||
|
||||
fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
|
@ -1295,18 +1323,6 @@ impl Context for AppContext {
|
|||
})
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let entity = self.entities.read(handle);
|
||||
read(entity, self)
|
||||
}
|
||||
|
||||
fn read_window<T, R>(
|
||||
&self,
|
||||
window: &WindowHandle<T>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue