pub struct DecorationStore { /* private fields */ }Expand description
The tracked-range decoration store: the one store, one mover.
Producers (snippet session, auto-close, find, the compile loop) add/remove/
replace; the commit path calls apply_patch exactly once
per transaction, before change events fire, so every consumer only ever sees
post-edit positions.
Implementations§
Source§impl DecorationStore
impl DecorationStore
Sourcepub fn add_decoration(
&mut self,
range: Range<u32>,
kind: DecorationKind,
stickiness: Stickiness,
) -> DecorationId
pub fn add_decoration( &mut self, range: Range<u32>, kind: DecorationKind, stickiness: Stickiness, ) -> DecorationId
Insert one tracked range and return its fresh id. Producers: the snippet session (stops), auto-close, and find.
The caller supplies current-revision offsets; per-endpoint char-boundary
clipping needs the buffer, so it is the Document’s responsibility, not
this standalone store’s.
Sourcepub fn take_decoration(&mut self, id: DecorationId) -> Option<TrackedRange>
pub fn take_decoration(&mut self, id: DecorationId) -> Option<TrackedRange>
Owner-driven removal (session end, auto-close invalidation): returns the
range if id was present, else None.
Sourcepub fn decoration_range(&self, id: DecorationId) -> Option<Range<u32>>
pub fn decoration_range(&self, id: DecorationId) -> Option<Range<u32>>
The decoration’s current byte range after the mover has ridden it across
edits, or None if the id is gone. The snippet session and find read a
stop’s or match’s live position back through this.
Sourcepub fn set_decoration_stickiness(
&mut self,
id: DecorationId,
s: Stickiness,
) -> bool
pub fn set_decoration_stickiness( &mut self, id: DecorationId, s: Stickiness, ) -> bool
Swap a range’s stickiness — the snippet active-stop swap: AlwaysGrows
onto the newly active stop, NeverGrows onto the leaving one. Returns
false if the id is gone.
Sourcepub fn decorations_in(
&self,
range: Range<u32>,
) -> impl Iterator<Item = TrackedRange>
pub fn decorations_in( &self, range: Range<u32>, ) -> impl Iterator<Item = TrackedRange>
All ranges intersecting range, in ascending (start, id) order.
Touching counts, so a zero-width range on the boundary still renders.
An O(log n + hits) interval descent: a subtree is entered only when it can
hold a touching range — some start ≤ range.end and some end ≥
range.start, read from the relative max_end in its summary — then an
exact per-item touch filter keeps only the real hits. In-order, so the
yield is ascending (start, id).
Sourcepub fn find_count(&self) -> usize
pub fn find_count(&self) -> usize
How many DecorationKind::FindMatch ranges the store holds — an O(1)
read of the root summary, not a whole-store walk.
Sourcepub fn find_rank_before(&self, off: u32) -> usize
pub fn find_rank_before(&self, off: u32) -> usize
How many find matches start strictly before byte offset off — the rank
(0-based document-order index) of the first find at or after off. O(log n)
prefix fold; find navigation uses it to number the current match.
Sourcepub fn nth_find(&self, r: usize) -> Option<(DecorationId, Range<u32>)>
pub fn nth_find(&self, r: usize) -> Option<(DecorationId, Range<u32>)>
The r-th find match in (start, id) order, or None when r >= find_count(). O(log n): FindCountDim seek lands directly on the item
carrying the r-th find increment — since only find matches contribute to
that dimension, the landed item IS the r-th find (a debug_assert pins it).
Sourcepub fn splice_sorted_batch(
&mut self,
spans: &[Range<u32>],
kind: DecorationKind,
stickiness: Stickiness,
) -> Vec<DecorationId>
pub fn splice_sorted_batch( &mut self, spans: &[Range<u32>], kind: DecorationKind, stickiness: Stickiness, ) -> Vec<DecorationId>
Insert an ascending, disjoint spans batch confined to a small window into
its index band WITHOUT rematerializing the store — the windowed sibling of
add_sorted_batch for the per-keystroke find repair. O(band + batch +
log n), mirroring take_matching_in: only the
existing items whose start falls in [spans.first().start, spans.last().start] sit in the touched band; everything outside is SHARED
(Arc clone) and the suffix re-relativizes at one delta-gap seam.
Ids are minted in span order and exceed every existing id, so a tie at a
shared start places the new item AFTER the existing one — byte-identical to
set_sorted. Insertion moves no bytes, so the suffix
reanchor runs with delta = 0.
Sourcepub fn diagnostic_overview(&self, bounds: &[u32], out: &mut Vec<(u8, u32)>)
pub fn diagnostic_overview(&self, bounds: &[u32], out: &mut Vec<(u8, u32)>)
Per bucket b in 0..bounds.len()-1 (ascending offset bounds): the max
Diagnostic severity among the diagnostics starting in [bounds[b], bounds[b+1]) (encoded severity + 1, 1..=4) and the start offset of the
FIRST severest one there — (0, 0) when the bucket holds no diagnostic.
The scrollbar-overview diagnostic lane: O(P + log M) to fold per-bucket max
severity, then O(log M) per non-empty bucket to fetch the winning offset,
so it never scans every diagnostic per frame.
Sourcepub fn find_overview(&self, bounds: &[u32], out: &mut Vec<Option<u32>>)
pub fn find_overview(&self, bounds: &[u32], out: &mut Vec<Option<u32>>)
Per bucket: the start offset of the first DecorationKind::FindMatch
starting in [bounds[b], bounds[b+1]), or None. The overview’s find
lane: O(P·log M) via find_rank_before/nth_find, no whole-store walk.
Sourcepub fn add_sorted_batch(
&mut self,
spans: impl IntoIterator<Item = Range<u32>>,
kind: DecorationKind,
stickiness: Stickiness,
) -> Vec<DecorationId>
pub fn add_sorted_batch( &mut self, spans: impl IntoIterator<Item = Range<u32>>, kind: DecorationKind, stickiness: Stickiness, ) -> Vec<DecorationId>
Batch-insert spans (ascending, one kind/stickiness) and return
the minted ids, in span order — ONE sort-and-rebuild for the whole batch
instead of one per span, so installing a 10k-match find set is a single
sort rather than one per match. The find re-scan installs its whole match
set through this.
Sourcepub fn take_matching_in(
&mut self,
window: Range<u32>,
pred: impl FnMut(&TrackedRange) -> bool,
) -> Vec<TrackedRange>
pub fn take_matching_in( &mut self, window: Range<u32>, pred: impl FnMut(&TrackedRange) -> bool, ) -> Vec<TrackedRange>
Remove — and return, in store order — every range intersecting window
that pred accepts. Find’s per-commit repair drives this with a small
window, so it is windowed: only the decorations that can touch window
sit in the index band [k_lo, k_hi) (starts in [wl, qe], wl the leftmost
touching start), and everything outside is SHARED — a decoration with start
< wl has end < qs so it cannot touch, and start > qe cannot touch either.
Removal keeps positions, so the suffix re-relativizes at one seam
(reanchor with delta = 0). O(band + log n), not O(store).
A whole-store window (a find rescan / clear_autoclose) makes the band the
whole store — O(store) — but those callers are debounced or early-out, not
the per-keystroke path.
Sourcepub fn iter(&self) -> impl Iterator<Item = TrackedRange>
pub fn iter(&self) -> impl Iterator<Item = TrackedRange>
Every tracked range, in ascending (start, id) order — the render path’s
full-store view before it intersects with the visible rows.
Sourcepub fn apply_patch(&mut self, patch: &Patch)
pub fn apply_patch(&mut self, patch: &Patch)
The eager mover: ride every tracked range across patch.
Each endpoint threads through Patch::map_offset with its stickiness
bias (start with the start-bias, end with the end-bias); the range never
inverts (a collapse pins both to the mapped end, via
Patch::map_range). Ranges that collapsed to empty whose kind’s
empty_policy is EmptyPolicy::Drop
are removed, and the store is re-sorted (ties can only reorder at a
shared boundary).
Patch already folds a multi-edit transaction into final post-edit
coordinates, so one map_range per range applies the whole transaction
at once — no back-to-front bookkeeping here (that lives in the patch).
Sourcepub fn set_diagnostics(
&mut self,
revision: u64,
current_revision: u64,
diags: Vec<Diagnostic>,
) -> DiagnosticsOutcome
pub fn set_diagnostics( &mut self, revision: u64, current_revision: u64, diags: Vec<Diagnostic>, ) -> DiagnosticsOutcome
Publish a diagnostic set against the revision it was computed on.
- Revision gate:
revision != current_revision→ returnDiagnosticsOutcome::Stalehaving touched nothing; the previous decorations keep riding edits via stickiness, so squiggles stay glued to their code until the next set arrives. - Wholesale replace: remove every existing
DecorationKind::Diagnosticrange and install the new set withStickiness::NeverGrows; severity, message, and code ride the kind variant. Non-diagnostic decorations (snippet stops, find matches, auto-close) are untouched.
Span clipping and degenerate-span normalization need the buffer, so they
are the Document’s responsibility; this standalone store installs spans
verbatim.
Trait Implementations§
Source§impl Clone for DecorationStore
impl Clone for DecorationStore
Source§fn clone(&self) -> DecorationStore
fn clone(&self) -> DecorationStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more