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:
Nathan Sobo 2024-04-10 07:32:51 -07:00 committed by GitHub
parent 664efef76b
commit 7abb63cfda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 376 additions and 519 deletions

View file

@ -165,6 +165,19 @@ pub trait Context {
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>;
/// Reserve a slot for a model to be inserted later.
/// The returned [Reservation] allows you to obtain the [EntityId] for the future model.
fn reserve_model<T: 'static>(&mut self) -> Self::Result<Reservation<T>>;
/// Insert a new model in the app context based on a [Reservation] previously obtained from [`reserve_model`].
///
/// [`reserve_model`]: Self::reserve_model
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>;
/// Update a model in the app context.
fn update_model<T, R>(
&mut self,
@ -198,6 +211,17 @@ pub trait Context {
T: 'static;
}
/// Returned by [Context::reserve_model] to later be passed to [Context::insert_model].
/// Allows you to obtain the [EntityId] for a model before it is created.
pub struct Reservation<T>(pub(crate) Slot<T>);
impl<T: 'static> Reservation<T> {
/// Returns the [EntityId] that will be associated with the model once it is inserted.
pub fn entity_id(&self) -> EntityId {
self.0.entity_id()
}
}
/// This trait is used for the different visual contexts in GPUI that
/// require a window to be present.
pub trait VisualContext: Context {