Skip to content

Commit

Permalink
Add _finish_no_fix() to RopeBuilder, for use in internal testing.
Browse files Browse the repository at this point in the history
  • Loading branch information
cessen committed Nov 7, 2022
1 parent 3f2ff15 commit 69cfb1e
Showing 1 changed file with 48 additions and 28 deletions.
76 changes: 48 additions & 28 deletions src/rope_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,6 @@ impl RopeBuilder {
self.append_internal(chunk, false);
}

/// NOT PART OF THE PUBLIC API (hidden from docs for a reason!).
///
/// Appends `contents` to the in-progress rope as a single leaf
/// node (chunk). This is useful for building ropes with specific
/// chunk configurations for testing purposes. It will happily append
/// both empty and more-than-max-size chunks.
///
/// This makes no attempt to be consistent with the standard `append()`
/// method, and should not be used in conjunction with it.
#[doc(hidden)]
pub fn _append_chunk(&mut self, contents: &str) {
self.append_leaf_node(Arc::new(Node::Leaf(NodeText::from_str(contents))));
}

/// Finishes the build, and returns the `Rope`.
///
/// Note: this method consumes the builder. If you want to continue
Expand All @@ -92,7 +78,7 @@ impl RopeBuilder {
pub fn finish(mut self) -> Rope {
// Append the last leaf
self.append_internal("", true);
self.finish_internal()
self.finish_internal(true)
}

/// Builds a rope all at once from a single string slice.
Expand All @@ -102,7 +88,31 @@ impl RopeBuilder {
/// Rope::from_str(), which actually uses this for its implementation.
pub(crate) fn build_at_once(mut self, chunk: &str) -> Rope {
self.append_internal(chunk, true);
self.finish_internal()
self.finish_internal(true)
}

/// NOT PART OF THE PUBLIC API (hidden from docs for a reason!).
///
/// Appends `contents` to the in-progress rope as a single leaf
/// node (chunk). This is useful for building ropes with specific
/// chunk configurations for testing purposes. It will happily append
/// both empty and more-than-max-size chunks.
///
/// This makes no attempt to be consistent with the standard `append()`
/// method, and should not be used in conjunction with it.
#[doc(hidden)]
pub fn _append_chunk(&mut self, contents: &str) {
self.append_leaf_node(Arc::new(Node::Leaf(NodeText::from_str(contents))));
}

/// NOT PART OF THE PUBLIC API (hidden from docs for a reason!).
///
/// Finishes the build without doing any tree fixing to adhere
/// to the btree invariants. To be used with `_append_chunk()` to
/// construct ropes with specific chunk boundaries for testing.
#[doc(hidden)]
pub fn _finish_no_fix(self) -> Rope {
self.finish_internal(false)
}

//-----------------------------------------------------------------
Expand Down Expand Up @@ -136,7 +146,11 @@ impl RopeBuilder {
}

// Internal workings of `finish()`.
fn finish_internal(mut self) -> Rope {
//
// When `fix_tree` is false, the resulting node tree is NOT fixed up
// to adhere to the btree invariants. This is useful for some testing
// code. But generally, `fix_tree` should be set to true.
fn finish_internal(mut self, fix_tree: bool) -> Rope {
// Zip up all the remaining nodes on the stack
let mut stack_idx = self.stack.len() - 1;
while stack_idx >= 1 {
Expand All @@ -150,19 +164,25 @@ impl RopeBuilder {
stack_idx -= 1;
}

// Get root and fix any right-side nodes with too few children or.
let mut root = self.stack.pop().unwrap();
Arc::make_mut(&mut root).zip_fix_right();
// Create the rope.
let mut rope = Rope {
root: self.stack.pop().unwrap(),
};

// Create the rope, make sure it's well-formed, and return it.
let mut rope = Rope { root: root };
if self.last_chunk_len_bytes < MIN_BYTES && self.last_chunk_len_bytes != rope.len_bytes() {
// Merge the last chunk if it was too small.
let idx =
rope.len_chars() - rope.byte_to_char(rope.len_bytes() - self.last_chunk_len_bytes);
Arc::make_mut(&mut rope.root).fix_tree_seam(idx);
// Fix up the tree to be well-formed.
if fix_tree {
Arc::make_mut(&mut rope.root).zip_fix_right();
if self.last_chunk_len_bytes < MIN_BYTES
&& self.last_chunk_len_bytes != rope.len_bytes()
{
// Merge the last chunk if it was too small.
let idx = rope.len_chars()
- rope.byte_to_char(rope.len_bytes() - self.last_chunk_len_bytes);
Arc::make_mut(&mut rope.root).fix_tree_seam(idx);
}
rope.pull_up_singular_nodes();
}
rope.pull_up_singular_nodes();

return rope;
}

Expand Down

0 comments on commit 69cfb1e

Please sign in to comment.