pub struct Rope<M>{ /* private fields */ }Expand description
A rope of elements that are Measurable.
The time complexity of nearly all edit and query operations on Rope<M>
are worst-case O(log N) in the length of the rope. Rope<M> is designed
to work efficiently even for huge (in the gigabytes) arrays of
M.
In the examples below, a struct called Width will be used
in order to demonstrate AnyRope’s features.
§Editing Operations
The primary editing operations on Rope<M> are insertion and removal of
slices or individual elements.
For example:
let mut rope = Rope::from_slice(&[
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
]);
rope.remove_inclusive(6..8, usize::cmp);
rope.insert(6, Width(5), usize::cmp);
assert_eq!(
rope,
[Width(1), Width(2), Width(3), Width(5), Width(1)].as_slice()
);§Query Operations
Rope<M> gives you the ability to query an element at any given index or
measure, and the convertion between the two. You can either convert an index
to a measure, or convert the measure at the start or end of an element to an
index. For example:
let rope = Rope::from_slice(&[
Width(0),
Width(0),
Width(1),
Width(1),
Width(2),
Width(25),
Width(0),
Width(0),
Width(1),
]);
// `start_measure_to_index()` will pick the first element that starts at the given index.
assert_eq!(rope.start_measure_to_index(0, usize::cmp), 0);
// `end_measure_to_index()` will pick the last element that still starts at the given index.
assert_eq!(rope.end_measure_to_index(0, usize::cmp), 2);
assert_eq!(rope.start_measure_to_index(2, usize::cmp), 4);
assert_eq!(rope.start_measure_to_index(3, usize::cmp), 4);
assert_eq!(rope.start_measure_to_index(16, usize::cmp), 5);
assert_eq!(rope.start_measure_to_index(29, usize::cmp), 6);§Slicing
You can take immutable slices of a Rope<M> using
measure_slice()
or index_slice():
let mut rope = Rope::from_slice(&[
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
]);
let measure_slice = rope.measure_slice(3..6, usize::cmp);
let index_slice = rope.index_slice(2..5);
assert_eq!(measure_slice, index_slice);§Cloning
Cloning Rope<M>s is extremely cheap, running in O(1) time and taking a
small constant amount of memory for the new clone, regardless of slice size.
This is accomplished by data sharing between Rope<M> clones. The memory
used by clones only grows incrementally as the their contents diverge due
to edits. All of this is thread safe, so clones can be sent freely
between threads.
The primary intended use-case for this feature is to allow asynchronous
processing of Rope<M>s.
Implementations§
Source§impl<M> Rope<M>
impl<M> Rope<M>
Sourcepub fn from_slice(slice: &[M]) -> Self
pub fn from_slice(slice: &[M]) -> Self
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Total size of the Rope<M>’s buffer space.
This includes unoccupied buffer space. You can calculate
the unoccupied space with Rope::capacity() - Rope::len(). In general,
there will always be some unoccupied buffer space.
Runs in O(N) time.
Sourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
Shrinks the Rope<M>’s capacity to the minimum possible.
This will rarely result in Rope::capacity() == Rope::len().
Rope<M> stores Ms in a sequence of
fixed-capacity chunks, so an exact fit only happens for lists of a
lenght that is a multiple of that capacity.
After calling this, the difference between capacity() and
len() is typically under 1000 for each 1000000 M in
the Rope<M>.
NOTE: calling this on a Rope<M> clone causes it to stop sharing
all data with its other clones. In such cases you will very likely
be increasing total memory usage despite shrinking the Rope<M>’s
capacity.
Runs in O(N) time, and uses O(log N) additional space during shrinking.
Sourcepub fn insert_slice(
&mut self,
measure: M::Measure,
slice: &[M],
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
)
pub fn insert_slice( &mut self, measure: M::Measure, slice: &[M], cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, )
Sourcepub fn insert(
&mut self,
measure: M::Measure,
measurable: M,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
)
pub fn insert( &mut self, measure: M::Measure, measurable: M, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, )
Sourcepub fn remove_inclusive(
&mut self,
range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
)
pub fn remove_inclusive( &mut self, range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, )
Removes the slice in the given measure range.
Uses range syntax, e.g. 2..7, 2.., etc.
Runs in O(M + log N) time, where N is the length of the Rope<M> and
M is the length of the range being removed.
The first removed M will be the first with a end measure
sum greater than the starting bound if its
measure() is greater than 0, or equal to the
starting bound if its measure() is equal to 0.
The last removed M will be the first with a start
measure sum greater than the ending bound if its
measure() is greater than 0, or the last one
with a start measure sum equal to the ending bound if its
measure() is equal to 0.
In essence, this means the following:
- A range starting between a
M’s start and end measure sums will remove saidM. - A range ending in the start of a list of 0 measure
Ms will remove all of them. - An empty range that starts and ends in a list of 0 measure
Ms will remove all of them, and nothing else. This contrasts with Rust’s usual definition of an empty range.
§Examples
let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// Removing in the middle of `Width(3)`.
rope.remove_inclusive(5.., usize::cmp);
assert_eq!(rope, [Width(1), Width(2)].as_slice());let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// End bound coincides with a 0 measure list.
rope.remove_inclusive(1..6, usize::cmp);
assert_eq!(rope, [Width(1), Width(2), Width(1)].as_slice());let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// Empty range at the start of a 0 measure list.
rope.remove_inclusive(6..6, usize::cmp);
// Inclusively removing an empty range does nothing.
assert_eq!(
rope,
[Width(1), Width(2), Width(3), Width(2), Width(1)].as_slice()
);§Panics
Panics if the start of the range is greater than the end, or if the
end is out of bounds (i.e. end > self.measure()).
Sourcepub fn remove_exclusive(
&mut self,
range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
)
pub fn remove_exclusive( &mut self, range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, )
Same as remove_inclusive(), but keeps
elements measure measure equal to 0 at the edges.
If the measure_range doesn’t cover the entire measure of a single
M, then the removal does nothing.
§Examples
let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// End bound coincides with a 0 measure list, which does not get removed.
rope.remove_exclusive(1..6, usize::cmp);
assert_eq!(
rope,
[Width(1), Width(0), Width(0), Width(2), Width(1)].as_slice()
);let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// Empty range at the start of a 0 measure list.
rope.remove_exclusive(6..6, usize::cmp);
// Exclusively removing an empty range does nothing.
assert_eq!(rope, array.as_slice());let array = [
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
];
let mut rope = Rope::from_slice(&array);
// Removing in the middle of `Width(3)`.
rope.remove_exclusive(5..6, usize::cmp);
// Exclusively removing in the middle of an element does nothing.
assert_eq!(rope, array.as_slice());§Panics
Panics if the start of the range is greater than the end, or if the
end is out of bounds (i.e. end > self.measure()).
Sourcepub fn split_off(
&mut self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Self
pub fn split_off( &mut self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Self
Sourcepub fn index_to_measure(&self, index: usize) -> M::Measure
pub fn index_to_measure(&self, index: usize) -> M::Measure
Returns the measure sum at the start of the given index.
Notes:
Runs in O(log N) time.
§Panics
Panics if the index is out of bounds (i.e. index > Rope::len()).
Sourcepub fn start_measure_to_index(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> usize
pub fn start_measure_to_index( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> usize
Returns an index, given a starting measure sum.
Runs in O(log N) time.
§Panics
Panics if the measure is out of bounds (i.e. measure > Rope::measure()).
Sourcepub fn end_measure_to_index(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> usize
pub fn end_measure_to_index( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> usize
Returns an index, given an ending measure sum.
Runs in O(log N) time.
§Panics
Panics if the measure is out of bounds (i.e. measure > Rope::measure()).
Sourcepub fn from_index(&self, index: usize) -> (M::Measure, M)
pub fn from_index(&self, index: usize) -> (M::Measure, M)
Sourcepub fn from_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> (M::Measure, M)
pub fn from_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> (M::Measure, M)
Sourcepub fn chunk_at_index(&self, index: usize) -> (&[M], usize, M::Measure)
pub fn chunk_at_index(&self, index: usize) -> (&[M], usize, M::Measure)
Returns the chunk containing the given index.
Also returns the index and widht of the beginning of the chunk.
Note: for convenience, a one-past-the-end index returns the last
chunk of the RopeSlice.
The return value is organized as
(chunk, chunk_index, chunk_measure).
Runs in O(log N) time.
§Panics
Panics if the index is out of bounds (i.e. index > Rope::len()).
Sourcepub fn chunk_at_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> (&[M], usize, M::Measure)
pub fn chunk_at_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> (&[M], usize, M::Measure)
Returns the chunk containing the given measure.
Also returns the index and measure of the beginning of the chunk.
Note: for convenience, a one-past-the-end measure returns the last
chunk of the RopeSlice.
The return value is organized as
(chunk, chunk_index, chunk_measure).
Runs in O(log N) time.
§Panics
Panics if the measure is out of bounds (i.e. measure > Rope::measure()).
Sourcepub fn measure_slice(
&self,
measure_range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> RopeSlice<'_, M>
pub fn measure_slice( &self, measure_range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> RopeSlice<'_, M>
Gets an immutable slice of the Rope<M>, using a measure range.
Uses range syntax, e.g. 2..7, 2.., etc.
§Example
let mut rope = Rope::from_slice(&[
Width(1),
Width(2),
Width(3),
Width(0),
Width(0),
Width(2),
Width(1),
]);
let slice = rope.measure_slice(..5, usize::cmp);
assert_eq!(slice, [Width(1), Width(2), Width(3)].as_slice());Runs in O(log N) time.
§Panics
Panics if the start of the range is greater than the end, or if the
end is out of bounds (i.e. end > Rope::measure()).
Sourcepub fn index_slice(
&self,
index_range: impl RangeBounds<usize>,
) -> RopeSlice<'_, M>
pub fn index_slice( &self, index_range: impl RangeBounds<usize>, ) -> RopeSlice<'_, M>
Sourcepub fn iter_at_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Iter<'_, M> ⓘ
pub fn iter_at_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Iter<'_, M> ⓘ
Creates an iterator over the Rope<M>, starting at measure.
This iterator will return values of type Option<(usize, M)>, where
the usize is the measure where the given M starts.
Since one can iterate in between an Ms start and end
measure sums. the first usize may not actually corelate to the
measure given to the function.
If measure == Rope::measure() then an iterator at the end of the
Rope<M> is created (i.e. next() will
return None).
Runs in O(log N) time.
§Panics
Panics if the measure is out of bounds (i.e. measure > Rope::measure()).
Sourcepub fn chunks(&self) -> Chunks<'_, M> ⓘ
pub fn chunks(&self) -> Chunks<'_, M> ⓘ
Creates an iterator over the chunks of the Rope<M>.
Runs in O(log N) time.
Sourcepub fn chunks_at_index(
&self,
index: usize,
) -> (Chunks<'_, M>, usize, M::Measure)
pub fn chunks_at_index( &self, index: usize, ) -> (Chunks<'_, M>, usize, M::Measure)
Creates an iterator over the chunks of the Rope<M>, with the
iterator starting at the chunk containing the index.
Also returns the index and measure of the beginning of the first chunk to be yielded.
If index == Rope::len() an iterator at the end of the Rope<M>
(yielding None on a call to next()) is
created.
The return value is organized as (iterator, chunk_index, chunk_measure).
Runs in O(log N) time.
§Panics
Panics if the index is out of bounds (i.e. index > Rope::len()).
Sourcepub fn chunks_at_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> (Chunks<'_, M>, usize, M::Measure)
pub fn chunks_at_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> (Chunks<'_, M>, usize, M::Measure)
Creates an iterator over the chunks of the Rope<M>, with the
iterator starting at the chunk containing the measure.
Also returns the index and measure of the beginning of the first chunk to be yielded.
If measure == Rope::measure() an iterator at the end of the
Rope<M> (yielding None on a call to
next()) is created.
The return value is organized as (iterator, chunk_index, chunk_measure).
Runs in O(log N) time.
§Panics
Panics if the measure is out of bounds (i.e. measure > Rope::measure()).
Sourcepub fn is_instance(&self, other: &Self) -> bool
pub fn is_instance(&self, other: &Self) -> bool
Returns true if this rope and other point to precisely the same
in-memory data.
This happens when one of the ropes is a clone of the other and neither have been modified since then. Because clones initially share all the same data, it can be useful to check if they still point to precisely the same memory as a way of determining whether they are both still unmodified.
Note: this is distinct from checking for equality: two ropes can have the same contents (equal) but be stored in different memory locations (not instances). Importantly, two clones that post-cloning are modified identically will not be instances anymore, even though they will have equal contents.
Runs in O(1) time.
Source§impl<M> Rope<M>
impl<M> Rope<M>
Sourcepub fn try_insert_slice(
&mut self,
measure: M::Measure,
slice: &[M],
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<(), M>
pub fn try_insert_slice( &mut self, measure: M::Measure, slice: &[M], cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<(), M>
Non-panicking version of insert().
Sourcepub fn try_insert(
&mut self,
measure: M::Measure,
measurable: M,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<(), M>
pub fn try_insert( &mut self, measure: M::Measure, measurable: M, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<(), M>
Non-panicking version of insert().
Sourcepub fn try_remove_inclusive(
&mut self,
range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<(), M>
pub fn try_remove_inclusive( &mut self, range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<(), M>
Non-panicking version of remove_inclusive().
Sourcepub fn try_remove_exclusive(
&mut self,
range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<(), M>
pub fn try_remove_exclusive( &mut self, range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<(), M>
Non-panicking version of remove_exclusive().
Sourcepub fn try_split_off(
&mut self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<Self, M>
pub fn try_split_off( &mut self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<Self, M>
Non-panicking version of split_off().
Sourcepub fn try_index_to_measure(&self, index: usize) -> Result<M::Measure, M>
pub fn try_index_to_measure(&self, index: usize) -> Result<M::Measure, M>
Non-panicking version of index_to_measure().
Sourcepub fn try_start_measure_to_index(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<usize, M>
pub fn try_start_measure_to_index( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<usize, M>
Non-panicking version of
start_measure_to_index().
Sourcepub fn try_end_measure_to_index(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<usize, M>
pub fn try_end_measure_to_index( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<usize, M>
Non-panicking version of
end_measure_to_index().
Sourcepub fn get_from_index(&self, index: usize) -> Option<(M::Measure, M)>
pub fn get_from_index(&self, index: usize) -> Option<(M::Measure, M)>
Non-panicking version of from_index().
Sourcepub fn get_from_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Option<(M::Measure, M)>
pub fn get_from_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Option<(M::Measure, M)>
Non-panicking version of from_measure().
Sourcepub fn get_chunk_at_index(
&self,
index: usize,
) -> Option<(&[M], usize, M::Measure)>
pub fn get_chunk_at_index( &self, index: usize, ) -> Option<(&[M], usize, M::Measure)>
Non-panicking version of chunk_at_index().
Sourcepub fn get_chunk_at_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Option<(&[M], usize, M::Measure)>
pub fn get_chunk_at_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Option<(&[M], usize, M::Measure)>
Non-panicking version of chunk_at_measure().
Sourcepub fn get_measure_slice(
&self,
range: impl MeasureRange<M>,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Result<RopeSlice<'_, M>, M>
pub fn get_measure_slice( &self, range: impl MeasureRange<M>, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Result<RopeSlice<'_, M>, M>
Non-panicking version of measure_slice().
Sourcepub fn get_index_slice(
&self,
index_range: impl RangeBounds<usize>,
) -> Option<RopeSlice<'_, M>>
pub fn get_index_slice( &self, index_range: impl RangeBounds<usize>, ) -> Option<RopeSlice<'_, M>>
Non-panicking version of index_slice().
Sourcepub fn get_iter_at_measure(
&self,
measure: M::Measure,
cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
) -> Option<Iter<'_, M>>
pub fn get_iter_at_measure( &self, measure: M::Measure, cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, ) -> Option<Iter<'_, M>>
Non-panicking version of iter_at_measure().
Sourcepub fn get_chunks_at_index(
&self,
index: usize,
) -> Option<(Chunks<'_, M>, usize, M::Measure)>
pub fn get_chunks_at_index( &self, index: usize, ) -> Option<(Chunks<'_, M>, usize, M::Measure)>
Non-panicking version of chunks_at_index().
Trait Implementations§
Source§impl<'a, M> From<RopeSlice<'a, M>> for Rope<M>
Will share data where possible.
impl<'a, M> From<RopeSlice<'a, M>> for Rope<M>
Will share data where possible.
Runs in O(log N) time.