Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/rope/rope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,27 @@ impl Rope {
is_grapheme_boundary(self.chunks(), self.byte_len(), byte_offset)
}

/// 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.
#[inline]
pub fn is_instance(&self, other: &Self) -> bool {
self.tree.is_instance(&other.tree)
}

/// Returns the line at `line_index`, without its line terminator.
///
/// If you want to include the line break consider taking a
Expand Down
6 changes: 6 additions & 0 deletions src/tree/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ impl<const ARITY: usize, L: Leaf> Tree<ARITY, L> {
Self { root: Arc::new(Node::Internal(root)) }
}

/// Returns `true` if the two roots point to the same allocation.
#[inline]
pub fn is_instance(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.root, &other.root)
}

/// Returns the leaf containing the `measure`-th unit of the `M`-metric,
/// plus the `M`-measure of all the leaves before it.
#[inline]
Expand Down
18 changes: 18 additions & 0 deletions tests/rope_indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ fn rope_is_char_boundary() {
}
}

#[cfg_attr(miri, ignore)]
#[test]
fn rope_is_instance() {
let r = Rope::from("Hello there!");
let mut c1 = r.clone();
let c2 = c1.clone();

assert!(r.is_instance(&c1));
assert!(r.is_instance(&c2));
assert!(c1.is_instance(&c2));

c1.insert(0, "Oh! ");

assert!(!r.is_instance(&c1));
assert!(r.is_instance(&c2));
assert!(!c1.is_instance(&c2));
}

/// ```
/// Root
/// ├───┐
Expand Down