pub trait BufferStore: Send + Sync {
// Required methods
fn find_by_name(&self, name: &str) -> Option<BufferId>;
fn handle_for(&self, id: BufferId) -> Option<Arc<dyn Document>>;
fn name_for(&self, id: BufferId) -> Option<String>;
fn insert_document_buffer(
&self,
id: BufferId,
kind: BufferKind,
handle: Arc<dyn Document>,
flags: BufferFlags,
name: Option<String>,
);
// Provided methods
fn path_for(&self, _id: BufferId) -> Option<PathBuf> { ... }
fn contains_buffer(&self, id: BufferId) -> bool { ... }
}Expand description
Host-implemented trait. The renderer crate provides an impl that wraps the App’s buffer registry + mode-activation state.
Methods take &self and must be safe to call from any thread
(the impl is responsible for synchronisation).
Required Methods§
Sourcefn find_by_name(&self, name: &str) -> Option<BufferId>
fn find_by_name(&self, name: &str) -> Option<BufferId>
Look up the buffer id whose name matches exactly.
Returns None when no buffer with that synthetic name is
registered yet.
Sourcefn handle_for(&self, id: BufferId) -> Option<Arc<dyn Document>>
fn handle_for(&self, id: BufferId) -> Option<Arc<dyn Document>>
Get a clone of the Arc<dyn Document> for id,
suitable for holding across thread boundaries. M.0: the
return type is the polymorphic shape so the same
surface serves both regular-document handles and (M.1+)
multibuffer handles uniformly. The handle is the only
way for a mode-owned background task to write into the
buffer (handle.apply_edit_batch(...)).
None when id is not a Document in the registry.
Sourcefn name_for(&self, id: BufferId) -> Option<String>
fn name_for(&self, id: BufferId) -> Option<String>
Read the buffer’s synthetic name. None when the buffer is
unnamed (the default for path-less scratch documents) or
when id is not registered. B’.7: lets a mode derive its
own identity from the buffer it’s attached to without the
host having to seed a buffer-local first.
Sourcefn insert_document_buffer(
&self,
id: BufferId,
kind: BufferKind,
handle: Arc<dyn Document>,
flags: BufferFlags,
name: Option<String>,
)
fn insert_document_buffer( &self, id: BufferId, kind: BufferKind, handle: Arc<dyn Document>, flags: BufferFlags, name: Option<String>, )
H.1 (2026-05-31): generic Document-shaped buffer
insertion. Used by extension crates (lattice-multibuffer
today; future plugin-defined Document-shaped kinds) to
push a BufferEntry into the registry without host
knowing the kind exists.
kind must be a Document-shaped kind whose payload is an
Arc<dyn Document>: today BufferKind::Document /
BufferKind::Messages / BufferKind::Multibuffer. For
other kinds (FileTree, Oil, Terminal, Help) the
payload is structurally different and they keep their
host-internal insertion paths until the v2 plugin-
architecture work designs the generic extension point
(per docs/dev/architecture/kind-agnostic-buffers.md
§8 Q2).
Idempotent: if id is already registered the call is a
no-op (consistent with the named-singleton create seam,
crate::ModeActivator::ensure_named_document). The caller is
responsible for allocating id via BufferId::next() first.
Errors fold into the impl’s logging path (e.g. the
lattice-host impl logs through tracing and emits a
host-side message); the trait surface is infallible
because every error here is a programmer error (wrong
kind, duplicate id) and there’s no recovery path the
caller could enact.
Provided Methods§
Sourcefn path_for(&self, _id: BufferId) -> Option<PathBuf>
fn path_for(&self, _id: BufferId) -> Option<PathBuf>
Read the buffer’s on-disk file path, if it has one. None
for path-less/synthetic buffers or when id is not
registered. Default None so existing implementors (e.g.
NullBufferStore) don’t need updating for this addition.
Sourcefn contains_buffer(&self, id: BufferId) -> bool
fn contains_buffer(&self, id: BufferId) -> bool
Is id a buffer this store knows about at all?
The existence oracle, and the reason it is a method rather than a
composition of the three above: every one of them returns None for
two different reasons — “no such buffer” and “that buffer has no
name / no path / no document handle” — so none of them can answer this
question, and a caller that picks one is really asking something else.
name_for is the specific trap. It is the SYNTHETIC-name slot, so it
answers None for every ordinary file-backed buffer; a caller using it
as an existence check refuses exactly the buffers a user actually edits.
The plugin project seam did that, and the project plugin was dead in
the real editor as a result — every document-opened resolved to none
and :project-switch reported “no projects remembered yet” forever,
while its tests passed against a stub that answered Some for a
file-backed buffer.
The default composes what the trait already offers, so no implementor breaks; it is best-effort and a store that can answer exactly — the host registry can, it has the map — should override. What the default cannot see is a registered buffer with no name, no path and no document handle, which it reports as absent.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".