├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE.md ├── README.md ├── rustfmt.toml ├── src ├── iter.rs ├── lib.rs ├── rope.rs ├── rope_builder.rs ├── slice.rs ├── slice_utils.rs └── tree │ ├── branch_children.rs │ ├── leaf_slice.rs │ ├── mod.rs │ ├── node.rs │ └── slice_info.rs └── tests ├── fix_tree.rs ├── from_slice.rs └── shrink_to_fit.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | schedule: 9 | # Every-other month, to make sure new Rust 10 | # releases don't break things. 11 | - cron: '15 12 5 1,3,5,7,9,11 *' 12 | 13 | env: 14 | CARGO_TERM_COLOR: always 15 | 16 | jobs: 17 | build-and-test-stable: 18 | name: Build and test, Rust-nightly 19 | runs-on: ubuntu-latest 20 | steps: 21 | # Get a checkout and rust toolchain. 22 | - uses: actions/checkout@v2 23 | - uses: actions-rs/toolchain@v1 24 | with: 25 | profile: minimal 26 | toolchain: nightly 27 | override: true 28 | 29 | # Build and test 30 | - run: cargo +nightly build 31 | - run: cargo +nightly test 32 | 33 | run-miri: 34 | name: Run Miri 35 | runs-on: ubuntu-latest 36 | steps: 37 | # Get a checkout and rust toolchain. 38 | - uses: actions/checkout@v2 39 | - uses: hecrj/setup-rust-action@v1 40 | with: 41 | rust-version: nightly 42 | components: miri 43 | 44 | # Build and test 45 | # --no-default-features to get rid of the simd feature 46 | - run: cargo miri test 47 | env: 48 | MIRIFLAGS: "-Zmiri-strict-provenance" 49 | 50 | clippy: 51 | name: Run Clippy 52 | runs-on: ubuntu-latest 53 | steps: 54 | - uses: actions/checkout@v1 55 | - uses: actions-rs/toolchain@v1 56 | with: 57 | toolchain: nightly 58 | components: clippy 59 | override: true 60 | - uses: actions-rs/clippy@master 61 | with: 62 | args: --all-features --all-targets 63 | 64 | 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | perf.data* 5 | cachegrind.out* 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "any-rope" 3 | version = "1.2.5" 4 | authors = ["Mateus Yoshiaki "] 5 | description = "A fast and robust arbitrary rope for Rust. Based on Ropey." 6 | documentation = "https://docs.rs/any-rope" 7 | repository = "https://github.com/AhoyISki/AnyRope" 8 | readme = "README.md" 9 | license = "MIT" 10 | keywords = ["rope", "data", "edit", "buffer"] 11 | categories = ["data-structures"] 12 | exclude = ["/.github/*"] 13 | edition = "2021" 14 | 15 | [dependencies] 16 | smallvec = "^1.10.0" 17 | 18 | [dev-dependencies] 19 | rand = "^0.8" 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Nathan Vegdahl 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AnyRope 2 | 3 | [![CI Build Status][github-ci-img]][github-ci] 4 | [![Latest Release][crates-io-badge]][crates-io-url] 5 | [![Documentation][docs-rs-img]][docs-rs-url] 6 | 7 | AnyRope is an arbitrary data type rope for Rust, designed for similar operations 8 | that a rope would do, but targeted at data types that are not text. 9 | 10 | 11 | ## Example Usage 12 | 13 | An example of where this would be useful is in the tagging of text in a text editor, 14 | for example, one may assossiate a rope of text with a rope of tags. 15 | 16 | ```rust 17 | // The tags that will be assossiated with a piece of text, that could be a rope. 18 | #[derive(Clone, Copy, PartialEq, Eq)] 19 | enum Tag { 20 | PrintRed, 21 | Underline, 22 | Normal, 23 | Skip(usize) 24 | } 25 | 26 | use Tag::*; 27 | 28 | impl any_rope::Measurable for Tag { 29 | type Measure = usize; 30 | 31 | fn measure(&self) -> Self::Measure { 32 | match self { 33 | // The zero here represents the fact that multiple tags may be placed 34 | // in the same character. 35 | PrintRed | Underline | Normal => 0, 36 | // Skip here is an amount of characters with no tags in them. 37 | Skip(amount) => *amount 38 | } 39 | } 40 | } 41 | 42 | // An `&str` that will be colored. 43 | let my_str = "This word will be red!"; 44 | 45 | // Here's what this means: 46 | // - Skip 5 characters; 47 | // - Change the color to red; 48 | // - Skip 4 characters; 49 | // - Change the rendering back to normal. 50 | let mut tags = any_rope::Rope::from_slice(&[Skip(5), PrintRed, Skip(4), Normal]); 51 | // Do note that Tag::Skip only represents characters because we are also iterating 52 | // over a `Chars` iterator, and have chosen to do so. 53 | 54 | // An empty range, when used in an inclusive removal 55 | // will remove all 0 width elements in that specific 56 | // width. `Rope::remove_exclusive()` would keep them. 57 | // In this case, that would be `Tag::PrintRed` 58 | // 59 | // The reason why we need to pass in a comparison 60 | // function is because of the flexibility of the 61 | // `Measurable::Measure` type. By passing various 62 | // types of comparison functions, we can selectively 63 | // choose what we are looking for. This is similar to 64 | // what regular ropes do when searching within text, 65 | // the end user can search by byte, char, line, etc. 66 | tags.remove_inclusive(5..5, usize::cmp); 67 | // In place of that `Tag::PrintRed`, we will insert `Tag::Underline`. 68 | tags.insert(5, Underline, usize::cmp); 69 | 70 | // The AnyRope iterator not only returns the element in question, but also the width 71 | // where it starts. 72 | let mut tags_iter = tags.iter().peekable(); 73 | 74 | for (cur_index, ch) in my_str.chars().enumerate() { 75 | // The while let loop here is a useful way to activate all tags within the same 76 | // character. For example, we could have a sequence of [Tag::UnderLine, Tag::PrintRed] 77 | // in the `Rope`, both of which have a width of 0, allowing one to execute multiple 78 | // `Tag`s in a single character. 79 | while let Some((index, tag)) = tags_iter.peek() { 80 | if *index == cur_index { 81 | activate_tag(tag); 82 | tags_iter.next(); 83 | } else { 84 | break; 85 | } 86 | } 87 | print!("{}", ch); 88 | } 89 | ``` 90 | 91 | ## When Should I Use AnyRope? 92 | 93 | So far, I haven't found a use for AnyRope, other than text editors, but I'm not 94 | discounting the possibility that it may be useful somewhere else. 95 | 96 | ## Features 97 | 98 | ### Concept of widths 99 | 100 | The width of the element that implements Measurable can be whatever the end user wants 101 | it to be, allowing for great flexibility in how AnyRope could be useful. 102 | 103 | ### Rope slices 104 | 105 | AnyRope has rope slices that allow you to work with just parts of a rope, using 106 | all the read-only operations of a full rope including iterators and making 107 | sub-slices. 108 | 109 | ### Flexible APIs with low-level access 110 | 111 | Although AnyRope is intentionally limited in scope, it also provides APIs for 112 | efficiently accessing and working with its internal slice chunk 113 | representation, allowing additional functionality to be efficiently 114 | implemented by client code with minimal overhead. 115 | 116 | ### Thread safe 117 | 118 | AnyRope ensures that even though clones share memory, everything is thread-safe. 119 | Clones can be sent to other threads for both reading and writing. 120 | 121 | ## Unsafe code 122 | 123 | AnyRope uses unsafe code to help achieve some of its space and performance 124 | characteristics. Although effort has been put into keeping the unsafe code 125 | compartmentalized and making it correct, please be cautious about using AnyRope 126 | in software that may face adversarial conditions. 127 | 128 | ## License 129 | 130 | AnyRope is licensed under the MIT license (LICENSE.md or http://opensource.org/licenses/MIT) 131 | 132 | ## Contributing 133 | 134 | Contributions are absolutely welcome! However, please open an issue or email 135 | me to discuss larger changes, to avoid doing a lot of work that may get 136 | rejected. 137 | 138 | Unless you explicitly state otherwise, any contribution intentionally 139 | submitted for inclusion in AnyRope by you will be licensed as above, 140 | without any additional terms or conditions. 141 | 142 | [crates-io-badge]: https://img.shields.io/crates/v/any-rope.svg 143 | [crates-io-url]: https://crates.io/crates/any-rope 144 | [github-ci-img]: https://github.com/AhoyISki/AnyRope/actions/workflows/ci.yml/badge.svg 145 | [github-ci]: https://github.com/AhoyISki/AnyRope/actions/workflows/ci.yml 146 | [docs-rs-img]: https://docs.rs/any-rope/badge.svg 147 | [docs-rs-url]: https://docs.rs/any-rope 148 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 100 2 | hard_tabs = false 3 | tab_spaces = 4 4 | newline_style = "Auto" 5 | indent_style = "Block" 6 | use_small_heuristics = "Default" 7 | fn_call_width = 60 8 | attr_fn_like_width = 70 9 | struct_lit_width = 18 10 | struct_variant_width = 35 11 | array_width = 60 12 | chain_width = 60 13 | single_line_if_else_max_width = 50 14 | single_line_let_else_max_width = 50 15 | wrap_comments = true 16 | format_code_in_doc_comments = true 17 | doc_comment_code_block_width = 80 18 | comment_width = 80 19 | normalize_comments = true 20 | normalize_doc_attributes = true 21 | format_strings = true 22 | format_macro_matchers = true 23 | format_macro_bodies = true 24 | skip_macro_invocations = [] 25 | hex_literal_case = "Lower" 26 | empty_item_single_line = true 27 | struct_lit_single_line = true 28 | fn_single_line = false 29 | where_single_line = false 30 | imports_indent = "Block" 31 | imports_layout = "Mixed" 32 | imports_granularity = "Crate" 33 | group_imports = "StdExternalCrate" 34 | reorder_imports = true 35 | reorder_modules = true 36 | reorder_impl_items = true 37 | type_punctuation_density = "Wide" 38 | space_before_colon = false 39 | space_after_colon = true 40 | spaces_around_ranges = false 41 | binop_separator = "Front" 42 | remove_nested_parens = true 43 | combine_control_expr = true 44 | short_array_element_width_threshold = 10 45 | overflow_delimited_expr = true 46 | struct_field_align_threshold = 0 47 | enum_discrim_align_threshold = 0 48 | match_arm_blocks = true 49 | match_arm_leading_pipes = "Never" 50 | force_multiline_blocks = false 51 | fn_params_layout = "Tall" 52 | brace_style = "SameLineWhere" 53 | control_brace_style = "AlwaysSameLine" 54 | trailing_semicolon = true 55 | trailing_comma = "Vertical" 56 | match_block_trailing_comma = false 57 | blank_lines_upper_bound = 1 58 | blank_lines_lower_bound = 0 59 | edition = "2021" 60 | version = "Two" 61 | inline_attribute_width = 0 62 | format_generated_files = true 63 | merge_derives = true 64 | use_try_shorthand = false 65 | use_field_init_shorthand = true 66 | force_explicit_abi = true 67 | condense_wildcard_suffixes = true 68 | color = "Auto" 69 | unstable_features = true 70 | disable_all_formatting = false 71 | skip_children = false 72 | hide_parse_errors = false 73 | error_on_line_overflow = false 74 | error_on_unformatted = false 75 | ignore = [] 76 | emit_mode = "Files" 77 | make_backup = false 78 | -------------------------------------------------------------------------------- /src/iter.rs: -------------------------------------------------------------------------------- 1 | //! Iterators over a [`Rope`]'s data. 2 | //! 3 | //! The iterators in Any-Ropey can be created from both [`Rope`]s and 4 | //! [`RopeSlice`]s. When created from a [`RopeSlice`], they iterate over 5 | //! only the data that the [`RopeSlice`] refers to. For the [`Chunks`] 6 | //! iterator, the data of the first and last yielded item will be correctly 7 | //! truncated to match the bounds of the [`RopeSlice`]. 8 | //! 9 | //! # Reverse iteration 10 | //! 11 | //! All iterators in Ropey operate as a cursor that can move both forwards 12 | //! and backwards over its contents. This can be accomplished via the 13 | //! `next()` and `prev()` methods on each iterator, or by using the `reverse()` 14 | //! or `reversed()` methods to change the iterator's direction. 15 | //! 16 | //! Conceptually, an iterator in Any-Ropey is always positioned *between* the 17 | //! elements it iterates over, and returns an element when it jumps over it 18 | //! via the `next()` or `prev()` methods. 19 | //! 20 | //! For example, given the slice `[Width(1), Width(2), Width(5)]` and a an 21 | //! iterator starting at the beginning of the slice, you would get the following 22 | //! sequence of states and return values by repeatedly calling `next()` (the 23 | //! vertical bar represents the position of the iterator): 24 | //! 25 | //! 0. `[|Width(1), Width(2), Width(5)]` 26 | //! 1. `[Width(1), |Width(2), Width(5)] -> Some(Width(1))` 27 | //! 2. `[Width(1), Width(2), |Width(5)] -> Some(Width(2))` 28 | //! 3. `[Width(1), Width(2), Width(5)|] -> Some(Width(5))` 29 | //! 4. `[Width(1), Width(2), Width(5)|] -> None` 30 | //! 31 | //! The `prev()` method operates identically, except moving in the opposite 32 | //! direction. And `reverse()` simply swaps the behavior of `prev()` and 33 | //! `next()`. 34 | //! 35 | //! # Creating iterators at any position 36 | //! 37 | //! Iterators in Ropey can be created starting at any position in the rope. 38 | //! This is accomplished with the [`Iter`] and [`Chunks`] iterators, which 39 | //! can be created by various functions on a [`Rope`]. 40 | //! 41 | //! When an iterator is created this way, it is positioned such that a call to 42 | //! `next()` will return the specified element, and a call to `prev()` will 43 | //! return the element just before the specified one. 44 | //! 45 | //! Importantly, iterators created this way still have access to the entire 46 | //! contents of the [`Rope`]/[`RopeSlice`] they were created from and the 47 | //! contents before the specified position is not truncated. For example, you 48 | //! can create an [`Iter`] iterator starting at the end of a [`Rope`], and 49 | //! then use the [`prev()`][Iter::prev] method to iterate backwards over all of 50 | //! that [`Rope`]'s elements. 51 | //! 52 | //! # A possible point of confusion 53 | //! 54 | //! The Rust standard library has an iterator trait [`DoubleEndedIterator`] with 55 | //! a method [`rev()`]. While this method's name is //! very similar to Ropey's 56 | //! [`reverse()`][Iter::reverse] method, its behavior is very different. 57 | //! 58 | //! [`DoubleEndedIterator`] actually provides two iterators: one starting at 59 | //! each end of the collection, moving in opposite directions towards each 60 | //! other. Calling [`rev()`] switches between those two iterators, changing not 61 | //! only the direction of iteration but also its current position in the 62 | //! collection. 63 | //! 64 | //! The [`reverse()`][Iter::reverse] method on AnyRopey's iterators, on the 65 | //! other hand, reverses the direction of the iterator in-place, without 66 | //! changing its position in the rope. 67 | //! 68 | //! [`Rope`]: crate::rope::Rope 69 | //! [`RopeSlice`]: crate::slice::RopeSlice 70 | //! [`rev()`]: Iterator::rev 71 | 72 | use std::{cmp::Ordering, sync::Arc}; 73 | 74 | use crate::{ 75 | fallible_max, 76 | slice_utils::{index_to_measure, measure_of, start_measure_to_index}, 77 | tree::{max_children, max_len, Node, SliceInfo}, 78 | FallibleOrd, Measurable, 79 | }; 80 | 81 | //========================================================== 82 | 83 | /// An iterator over a [`Rope`][crate::rope::Rope]'s elements. 84 | #[derive(Clone)] 85 | pub struct Iter<'a, M> 86 | where 87 | M: Measurable, 88 | [(); max_len::()]: Sized, 89 | [(); max_children::()]: Sized, 90 | { 91 | chunks: Chunks<'a, M>, 92 | cur_chunk: &'a [M], 93 | index: usize, 94 | measure: M::Measure, 95 | last_call_was_prev_impl: bool, 96 | total_len: usize, 97 | remaining_len: usize, 98 | is_reversed: bool, 99 | } 100 | 101 | impl<'a, M> Iter<'a, M> 102 | where 103 | M: Measurable, 104 | [(); max_len::()]: Sized, 105 | [(); max_children::()]: Sized, 106 | { 107 | pub(crate) fn new(node: &'a Arc>) -> Self { 108 | let mut chunk_iter = Chunks::new(node); 109 | let cur_chunk = if let Some(chunk) = chunk_iter.next() { 110 | chunk 111 | } else { 112 | &[] 113 | }; 114 | Iter { 115 | chunks: chunk_iter, 116 | cur_chunk, 117 | index: 0, 118 | measure: M::Measure::default(), 119 | last_call_was_prev_impl: false, 120 | total_len: node.info().len as usize, 121 | remaining_len: node.info().len as usize, 122 | is_reversed: false, 123 | } 124 | } 125 | 126 | #[inline(always)] 127 | pub(crate) fn new_with_range( 128 | node: &'a Arc>, 129 | index_range: (usize, usize), 130 | measure_range: (M::Measure, M::Measure), 131 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 132 | ) -> Self { 133 | Iter::new_with_range_at_measure(node, measure_range.0, index_range, measure_range, cmp) 134 | } 135 | 136 | pub(crate) fn new_with_range_at_measure( 137 | node: &'a Arc>, 138 | at_measure: M::Measure, 139 | index_range: (usize, usize), 140 | measure_range: (M::Measure, M::Measure), 141 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 142 | ) -> Self { 143 | let (mut chunks, mut chunk_start_index, mut chunk_start_measure) = 144 | Chunks::new_with_range_at_measure(node, at_measure, index_range, measure_range, &cmp); 145 | 146 | let cur_chunk = if index_range.0 == index_range.1 { 147 | &[] 148 | } else if let Some(chunk) = chunks.next() { 149 | chunk 150 | } else { 151 | let chunk = chunks.prev().unwrap(); 152 | chunks.next(); 153 | chunk_start_index -= chunk.len(); 154 | 155 | let accum_prev_measure = chunk 156 | .iter() 157 | .map(|m| m.measure()) 158 | .fold(M::Measure::default(), |accum, measure| accum + measure); 159 | chunk_start_measure = chunk_start_measure - accum_prev_measure; 160 | 161 | chunk 162 | }; 163 | 164 | let index = start_measure_to_index(cur_chunk, at_measure - chunk_start_measure, &cmp); 165 | let measure = index_to_measure(cur_chunk, index) + chunk_start_measure; 166 | 167 | Iter { 168 | chunks, 169 | cur_chunk, 170 | index, 171 | measure, 172 | last_call_was_prev_impl: false, 173 | total_len: index_range.1 - index_range.0, 174 | remaining_len: index_range.1 - (index + chunk_start_index), 175 | is_reversed: false, 176 | } 177 | } 178 | 179 | #[inline(always)] 180 | pub(crate) fn from_slice(slice: &'a [M]) -> Self { 181 | Iter::from_slice_at(slice, M::Measure::default(), M::Measure::fallible_cmp) 182 | } 183 | 184 | pub(crate) fn from_slice_at( 185 | slice: &'a [M], 186 | measure: M::Measure, 187 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 188 | ) -> Self { 189 | let mut chunks = Chunks::from_slice(slice, false); 190 | let cur_chunk = if let Some(chunk) = chunks.next() { 191 | chunk 192 | } else { 193 | &[] 194 | }; 195 | 196 | let index = start_measure_to_index(slice, measure, cmp); 197 | let measure = index_to_measure(slice, index); 198 | 199 | Iter { 200 | chunks, 201 | cur_chunk, 202 | index, 203 | measure, 204 | last_call_was_prev_impl: false, 205 | total_len: slice.len(), 206 | remaining_len: slice.len() - index, 207 | is_reversed: false, 208 | } 209 | } 210 | 211 | /// Reverses the direction of the iterator in-place. 212 | /// 213 | /// In other words, swaps the behavior of [`prev()`][Self::prev] 214 | /// and [`next()`][Self::next]. 215 | #[inline] 216 | pub fn reverse(&mut self) { 217 | self.is_reversed = !self.is_reversed; 218 | } 219 | 220 | /// Same as [`reverse()`][Self::reverse], but returns itself. 221 | /// 222 | /// This is useful when chaining iterator methods: 223 | /// 224 | /// ```rust 225 | /// #![feature(generic_const_exprs)] 226 | /// # use any_rope::{Rope, Width}; 227 | /// # let rope = Rope::from_slice(&[Width(1), Width(2), Width(5)]); 228 | /// // Print the rope's elements and their measures in reverse. 229 | /// for (measure, element) in rope.iter_at_measure(rope.measure(), usize::cmp).reversed() { 230 | /// println!("{} {:?}", measure, element); 231 | /// # assert_eq!((measure, element), rope.from_measure(measure, usize::cmp)); 232 | /// } 233 | #[inline] 234 | #[must_use] 235 | pub fn reversed(mut self) -> Self { 236 | self.reverse(); 237 | self 238 | } 239 | 240 | /// Advances the iterator backwards and returns the previous value. 241 | /// 242 | /// Runs in amortized O(1) time and worst-case O(log N) time. 243 | #[inline(always)] 244 | pub fn prev(&mut self) -> Option<(M::Measure, M)> { 245 | if !self.is_reversed { 246 | self.prev_impl() 247 | } else { 248 | self.next_impl() 249 | } 250 | } 251 | 252 | #[inline] 253 | fn prev_impl(&mut self) -> Option<(M::Measure, M)> { 254 | // Put us back into a "prev" progression. 255 | if !self.last_call_was_prev_impl { 256 | self.chunks.prev(); 257 | self.last_call_was_prev_impl = true; 258 | } 259 | 260 | // Progress the chunks iterator back if needed. 261 | if self.index == 0 { 262 | if let Some(chunk) = self.chunks.prev() { 263 | self.cur_chunk = chunk; 264 | self.index = self.cur_chunk.len(); 265 | } else { 266 | return None; 267 | } 268 | } 269 | 270 | // Progress the byte counts and return the previous element. 271 | self.index -= 1; 272 | self.remaining_len += 1; 273 | self.measure = self.measure - self.cur_chunk[self.index].measure(); 274 | return Some((self.measure, self.cur_chunk[self.index].clone())); 275 | } 276 | 277 | #[inline] 278 | fn next_impl(&mut self) -> Option<(M::Measure, M)> { 279 | // Put us back into a "next" progression. 280 | if self.last_call_was_prev_impl { 281 | self.chunks.next(); 282 | self.last_call_was_prev_impl = false; 283 | } 284 | 285 | // Progress the chunks iterator forward if needed. 286 | if self.index >= self.cur_chunk.len() { 287 | if let Some(chunk) = self.chunks.next() { 288 | self.cur_chunk = chunk; 289 | self.index = 0; 290 | } else { 291 | return None; 292 | } 293 | } 294 | 295 | // Progress the byte counts and return the next element. 296 | let element = self.cur_chunk[self.index].clone(); 297 | self.index += 1; 298 | self.remaining_len -= 1; 299 | 300 | let old_measure = self.measure; 301 | self.measure = self.measure + element.measure(); 302 | return Some((old_measure, element)); 303 | } 304 | } 305 | 306 | impl<'a, M> Iterator for Iter<'a, M> 307 | where 308 | M: Measurable, 309 | [(); max_len::()]: Sized, 310 | [(); max_children::()]: Sized, 311 | { 312 | type Item = (M::Measure, M); 313 | 314 | /// Advances the iterator forward and returns the next value. 315 | /// 316 | /// Runs in amortized O(1) time and worst-case O(log N) time. 317 | #[inline(always)] 318 | fn next(&mut self) -> Option { 319 | if !self.is_reversed { 320 | self.next_impl() 321 | } else { 322 | self.prev_impl() 323 | } 324 | } 325 | 326 | fn size_hint(&self) -> (usize, Option) { 327 | let remaining = if !self.is_reversed { 328 | self.remaining_len 329 | } else { 330 | self.total_len - self.remaining_len 331 | }; 332 | (remaining, Some(remaining)) 333 | } 334 | } 335 | 336 | impl<'a, M> ExactSizeIterator for Iter<'a, M> 337 | where 338 | M: Measurable, 339 | [(); max_len::()]: Sized, 340 | [(); max_children::()]: Sized, 341 | { 342 | } 343 | 344 | //========================================================== 345 | 346 | /// An iterator over a [`Rope`]'s contiguous [`M`] chunks. 347 | /// 348 | /// Internally, each [`Rope`] stores [`M`]s as a segemented collection of 349 | /// [`&[M]`][Measurable]. It is useful for situations such as: 350 | /// 351 | /// - Streaming a [`Rope`]'s elements data somewhere. 352 | /// - Writing custom iterators over a [`Rope`]'s data. 353 | /// 354 | /// There are no guarantees about the size of yielded chunks, and there are 355 | /// no guarantees about where the chunks are split. For example, they may 356 | /// be zero-sized. 357 | /// 358 | /// [`M`]: Measurable 359 | /// [`Rope`]: crate::rope::Rope 360 | #[derive(Clone)] 361 | pub struct Chunks<'a, M> 362 | where 363 | M: Measurable, 364 | [(); max_len::()]: Sized, 365 | [(); max_children::()]: Sized, 366 | { 367 | iter: ChunksEnum<'a, M>, 368 | is_reversed: bool, 369 | } 370 | 371 | #[derive(Clone)] 372 | enum ChunksEnum<'a, M> 373 | where 374 | M: Measurable, 375 | [(); max_len::()]: Sized, 376 | [(); max_children::()]: Sized, 377 | { 378 | Full { 379 | /// (node ref, index of current child) 380 | node_stack: Vec<(&'a Arc>, usize)>, 381 | /// Total lenght of the data range of the iterator. 382 | len: usize, 383 | /// The index of the current element relative to the data range start. 384 | index: isize, 385 | }, 386 | Light { 387 | slice: &'a [M], 388 | is_end: bool, 389 | }, 390 | } 391 | 392 | impl<'a, M> Chunks<'a, M> 393 | where 394 | M: Measurable, 395 | [(); max_len::()]: Sized, 396 | [(); max_children::()]: Sized, 397 | { 398 | #[inline(always)] 399 | pub(crate) fn new(node: &'a Arc>) -> Self { 400 | let info = node.info(); 401 | Chunks::new_with_range_at_index( 402 | node, 403 | 0, 404 | (0, info.len as usize), 405 | (M::Measure::default(), info.measure), 406 | ) 407 | .0 408 | } 409 | 410 | #[inline(always)] 411 | pub(crate) fn new_with_range( 412 | node: &'a Arc>, 413 | index_range: (usize, usize), 414 | measure_range: (M::Measure, M::Measure), 415 | ) -> Self { 416 | Chunks::new_with_range_at_index(node, index_range.0, index_range, measure_range).0 417 | } 418 | 419 | /// The main workhorse function for creating new [`Chunks`] iterators. 420 | /// 421 | /// Creates a new [`Chunks`] iterator from the given node, starting the 422 | /// iterator at the chunk containing the element in `at_index` 423 | /// (i.e. the [`next()`][Self::next] method will yield the chunk containing 424 | /// that element). The range of the iterator is bounded by `index_range`. 425 | /// 426 | /// Both `at_index` and `index_range` are relative to the beginning of 427 | /// of the passed node. 428 | /// 429 | /// Passing an `at_index` equal to the max of `index_range` creates an 430 | /// iterator at the end of forward iteration. 431 | /// 432 | /// Returns the iterator and the index/measure of its start relative 433 | /// to the start of the node. 434 | pub(crate) fn new_with_range_at_index( 435 | node: &Arc>, 436 | at_index: usize, 437 | (start_index, end_index): (usize, usize), 438 | measure_range: (M::Measure, M::Measure), 439 | ) -> (Chunks, usize, M::Measure) { 440 | debug_assert!(at_index >= start_index); 441 | debug_assert!(at_index <= end_index); 442 | 443 | // Special-case for empty slice contents. 444 | if start_index == end_index { 445 | return ( 446 | Chunks { 447 | iter: ChunksEnum::Light { 448 | slice: &[], 449 | is_end: false, 450 | }, 451 | is_reversed: false, 452 | }, 453 | 0, 454 | M::Measure::default(), 455 | ); 456 | } 457 | 458 | // If root is a leaf, return light version of the iter. 459 | if node.is_leaf() { 460 | let slice = &node.leaf_slice()[start_index..end_index]; 461 | if at_index == end_index { 462 | return ( 463 | Chunks { 464 | iter: ChunksEnum::Light { 465 | slice, 466 | is_end: true, 467 | }, 468 | is_reversed: false, 469 | }, 470 | slice.len(), 471 | measure_of(slice), 472 | ); 473 | } else { 474 | return ( 475 | Chunks { 476 | iter: ChunksEnum::Light { 477 | slice, 478 | is_end: false, 479 | }, 480 | is_reversed: false, 481 | }, 482 | 0, 483 | M::Measure::default(), 484 | ); 485 | } 486 | } 487 | 488 | // Create and populate the node stack, and determine the char index 489 | // within the first chunk, and byte index of the start of that chunk. 490 | let mut info = SliceInfo::::new::(); 491 | let mut index = at_index as isize; 492 | let node_stack = { 493 | let mut node_stack: Vec<(&Arc>, usize)> = Vec::new(); 494 | let mut node_ref = node; 495 | loop { 496 | match **node_ref { 497 | Node::Leaf(ref slice) => { 498 | if at_index < end_index || index == 0 { 499 | index = info.len as isize - start_index as isize; 500 | } else { 501 | index = 502 | (info.len as isize + slice.len() as isize) - start_index as isize; 503 | info = SliceInfo { 504 | len: end_index as u64, 505 | measure: measure_range.1, 506 | }; 507 | node_stack.last_mut().unwrap().1 += 1; 508 | } 509 | break; 510 | } 511 | Node::Branch(ref children) => { 512 | let (child_i, acc_info) = children.search_index(index as usize); 513 | info += acc_info; 514 | node_stack.push((node_ref, child_i)); 515 | node_ref = &children.nodes()[child_i]; 516 | index -= acc_info.len as isize; 517 | } 518 | } 519 | } 520 | node_stack 521 | }; 522 | 523 | // Create the iterator. 524 | ( 525 | Chunks { 526 | iter: ChunksEnum::Full { 527 | node_stack, 528 | len: end_index - start_index, 529 | index, 530 | }, 531 | is_reversed: false, 532 | }, 533 | (info.len as usize).max(start_index), 534 | fallible_max(info.measure, measure_range.0), 535 | ) 536 | } 537 | 538 | #[inline(always)] 539 | pub(crate) fn new_with_range_at_measure( 540 | node: &'a Arc>, 541 | at_measure: M::Measure, 542 | index_range: (usize, usize), 543 | measure_range: (M::Measure, M::Measure), 544 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 545 | ) -> (Self, usize, M::Measure) { 546 | let at_index = 547 | (node.get_first_chunk_at_measure(at_measure, &cmp).1.len as usize).max(index_range.0); 548 | 549 | Chunks::new_with_range_at_index(node, at_index, index_range, measure_range) 550 | } 551 | 552 | pub(crate) fn from_slice(slice: &'a [M], is_end: bool) -> Self { 553 | Chunks { 554 | iter: ChunksEnum::Light { slice, is_end }, 555 | is_reversed: false, 556 | } 557 | } 558 | 559 | /// Reverses the direction of the iterator in-place. 560 | /// 561 | /// In other words, swaps the behavior of [`prev()`][Self::prev] 562 | /// and [`next()`][Self::next]. 563 | #[inline] 564 | pub fn reverse(&mut self) { 565 | self.is_reversed = !self.is_reversed; 566 | } 567 | 568 | /// Same as [`reverse()`][Self::reverse], but returns itself. 569 | /// 570 | /// This is useful when chaining iterator methods: 571 | /// 572 | /// ```rust 573 | /// # use any_rope::{Rope, Width}; 574 | /// # let rope = Rope::from_slice( 575 | /// # &[Width(1), Width(2), Width(3), Width(0), Width(0)] 576 | /// # ); 577 | /// // Enumerate the rope's chunks in reverse, starting from the end. 578 | /// for (index, chunk) in rope.chunks_at_index(rope.len()).0.reversed().enumerate() { 579 | /// println!("{} {:?}", index, chunk); 580 | /// # assert_eq!(chunk, rope.chunks().nth(rope.chunks().count() - index - 1).unwrap()); 581 | /// } 582 | #[inline] 583 | #[must_use] 584 | pub fn reversed(mut self) -> Self { 585 | self.reverse(); 586 | self 587 | } 588 | 589 | /// Advances the iterator backwards and returns the previous value. 590 | /// 591 | /// Runs in amortized O(1) time and worst-case O(log N) time. 592 | #[inline(always)] 593 | pub fn prev(&mut self) -> Option<&'a [M]> { 594 | if !self.is_reversed { 595 | self.prev_impl() 596 | } else { 597 | self.next_impl() 598 | } 599 | } 600 | 601 | fn prev_impl(&mut self) -> Option<&'a [M]> { 602 | match *self { 603 | Chunks { 604 | iter: 605 | ChunksEnum::Full { 606 | ref mut node_stack, 607 | len, 608 | ref mut index, 609 | }, 610 | .. 611 | } => { 612 | if *index <= 0 { 613 | return None; 614 | } 615 | 616 | // Progress the node stack if needed. 617 | let mut stack_index = node_stack.len() - 1; 618 | if node_stack[stack_index].1 == 0 { 619 | while node_stack[stack_index].1 == 0 { 620 | if stack_index == 0 { 621 | return None; 622 | } else { 623 | stack_index -= 1; 624 | } 625 | } 626 | node_stack[stack_index].1 -= 1; 627 | while stack_index < (node_stack.len() - 1) { 628 | let child_i = node_stack[stack_index].1; 629 | let node = &node_stack[stack_index].0.children().nodes()[child_i]; 630 | node_stack[stack_index + 1] = (node, node.child_count() - 1); 631 | stack_index += 1; 632 | } 633 | node_stack[stack_index].1 += 1; 634 | } 635 | 636 | // Fetch the node and child index. 637 | let (node, ref mut child_i) = node_stack.last_mut().unwrap(); 638 | *child_i -= 1; 639 | 640 | // Get the slice in the appropriate range. 641 | let slice = node.children().nodes()[*child_i].leaf_slice(); 642 | *index -= slice.len() as isize; 643 | let slice = { 644 | let start_byte = if *index < 0 { (-*index) as usize } else { 0 }; 645 | let end_byte = slice.len().min((len as isize - *index) as usize); 646 | &slice[start_byte..end_byte] 647 | }; 648 | 649 | // Return the slice. 650 | return Some(slice); 651 | } 652 | 653 | Chunks { 654 | iter: 655 | ChunksEnum::Light { 656 | slice, 657 | ref mut is_end, 658 | }, 659 | .. 660 | } => { 661 | if !*is_end || slice.is_empty() { 662 | return None; 663 | } else { 664 | *is_end = false; 665 | return Some(slice); 666 | } 667 | } 668 | } 669 | } 670 | 671 | fn next_impl(&mut self) -> Option<&'a [M]> { 672 | match *self { 673 | Chunks { 674 | iter: 675 | ChunksEnum::Full { 676 | ref mut node_stack, 677 | len, 678 | ref mut index, 679 | }, 680 | .. 681 | } => { 682 | if *index >= len as isize { 683 | return None; 684 | } 685 | 686 | // Progress the node stack if needed. 687 | let mut stack_index = node_stack.len() - 1; 688 | if node_stack[stack_index].1 >= node_stack[stack_index].0.child_count() { 689 | while node_stack[stack_index].1 >= (node_stack[stack_index].0.child_count() - 1) 690 | { 691 | if stack_index == 0 { 692 | return None; 693 | } else { 694 | stack_index -= 1; 695 | } 696 | } 697 | node_stack[stack_index].1 += 1; 698 | while stack_index < (node_stack.len() - 1) { 699 | let child_i = node_stack[stack_index].1; 700 | let node = &node_stack[stack_index].0.children().nodes()[child_i]; 701 | node_stack[stack_index + 1] = (node, 0); 702 | stack_index += 1; 703 | } 704 | } 705 | 706 | // Fetch the node and child index. 707 | let (node, ref mut child_i) = node_stack.last_mut().unwrap(); 708 | 709 | // Get the slice, sliced to the appropriate range. 710 | let leaf_slice = node.children().nodes()[*child_i].leaf_slice(); 711 | let slice = { 712 | let start_byte = if *index < 0 { (-*index) as usize } else { 0 }; 713 | let end_byte = leaf_slice.len().min((len as isize - *index) as usize); 714 | &leaf_slice[start_byte..end_byte] 715 | }; 716 | 717 | // Book keeping. 718 | *index += leaf_slice.len() as isize; 719 | *child_i += 1; 720 | 721 | // Return the slice. 722 | return Some(slice); 723 | } 724 | 725 | Chunks { 726 | iter: 727 | ChunksEnum::Light { 728 | slice, 729 | ref mut is_end, 730 | }, 731 | .. 732 | } => { 733 | if *is_end || slice.is_empty() { 734 | return None; 735 | } else { 736 | *is_end = true; 737 | return Some(slice); 738 | } 739 | } 740 | } 741 | } 742 | } 743 | 744 | impl<'a, M> Iterator for Chunks<'a, M> 745 | where 746 | M: Measurable, 747 | [(); max_len::()]: Sized, 748 | [(); max_children::()]: Sized, 749 | { 750 | type Item = &'a [M]; 751 | 752 | /// Advances the iterator forward and returns the next value. 753 | /// 754 | /// Runs in amortized O(1) time and worst-case O(log N) time. 755 | #[inline(always)] 756 | fn next(&mut self) -> Option<&'a [M]> { 757 | if !self.is_reversed { 758 | self.next_impl() 759 | } else { 760 | self.prev_impl() 761 | } 762 | } 763 | } 764 | 765 | #[cfg(test)] 766 | mod tests { 767 | #![allow(clippy::while_let_on_iterator)] 768 | use super::*; 769 | use crate::{Rope, Width}; 770 | 771 | fn pseudo_random() -> Vec { 772 | (0..1400) 773 | .map(|num| match num % 14 { 774 | 0 => Width(1), 775 | 1 => Width(2), 776 | 2 => Width(4), 777 | 3 => Width(0), 778 | 4 => Width(0), 779 | 5 => Width(5), 780 | 6 => Width(1), 781 | 7 => Width(1), 782 | 8 => Width(2), 783 | 9 => Width(8), 784 | 10 => Width(0), 785 | 11 => Width(0), 786 | 12 => Width(3), 787 | 13 => Width(0), 788 | _ => unreachable!(), 789 | }) 790 | .collect() 791 | } 792 | 793 | #[test] 794 | #[cfg_attr(miri, ignore)] 795 | fn iter_01() { 796 | let rope = Rope::from_slice(pseudo_random().as_slice()); 797 | for ((_, from_rope), from_vec) in rope.iter().zip(pseudo_random().iter().copied()) { 798 | assert_eq!(from_rope, from_vec); 799 | } 800 | } 801 | 802 | #[test] 803 | #[cfg_attr(miri, ignore)] 804 | fn iter_02() { 805 | let rope = Rope::from_slice(pseudo_random().as_slice()); 806 | let mut iter = rope.iter(); 807 | while let Some(_) = iter.next() {} 808 | 809 | let mut i = pseudo_random().len(); 810 | while let Some((_, element)) = iter.prev() { 811 | i -= 1; 812 | assert_eq!(element, pseudo_random()[i]); 813 | } 814 | } 815 | 816 | #[test] 817 | #[cfg_attr(miri, ignore)] 818 | fn iter_03() { 819 | let rope = Rope::from_slice(pseudo_random().as_slice()); 820 | let mut iter = rope.iter(); 821 | 822 | iter.next(); 823 | iter.prev(); 824 | assert_eq!(None, iter.prev()); 825 | } 826 | 827 | #[test] 828 | #[cfg_attr(miri, ignore)] 829 | fn iter_04() { 830 | let rope = Rope::from_slice(pseudo_random().as_slice()); 831 | let mut iter = rope.iter(); 832 | while let Some(_) = iter.next() {} 833 | 834 | iter.prev(); 835 | iter.next(); 836 | assert_eq!(None, iter.next()); 837 | } 838 | 839 | #[test] 840 | #[cfg_attr(miri, ignore)] 841 | fn iter_05() { 842 | let rope = Rope::from_slice(pseudo_random().as_slice()); 843 | let mut iter = rope.iter(); 844 | 845 | assert_eq!(None, iter.prev()); 846 | iter.next(); 847 | iter.prev(); 848 | assert_eq!(None, iter.prev()); 849 | } 850 | 851 | #[test] 852 | #[cfg_attr(miri, ignore)] 853 | fn iter_06() { 854 | let rope = Rope::from_slice(pseudo_random().as_slice()); 855 | let mut iter = rope.iter(); 856 | while let Some(_) = iter.next() {} 857 | 858 | assert_eq!(None, iter.next()); 859 | iter.prev(); 860 | iter.next(); 861 | assert_eq!(None, iter.next()); 862 | } 863 | 864 | #[test] 865 | #[cfg_attr(miri, ignore)] 866 | fn iter_07() { 867 | let mut iter = Iter::from_slice(&[Width(1)]); 868 | 869 | assert_eq!(Some((0, Width(1))), iter.next()); 870 | assert_eq!(None, iter.next()); 871 | assert_eq!(Some((0, Width(1))), iter.prev()); 872 | assert_eq!(None, iter.prev()); 873 | } 874 | 875 | #[test] 876 | #[cfg_attr(miri, ignore)] 877 | fn iter_08() { 878 | let measure_vec = pseudo_random(); 879 | let mut iter = Iter::from_slice(measure_vec.as_slice()); 880 | 881 | assert_eq!(iter.next(), Some((0, Width(1)))); 882 | assert_eq!(iter.next(), Some((1, Width(2)))); 883 | assert_eq!(iter.next(), Some((3, Width(4)))); 884 | assert_eq!(iter.next(), Some((7, Width(0)))); 885 | assert_eq!(iter.next(), Some((7, Width(0)))); 886 | assert_eq!(iter.next(), Some((7, Width(5)))); 887 | assert_eq!(iter.next(), Some((12, Width(1)))); 888 | assert_eq!(iter.next(), Some((13, Width(1)))); 889 | assert_eq!(iter.next(), Some((14, Width(2)))); 890 | assert_eq!(iter.next(), Some((16, Width(8)))); 891 | assert_eq!(iter.next(), Some((24, Width(0)))); 892 | assert_eq!(iter.next(), Some((24, Width(0)))); 893 | assert_eq!(iter.next(), Some((24, Width(3)))); 894 | assert_eq!(iter.next(), Some((27, Width(0)))); 895 | assert_eq!(iter.next(), Some((27, Width(1)))); 896 | } 897 | 898 | #[test] 899 | #[cfg_attr(miri, ignore)] 900 | fn iter_at_01() { 901 | let rope = Rope::from_slice(pseudo_random().as_slice()); 902 | let slice = rope.measure_slice(..79, usize::cmp); 903 | let mut iter = slice.iter_at(56, usize::cmp); 904 | 905 | assert_eq!(iter.next(), Some((55, Width(2)))); 906 | assert_eq!(iter.next(), Some((57, Width(4)))); 907 | assert_eq!(iter.next(), Some((61, Width(0)))); 908 | assert_eq!(iter.next(), Some((61, Width(0)))); 909 | assert_eq!(iter.next(), Some((61, Width(5)))); 910 | assert_eq!(iter.next(), Some((66, Width(1)))); 911 | assert_eq!(iter.next(), Some((67, Width(1)))); 912 | assert_eq!(iter.next(), Some((68, Width(2)))); 913 | assert_eq!(iter.next(), Some((70, Width(8)))); 914 | assert_eq!(iter.next(), Some((78, Width(0)))); 915 | assert_eq!(iter.next(), Some((78, Width(0)))); 916 | assert_eq!(iter.next(), Some((78, Width(3)))); 917 | assert_eq!(iter.next(), None); 918 | } 919 | 920 | #[test] 921 | #[cfg_attr(miri, ignore)] 922 | fn iter_at_02() { 923 | let rope = Rope::from_slice(pseudo_random().as_slice()); 924 | let mut bytes = rope.iter_at_measure(rope.measure(), usize::cmp); 925 | // Iterating at the end, when there are zero measure elements, always yields 926 | // them. 927 | assert_eq!(bytes.next(), Some((2700, Width(0)))); 928 | assert_eq!(bytes.next(), None); 929 | } 930 | 931 | #[test] 932 | #[cfg_attr(miri, ignore)] 933 | fn iter_at_03() { 934 | let rope = Rope::from_slice(pseudo_random().as_slice()); 935 | let mut iter_1 = rope.iter_at_measure(rope.measure(), usize::cmp); 936 | let measure_vec = pseudo_random(); 937 | // Skip the last element, since it's zero measure. 938 | let mut iter_2 = measure_vec.iter().take(1399).copied(); 939 | 940 | while let Some(b) = iter_2.next_back() { 941 | assert_eq!(iter_1.prev().map(|(_, element)| element), Some(b)); 942 | } 943 | } 944 | 945 | #[test] 946 | #[cfg_attr(miri, ignore)] 947 | fn exact_size_iter_01() { 948 | let rope = Rope::from_slice(pseudo_random().as_slice()); 949 | let slice = rope.measure_slice(34..75, usize::cmp); 950 | 951 | let mut len = slice.len(); 952 | let mut iter = slice.iter(); 953 | assert_eq!(len, iter.len()); 954 | 955 | while let Some(_) = iter.next() { 956 | len -= 1; 957 | assert_eq!(len, iter.len()); 958 | } 959 | 960 | iter.next(); 961 | iter.next(); 962 | iter.next(); 963 | iter.next(); 964 | iter.next(); 965 | iter.next(); 966 | iter.next(); 967 | assert_eq!(iter.len(), 0); 968 | assert_eq!(len, 0); 969 | } 970 | 971 | #[test] 972 | #[cfg_attr(miri, ignore)] 973 | fn exact_size_iter_02() { 974 | let rope = Rope::from_slice(pseudo_random().as_slice()); 975 | let slice = rope.measure_slice(34..300, usize::cmp); 976 | 977 | let mut len = 0; 978 | let mut iter = slice.iter_at(slice.measure(), usize::cmp); 979 | 980 | assert_eq!(len, iter.len()); 981 | 982 | while iter.prev().is_some() { 983 | len += 1; 984 | assert_eq!(len, iter.len()); 985 | } 986 | 987 | assert_eq!(iter.len(), slice.len()); 988 | iter.prev(); 989 | iter.prev(); 990 | iter.prev(); 991 | iter.prev(); 992 | iter.prev(); 993 | iter.prev(); 994 | iter.prev(); 995 | assert_eq!(iter.len(), slice.len()); 996 | assert_eq!(len, slice.len()); 997 | } 998 | 999 | #[test] 1000 | #[cfg_attr(miri, ignore)] 1001 | fn exact_size_iter_03() { 1002 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1003 | let slice = rope.measure_slice(34..34, usize::cmp); 1004 | let mut iter = slice.iter(); 1005 | 1006 | assert_eq!(iter.next(), Some((34, Width(0)))); 1007 | assert_eq!(iter.next(), Some((34, Width(0)))); 1008 | assert_eq!(iter.next(), None); 1009 | } 1010 | 1011 | #[test] 1012 | #[cfg_attr(miri, ignore)] 1013 | fn iter_reverse_01() { 1014 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1015 | let mut iter = rope.iter(); 1016 | let mut stack = Vec::new(); 1017 | 1018 | for _ in 0..32 { 1019 | stack.push(iter.next().unwrap()); 1020 | } 1021 | iter.reverse(); 1022 | for _ in 0..32 { 1023 | assert_eq!(stack.pop(), iter.next()); 1024 | } 1025 | } 1026 | 1027 | #[test] 1028 | #[cfg_attr(miri, ignore)] 1029 | fn iter_reverse_02() { 1030 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1031 | let mut iter = rope.iter_at_measure(rope.len() / 3, usize::cmp); 1032 | let mut stack = Vec::new(); 1033 | 1034 | for _ in 0..32 { 1035 | stack.push(iter.next().unwrap()); 1036 | } 1037 | iter.reverse(); 1038 | for _ in 0..32 { 1039 | assert_eq!(stack.pop(), iter.next()); 1040 | } 1041 | } 1042 | 1043 | #[test] 1044 | #[cfg_attr(miri, ignore)] 1045 | fn chunks_01() { 1046 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1047 | 1048 | let mut index = 0; 1049 | for chunk in rope.chunks() { 1050 | assert_eq!(chunk, &pseudo_random()[index..(index + chunk.len())]); 1051 | index += chunk.len(); 1052 | } 1053 | } 1054 | 1055 | #[test] 1056 | #[cfg_attr(miri, ignore)] 1057 | fn chunks_02() { 1058 | let rope = Rope::::from_slice(&[]); 1059 | let mut iter = rope.chunks(); 1060 | 1061 | assert_eq!(None, iter.next()); 1062 | } 1063 | 1064 | #[test] 1065 | #[cfg_attr(miri, ignore)] 1066 | fn chunks_03() { 1067 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1068 | 1069 | let mut iter = rope.chunks(); 1070 | 1071 | assert_eq!(None, iter.prev()); 1072 | } 1073 | 1074 | #[test] 1075 | #[cfg_attr(miri, ignore)] 1076 | fn chunks_04() { 1077 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1078 | 1079 | let mut chunks = Vec::new(); 1080 | let mut iter = rope.chunks(); 1081 | 1082 | while let Some(slice) = iter.next() { 1083 | chunks.push(slice); 1084 | } 1085 | 1086 | while let Some(slice) = iter.prev() { 1087 | assert_eq!(slice, chunks.pop().unwrap()); 1088 | } 1089 | 1090 | assert!(chunks.is_empty()); 1091 | } 1092 | 1093 | #[test] 1094 | #[cfg_attr(miri, ignore)] 1095 | fn chunks_at_01() { 1096 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1097 | 1098 | for i in 0..rope.len() { 1099 | let (chunk, index, measure) = rope.chunk_at_index(i); 1100 | let (mut chunks, slice_index, slice_measure) = rope.chunks_at_index(i); 1101 | 1102 | assert_eq!(index, slice_index); 1103 | assert_eq!(measure, slice_measure); 1104 | assert_eq!(Some(chunk), chunks.next()); 1105 | } 1106 | } 1107 | 1108 | #[test] 1109 | #[cfg_attr(miri, ignore)] 1110 | fn chunks_at_02() { 1111 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1112 | let slice = rope.measure_slice(34..301, usize::cmp); 1113 | 1114 | let (mut chunks, ..) = slice.chunks_at_index(slice.len()); 1115 | assert_eq!(chunks.next(), None); 1116 | 1117 | let (mut chunks, ..) = slice.chunks_at_index(slice.len()); 1118 | assert_eq!(slice.chunks().last(), chunks.prev()); 1119 | } 1120 | 1121 | #[test] 1122 | #[cfg_attr(miri, ignore)] 1123 | fn chunks_at_03() { 1124 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1125 | let slice = rope.measure_slice(34..34, usize::cmp); 1126 | 1127 | let (mut chunks, ..) = slice.chunks_at_index(0); 1128 | assert_eq!(chunks.next(), Some([Width(0)].as_slice())); 1129 | assert!(chunks.next().is_some()); 1130 | 1131 | let (mut chunks, ..) = slice.chunks_at_index(0); 1132 | assert_eq!(chunks.prev(), None); 1133 | } 1134 | 1135 | #[test] 1136 | #[cfg_attr(miri, ignore)] 1137 | fn chunks_reverse_01() { 1138 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1139 | let mut iter = rope.chunks(); 1140 | let mut stack = Vec::new(); 1141 | 1142 | for _ in 0..8 { 1143 | stack.push(iter.next().unwrap()); 1144 | } 1145 | iter.reverse(); 1146 | for _ in 0..8 { 1147 | assert_eq!(stack.pop().unwrap(), iter.next().unwrap()); 1148 | } 1149 | } 1150 | 1151 | #[test] 1152 | #[cfg_attr(miri, ignore)] 1153 | fn chunks_reverse_02() { 1154 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1155 | let mut iter = rope.chunks_at_measure(rope.measure() / 3, usize::cmp).0; 1156 | let mut stack = Vec::new(); 1157 | 1158 | for _ in 0..8 { 1159 | stack.push(iter.next().unwrap()); 1160 | } 1161 | iter.reverse(); 1162 | for _ in 0..8 { 1163 | assert_eq!(stack.pop().unwrap(), iter.next().unwrap()); 1164 | } 1165 | } 1166 | 1167 | #[test] 1168 | #[cfg_attr(miri, ignore)] 1169 | fn chunks_reverse_03() { 1170 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1171 | let mut iter = rope.chunks_at_measure(rope.measure() / 3, usize::cmp).0; 1172 | let mut stack = Vec::new(); 1173 | 1174 | iter.reverse(); 1175 | for _ in 0..8 { 1176 | stack.push(iter.next().unwrap()); 1177 | } 1178 | iter.reverse(); 1179 | for _ in 0..8 { 1180 | assert_eq!(stack.pop().unwrap(), iter.next().unwrap()); 1181 | } 1182 | } 1183 | 1184 | #[test] 1185 | #[cfg_attr(miri, ignore)] 1186 | fn chunks_reverse_04() { 1187 | let mut iter = Chunks::from_slice(&[Width(5), Width(0)], false); 1188 | 1189 | assert_eq!(Some([Width(5), Width(0)].as_slice()), iter.next()); 1190 | assert_eq!(None, iter.next()); 1191 | iter.reverse(); 1192 | assert_eq!(Some([Width(5), Width(0)].as_slice()), iter.next()); 1193 | assert_eq!(None, iter.next()); 1194 | } 1195 | 1196 | #[test] 1197 | #[cfg_attr(miri, ignore)] 1198 | fn iter_sliced_01() { 1199 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1200 | 1201 | let slice_start = 34; 1202 | let slice_end = 301; 1203 | let slice_start_byte = rope.start_measure_to_index(slice_start, usize::cmp); 1204 | let s_end_byte = rope.end_measure_to_index(slice_end, usize::cmp); 1205 | 1206 | let slice_1 = rope.measure_slice(slice_start..slice_end, usize::cmp); 1207 | let slice_2 = &pseudo_random()[slice_start_byte..s_end_byte]; 1208 | 1209 | let mut slice_1_iter = slice_1.iter(); 1210 | let mut slice_2_iter = slice_2.iter().copied(); 1211 | 1212 | assert_eq!(slice_1, slice_2); 1213 | assert_eq!(slice_1.from_index(0).1, slice_2[0]); 1214 | for _ in 0..(slice_2.len() + 1) { 1215 | assert_eq!( 1216 | slice_1_iter.next().map(|(_, element)| element), 1217 | slice_2_iter.next() 1218 | ); 1219 | } 1220 | } 1221 | 1222 | #[test] 1223 | #[cfg_attr(miri, ignore)] 1224 | fn iter_at_sliced_02() { 1225 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1226 | let slice = rope.measure_slice(34..300, usize::cmp); 1227 | let mut iter = slice.iter_at(slice.measure(), usize::cmp); 1228 | // Yields None, since we're iterating in the middle of a Width(4) element. 1229 | assert_eq!(iter.next(), None); 1230 | } 1231 | 1232 | #[test] 1233 | #[cfg_attr(miri, ignore)] 1234 | fn iter_at_sliced_03() { 1235 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1236 | 1237 | let slice_start = 34; 1238 | let slice_end = 300; 1239 | let slice_start_byte = rope.start_measure_to_index(slice_start, usize::cmp); 1240 | let s_end_byte = rope.end_measure_to_index(slice_end, usize::cmp); 1241 | 1242 | let slice_1 = rope.measure_slice(slice_start..slice_end, usize::cmp); 1243 | let slice_2 = &pseudo_random()[slice_start_byte..s_end_byte]; 1244 | 1245 | let mut bytes_1 = slice_1.iter_at(slice_1.measure(), usize::cmp); 1246 | let mut bytes_2 = slice_2.iter().copied(); 1247 | while let Some(b) = bytes_2.next_back() { 1248 | assert_eq!(bytes_1.prev().map(|(_, element)| element), Some(b)); 1249 | } 1250 | } 1251 | 1252 | #[test] 1253 | #[cfg_attr(miri, ignore)] 1254 | fn iter_at_sliced_reverse_01() { 1255 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1256 | 1257 | let slice_start = 34; 1258 | let slice_end = 301; 1259 | let slice = rope.measure_slice(slice_start..slice_end, usize::cmp); 1260 | 1261 | let mut iter = slice.iter_at(slice.len() / 3, usize::cmp); 1262 | let mut stack = Vec::new(); 1263 | for _ in 0..32 { 1264 | stack.push(iter.next().unwrap()); 1265 | } 1266 | iter.reverse(); 1267 | for _ in 0..32 { 1268 | assert_eq!(stack.pop(), iter.next()); 1269 | } 1270 | } 1271 | 1272 | #[test] 1273 | #[cfg_attr(miri, ignore)] 1274 | fn chunks_sliced_01() { 1275 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1276 | 1277 | let slice_start = 34; 1278 | let slice_end = 301; 1279 | let slice_start_index = rope.start_measure_to_index(slice_start, usize::cmp); 1280 | let slice_end_index = rope.end_measure_to_index(slice_end, usize::cmp); 1281 | 1282 | let slice_1 = rope.measure_slice(slice_start..slice_end, usize::cmp); 1283 | let slice_2 = &pseudo_random()[slice_start_index..slice_end_index]; 1284 | 1285 | let mut index = 0; 1286 | for chunk in slice_1.chunks() { 1287 | assert_eq!(chunk, &slice_2[index..(index + chunk.len())]); 1288 | index += chunk.len(); 1289 | } 1290 | 1291 | assert_eq!(index, slice_2.len()); 1292 | } 1293 | 1294 | #[test] 1295 | #[cfg_attr(miri, ignore)] 1296 | fn chunks_sliced_reverse_01() { 1297 | let rope = Rope::from_slice(pseudo_random().as_slice()); 1298 | 1299 | let slice_start = 34; 1300 | let slice_end = 301; 1301 | let slice = rope.measure_slice(slice_start..slice_end, usize::cmp); 1302 | 1303 | let mut iter = slice.chunks(); 1304 | let mut stack = Vec::new(); 1305 | for _ in 0..8 { 1306 | stack.push(iter.next().unwrap()); 1307 | } 1308 | iter.reverse(); 1309 | for _ in 0..8 { 1310 | assert_eq!(stack.pop(), iter.next()); 1311 | } 1312 | } 1313 | 1314 | #[test] 1315 | #[cfg_attr(miri, ignore)] 1316 | fn empty_iter() { 1317 | let rope = Rope::::from_slice(&[]); 1318 | let rope: Vec = rope.iter().map(|(_, element)| element).collect(); 1319 | assert_eq!(&*rope, [].as_slice()) 1320 | } 1321 | } 1322 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow( 2 | incomplete_features, 3 | clippy::arc_with_non_send_sync, 4 | clippy::too_many_arguments 5 | )] 6 | #![feature(generic_const_exprs)] 7 | //! AnyRope is an arbitrary data rope for Rust. 8 | //! 9 | //! AnyRope's [`Rope`] contains elements `M` that implement [`Measurable`], a 10 | //! trait that assigns an arbitrary "measure" to each element, through the 11 | //! [`measure()`][Measurable::measure] function. AnyRope can then use these 12 | //! "measures" to retrieve and iterate over elements in any given "measure" from 13 | //! the beginning of the [`Rope`]. 14 | //! 15 | //! Keep in mind that the "measure" does not correspond to the actual size of a 16 | //! type in bits or bytes, but is instead decided by the implementor, and can be 17 | //! whatever value they want. 18 | //! 19 | //! The library is made up of four main components: 20 | //! 21 | //! - [`Rope`]: the main rope type. 22 | //! - [`RopeSlice`]: an immutable view into part of a [`Rope`]. 23 | //! - [`iter`]: iterators over [`Rope`]/[`RopeSlice`] data. 24 | //! - [`RopeBuilder`]: an efficient incremental [`Rope`] builder. 25 | //! 26 | //! # A Basic Example 27 | //! 28 | //! Let's say we want create a tagging system that will be applied to text, 29 | //! in which the tags either tell you to print normally, print in red, 30 | //! underline, or skip: 31 | //! 32 | //! ```rust 33 | //! #![feature(generic_const_exprs)] 34 | //! # use std::io::Result; 35 | //! use std::fs::File; 36 | //! use std::io::{BufReader, BufWriter}; 37 | //! use any_rope::{Rope, Measurable}; 38 | //! 39 | //! // A simple tag structure that our program can understand. 40 | //! #[derive(Clone, Copy, PartialEq, Eq)] 41 | //! enum Tag { 42 | //! InRed, 43 | //! UnderLine, 44 | //! Normal, 45 | //! // The `usize` in here represents an amount of characters that won't change 46 | //! // the color of the text. 47 | //! Skip(usize) 48 | //! } 49 | //! 50 | //! impl Measurable for Tag { 51 | //! type Measure = usize; 52 | //! 53 | //! fn measure(&self) -> Self::Measure { 54 | //! match self { 55 | //! // The coloring tags are only meant to color, not to "move forward". 56 | //! Tag::InRed | Tag::UnderLine | Tag::Normal => 0, 57 | //! // The Skip tag represents an amount of characters in which no 58 | //! // tags are applied. 59 | //! Tag::Skip(amount) => *amount 60 | //! } 61 | //! } 62 | //! } 63 | //! use Tag::*; 64 | //! 65 | //! # fn activate_tag(tag: &Tag) {} 66 | //! // An `&str` that will be colored. 67 | //! let my_str = "This word will be red!"; 68 | //! 69 | //! // Here's what this means: 70 | //! // - Skip 5 characters; 71 | //! // - Change the color to red; 72 | //! // - Start underlining; 73 | //! // - Skip 4 characters; 74 | //! // - Change the rendering back to normal. 75 | //! let my_tagger = Rope::from_slice(&[Skip(5), InRed, UnderLine, Skip(4), Normal]); 76 | //! // Do note that Tag::Skip only represents characters because we are also iterating 77 | //! // over a `Chars` iterator, and have chosen to do so. 78 | //! 79 | //! let mut tags_iter = my_tagger.iter().peekable(); 80 | //! for (cur_index, ch) in my_str.chars().enumerate() { 81 | //! // The while let loop here is a useful way to activate all tags within the same 82 | //! // character. Note the sequence of [.., InRed, UnderLine, ..], both of which have 83 | //! // a measure of 0. This means that both would be triggered before moving on to the next 84 | //! // character. 85 | //! while let Some((index, tag)) = tags_iter.peek() { 86 | //! // The returned index is always the measure where an element began. In this 87 | //! // case, `tags_iter.peek()` would return `Some((0, Skip(5)))`, and then 88 | //! // `Some((5, InRed))`. 89 | //! if *index == cur_index { 90 | //! activate_tag(tag); 91 | //! tags_iter.next(); 92 | //! } else { 93 | //! break; 94 | //! } 95 | //! } 96 | //! 97 | //! print!("{}", ch); 98 | //! } 99 | //! ``` 100 | //! 101 | //! An example can be found in the `examples` directory, detailing a "search and 102 | //! replace" functionality for [`Rope`]. 103 | //! 104 | //! # Low-level APIs 105 | //! 106 | //! AnyRope also provides access to some of its low-level APIs, enabling client 107 | //! code to efficiently work with a [`Rope`]'s data and implement new 108 | //! functionality. The most important of those API's are: 109 | //! 110 | //! - The [`chunk_at_*()`][Rope::chunk_at_measure] chunk-fetching methods of 111 | //! [`Rope`] and [`RopeSlice`]. 112 | //! - The [`Chunks`](iter::Chunks) iterator. 113 | //! - The functions in `slice_utils` for operating on [`&[M]`][Measurable] 114 | //! slices. 115 | //! 116 | //! As a reminder, if you notice similarities with the AnyRope crate, it is 117 | //! because this is a heavily modified fork of it. 118 | #![allow( 119 | clippy::collapsible_if, 120 | clippy::inline_always, 121 | clippy::needless_return, 122 | clippy::redundant_field_names, 123 | clippy::type_complexity 124 | )] 125 | 126 | mod rope; 127 | mod rope_builder; 128 | mod slice; 129 | mod slice_utils; 130 | mod tree; 131 | 132 | pub mod iter; 133 | 134 | use std::{ 135 | cmp::Ordering, 136 | fmt::Debug, 137 | ops::{Add, Bound, Range, RangeFrom, RangeFull, RangeTo, Sub}, 138 | }; 139 | 140 | pub use crate::{ 141 | rope::Rope, 142 | rope_builder::RopeBuilder, 143 | slice::RopeSlice, 144 | tree::{max_children, max_len}, 145 | }; 146 | 147 | /// A trait defining a comparison that must panic if there is ever ambiguity 148 | /// about the ordering in a given struct. 149 | pub trait FallibleOrd { 150 | /// A comparison that can panic. 151 | /// 152 | /// This comparison should panic with the [`unreachable!`] macro, since the 153 | /// panicking code is supposed to be unreachable from within `any-rope`. 154 | /// 155 | /// Here's an example of how this function should be implemented: 156 | /// 157 | /// ```rust 158 | /// # use std::cmp::Ordering; 159 | /// # use any_rope::FallibleOrd; 160 | /// struct TwoUsizes(usize, usize); 161 | /// 162 | /// impl FallibleOrd for TwoUsizes { 163 | /// fn fallible_cmp(&self, other: &Self) -> Ordering { 164 | /// use Ordering::*; 165 | /// let cmp_0 = self.0.cmp(&other.0); 166 | /// let cmp_1 = self.1.cmp(&other.1); 167 | /// 168 | /// match (cmp_0, cmp_1) { 169 | /// (Less, Less) => Less, 170 | /// (Less, Equal) => Less, 171 | /// (Equal, Less) => Less, 172 | /// (Equal, Equal) => Equal, 173 | /// (Equal, Greater) => Greater, 174 | /// (Greater, Equal) => Greater, 175 | /// (Greater, Greater) => todo!(), 176 | /// (Less, Greater) | (Greater, Less) => unreachable!( 177 | /// "Ambiguous comparison, report this as a bug on the \ 178 | /// AnyRope crate" 179 | /// ), 180 | /// } 181 | /// } 182 | /// } 183 | /// ``` 184 | /// 185 | /// Note that, if all values are equal, then the comparison is equal. If at 186 | /// least one value is greater or lesse, then the comparison follows that 187 | /// value. But if there are greater and lesser values at the same time, then 188 | /// something has failed within `any-rope` itself, and that should be 189 | /// reported as a bug. 190 | fn fallible_cmp(&self, other: &Self) -> Ordering; 191 | } 192 | 193 | /// A object that has a user defined size, that can be interpreted by a 194 | /// [`Rope`]. 195 | pub trait Measurable: Clone { 196 | /// This type is what will be used to query, iterate, modify, and slice up 197 | /// the [`Rope`]. 198 | /// 199 | /// It needs to be light, since it will be heavily utilized from within 200 | /// `any-rope`, and needs to be malleable, such that it can be compared, 201 | /// added and subtracted at will by the rope. 202 | /// 203 | /// Normally, in order to query, iterate, or modify the rope, the various 204 | /// methods take in a comparator function. This function offers flexibility 205 | /// in how one searches within the rope, for example: 206 | /// 207 | /// ```rust 208 | /// # use std::{ 209 | /// # cmp::Ordering, 210 | /// # ops::{Add, Sub}, 211 | /// # }; 212 | /// # use any_rope::{FallibleOrd, Measurable, Rope}; 213 | /// #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] 214 | /// struct TwoWidths(usize, usize); 215 | /// 216 | /// impl TwoWidths { 217 | /// fn first_cmp(&self, other: &Self) -> Ordering { 218 | /// self.0.cmp(&other.0) 219 | /// } 220 | /// 221 | /// fn second_cmp(&self, other: &Self) -> Ordering { 222 | /// self.1.cmp(&other.1) 223 | /// } 224 | /// } 225 | /// 226 | /// impl FallibleOrd for TwoWidths { 227 | /// fn fallible_cmp(&self, other: &Self) -> Ordering { 228 | /// use Ordering::*; 229 | /// let cmp_0 = self.0.cmp(&other.0); 230 | /// let cmp_1 = self.1.cmp(&other.1); 231 | /// 232 | /// match (cmp_0, cmp_1) { 233 | /// (Less, Less) => Less, 234 | /// (Less, Equal) => Less, 235 | /// (Equal, Less) => Less, 236 | /// (Equal, Equal) => Equal, 237 | /// (Equal, Greater) => Greater, 238 | /// (Greater, Equal) => Greater, 239 | /// (Greater, Greater) => todo!(), 240 | /// (Less, Greater) | (Greater, Less) => unreachable!( 241 | /// "Ambiguous comparison, report this as a bug on the \ 242 | /// AnyRope crate" 243 | /// ), 244 | /// } 245 | /// } 246 | /// } 247 | /// 248 | /// // ... Implementation of `Add` and `Sub` for `TwoWidths`. 249 | /// 250 | /// # impl Add for TwoWidths { 251 | /// # type Output = Self; 252 | /// 253 | /// # fn add(self, other: Self) -> Self::Output { 254 | /// # Self(self.0 + other.0, self.1 + other.1) 255 | /// # } 256 | /// # } 257 | /// # impl Sub for TwoWidths { 258 | /// # type Output = Self; 259 | /// 260 | /// # fn sub(self, other: Self) -> Self::Output { 261 | /// # Self(self.0 - other.0, self.1 - other.1) 262 | /// # } 263 | /// # } 264 | /// #[derive(Clone, Copy, PartialEq, Eq)] 265 | /// struct MyStruct(TwoWidths); 266 | /// 267 | /// impl Measurable for MyStruct { 268 | /// type Measure = TwoWidths; 269 | /// 270 | /// fn measure(&self) -> Self::Measure { 271 | /// self.0 272 | /// } 273 | /// } 274 | /// ``` 275 | /// 276 | /// With the `TwoWidths::first_cmp` and `TwoWidths::second_cmp`, you can 277 | /// search with two different variables within the rope, similarly to how 278 | /// regular ropes let you search by byte, char, or line. 279 | /// 280 | /// Note, however, that this type also requires `PartialOrd` and `Ord`. That 281 | /// is because, internally, `any-rope` needs those comparison functions to 282 | /// sort itself out. These implementations also cannot be derived by Rust, 283 | /// and need to be 284 | type Measure: Debug 285 | + Default 286 | + Clone 287 | + Copy 288 | + PartialEq 289 | + Eq 290 | + Add 291 | + Sub 292 | + FallibleOrd; 293 | 294 | /// The measure of this element, it need not be the actual lenght in bytes, 295 | /// but just a representative value, to be fed to the [`Rope`]. 296 | fn measure(&self) -> Self::Measure; 297 | } 298 | 299 | /// A struct meant for testing and exemplification 300 | /// 301 | /// Its [`measure`][Measurable::measure] is always equal to the number within. 302 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 303 | pub struct Width(pub usize); 304 | 305 | impl PartialOrd for Width { 306 | fn partial_cmp(&self, other: &Self) -> Option { 307 | Some(self.cmp(other)) 308 | } 309 | } 310 | 311 | impl Ord for Width { 312 | fn cmp(&self, other: &Self) -> Ordering { 313 | self.0.fallible_cmp(&other.0) 314 | } 315 | } 316 | 317 | impl FallibleOrd for usize { 318 | fn fallible_cmp(&self, other: &Self) -> Ordering { 319 | self.cmp(other) 320 | } 321 | } 322 | 323 | impl Measurable for Width { 324 | type Measure = usize; 325 | 326 | fn measure(&self) -> Self::Measure { 327 | self.0 328 | } 329 | } 330 | 331 | //============================================================== 332 | // Error reporting types. 333 | 334 | /// AnyRope's result type. 335 | pub type Result = std::result::Result>; 336 | 337 | /// AnyRope's error type. 338 | #[derive(Clone, Copy)] 339 | #[non_exhaustive] 340 | pub enum Error { 341 | /// Indicates that the passed index was out of bounds. 342 | /// 343 | /// Contains the index attempted and the actual length of the 344 | /// [`Rope`]/[`RopeSlice`], in that order. 345 | IndexOutOfBounds(usize, usize), 346 | 347 | /// Indicates that the passed measure was out of bounds. 348 | /// 349 | /// Contains the index attempted and the actual measure of the 350 | /// [`Rope`]/[`RopeSlice`], in that order. 351 | MeasureOutOfBounds(M::Measure, M::Measure), 352 | 353 | /// Indicates that a reversed index range (end < start) was encountered. 354 | /// 355 | /// Contains the [start, end) indices of the range, in that order. 356 | IndexRangeInvalid(usize, usize), 357 | 358 | /// Indicates that a reversed measure range (end < start) was 359 | /// encountered. 360 | /// 361 | /// Contains the [start, end) measures of the range, in that order. 362 | MeasureRangeInvalid(Option, Option), 363 | 364 | /// Indicates that the passed index range was partially or fully out of 365 | /// bounds. 366 | /// 367 | /// Contains the [start, end) indices of the range and the actual 368 | /// length of the [`Rope`]/[`RopeSlice`], in that order. 369 | /// When either the start or end are [`None`], that indicates a half-open 370 | /// range. 371 | IndexRangeOutOfBounds(Option, Option, usize), 372 | 373 | /// Indicates that the passed measure range was partially or fully out of 374 | /// bounds. 375 | /// 376 | /// Contains the [start, end) measures of the range and the actual 377 | /// measure of the [`Rope`]/[`RopeSlice`], in that order. 378 | /// When either the start or end are [`None`], that indicates a half-open 379 | /// range. 380 | MeasureRangeOutOfBounds(Option, Option, M::Measure), 381 | } 382 | 383 | impl std::fmt::Debug for Error { 384 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 385 | match *self { 386 | Error::IndexOutOfBounds(index, len) => { 387 | write!( 388 | f, 389 | "Index out of bounds: index {}, Rope/RopeSlice length {}", 390 | index, len 391 | ) 392 | } 393 | Error::MeasureOutOfBounds(measure, max) => { 394 | write!( 395 | f, 396 | "Measure out of bounds: measure {:?}, Rope/RopeSlice measure {:?}", 397 | measure, max 398 | ) 399 | } 400 | Error::IndexRangeInvalid(start_index, end_index) => { 401 | write!( 402 | f, 403 | "Invalid index range {}..{}: start must be <= end", 404 | start_index, end_index 405 | ) 406 | } 407 | Error::MeasureRangeInvalid(start_measure, end_measure) => { 408 | write!( 409 | f, 410 | "Invalid measure range {:?}..{:?}: start must be <= end", 411 | start_measure, end_measure 412 | ) 413 | } 414 | Error::IndexRangeOutOfBounds(start, end, len) => { 415 | write!(f, "Index range out of bounds: index range ")?; 416 | write_range(f, start, end)?; 417 | write!(f, ", Rope/RopeSlice byte length {}", len) 418 | } 419 | Error::MeasureRangeOutOfBounds(start, end, measure) => { 420 | write!(f, "Measure range out of bounds: measure range ")?; 421 | write_range(f, start, end)?; 422 | write!(f, ", Rope/RopeSlice measure {:?}", measure) 423 | } 424 | } 425 | } 426 | } 427 | 428 | impl std::error::Error for Error {} 429 | 430 | impl std::fmt::Display for Error { 431 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 432 | // Just re-use the debug impl. 433 | std::fmt::Debug::fmt(self, f) 434 | } 435 | } 436 | 437 | fn write_range( 438 | f: &mut std::fmt::Formatter<'_>, 439 | start_idx: Option, 440 | end_idx: Option, 441 | ) -> std::fmt::Result { 442 | match (start_idx, end_idx) { 443 | (None, None) => write!(f, ".."), 444 | (None, Some(end)) => write!(f, "..{:?}", end), 445 | (Some(start), None) => write!(f, "{:?}..", start), 446 | (Some(start), Some(end)) => write!(f, "{:?}..{:?}", start, end), 447 | } 448 | } 449 | 450 | //============================================================== 451 | // Range handling utilities. 452 | 453 | #[inline(always)] 454 | fn start_bound_to_num(b: Bound<&usize>) -> Option { 455 | match b { 456 | Bound::Included(n) => Some(*n), 457 | Bound::Excluded(n) => Some(*n + 1), 458 | Bound::Unbounded => None, 459 | } 460 | } 461 | 462 | #[inline(always)] 463 | fn end_bound_to_num(b: Bound<&usize>) -> Option { 464 | match b { 465 | Bound::Included(n) => Some(*n + 1), 466 | Bound::Excluded(n) => Some(*n), 467 | Bound::Unbounded => None, 468 | } 469 | } 470 | 471 | mod hidden { 472 | use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; 473 | 474 | pub trait Internal {} 475 | 476 | impl Internal for Range {} 477 | impl Internal for RangeFrom {} 478 | impl Internal for RangeTo {} 479 | impl Internal for RangeFull {} 480 | } 481 | 482 | pub trait MeasureRange: hidden::Internal { 483 | fn start_bound(&self) -> Option<&M::Measure>; 484 | 485 | fn end_bound(&self) -> Option<&M::Measure>; 486 | } 487 | 488 | impl MeasureRange for Range { 489 | fn start_bound(&self) -> Option<&M::Measure> { 490 | Some(&self.start) 491 | } 492 | 493 | fn end_bound(&self) -> Option<&M::Measure> { 494 | Some(&self.end) 495 | } 496 | } 497 | 498 | impl MeasureRange for RangeFrom { 499 | fn start_bound(&self) -> Option<&M::Measure> { 500 | Some(&self.start) 501 | } 502 | 503 | fn end_bound(&self) -> Option<&M::Measure> { 504 | None 505 | } 506 | } 507 | 508 | impl MeasureRange for RangeTo { 509 | fn start_bound(&self) -> Option<&M::Measure> { 510 | None 511 | } 512 | 513 | fn end_bound(&self) -> Option<&M::Measure> { 514 | Some(&self.end) 515 | } 516 | } 517 | 518 | impl MeasureRange for RangeFull { 519 | fn start_bound(&self) -> Option<&M::Measure> { 520 | None 521 | } 522 | 523 | fn end_bound(&self) -> Option<&M::Measure> { 524 | None 525 | } 526 | } 527 | 528 | #[inline(always)] 529 | fn measures_from_range( 530 | range: &impl MeasureRange, 531 | limit: M::Measure, 532 | ) -> Result<(M::Measure, M::Measure), M> { 533 | #[cfg(debug_assertions)] 534 | { 535 | if let Some(start) = range.start_bound() { 536 | assert_default_is_lowest::(start); 537 | } 538 | if let Some(end) = range.end_bound() { 539 | assert_default_is_lowest::(end); 540 | } 541 | } 542 | 543 | match (range.start_bound(), range.end_bound()) { 544 | (None, None) => Ok((M::Measure::default(), limit)), 545 | (None, Some(end)) => { 546 | if end.fallible_cmp(&limit).is_gt() { 547 | Err(Error::MeasureRangeOutOfBounds(None, Some(*end), limit)) 548 | } else { 549 | Ok((M::Measure::default(), *end)) 550 | } 551 | } 552 | (Some(start), None) => { 553 | if start.fallible_cmp(&limit).is_gt() { 554 | Err(Error::MeasureRangeOutOfBounds(Some(*start), None, limit)) 555 | } else { 556 | Ok((*start, limit)) 557 | } 558 | } 559 | 560 | (Some(start), Some(end)) => { 561 | if start.fallible_cmp(end).is_gt() { 562 | Err(Error::MeasureRangeInvalid(Some(*start), Some(*end))) 563 | } else if end.fallible_cmp(&limit).is_gt() || start.fallible_cmp(&limit).is_gt() { 564 | Err(Error::MeasureRangeOutOfBounds( 565 | Some(*start), 566 | Some(*end), 567 | limit, 568 | )) 569 | } else { 570 | Ok((*start, *end)) 571 | } 572 | } 573 | } 574 | } 575 | 576 | //============================================================== 577 | // Other utilities. 578 | 579 | fn assert_default_is_lowest(cmp: &M::Measure) { 580 | assert!( 581 | M::Measure::default().fallible_cmp(cmp).is_le(), 582 | "{:?} (Measure::default()) is supposed to be the smallest possible value for \ 583 | Measurable::Measure, and yet {:?} is smaller", 584 | M::Measure::default(), 585 | cmp 586 | ) 587 | } 588 | 589 | fn fallible_saturating_sub(lhs: T, rhs: T) -> T 590 | where 591 | T: Default + FallibleOrd + Sub, 592 | { 593 | if lhs.fallible_cmp(&rhs).is_le() { 594 | T::default() 595 | } else { 596 | lhs - rhs 597 | } 598 | } 599 | 600 | fn fallible_min(lhs: T, rhs: T) -> T { 601 | if lhs.fallible_cmp(&rhs).is_le() { 602 | lhs 603 | } else { 604 | rhs 605 | } 606 | } 607 | 608 | fn fallible_max(lhs: T, rhs: T) -> T { 609 | if lhs.fallible_cmp(&rhs).is_ge() { 610 | lhs 611 | } else { 612 | rhs 613 | } 614 | } 615 | -------------------------------------------------------------------------------- /src/rope_builder.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use smallvec::SmallVec; 4 | 5 | use crate::{ 6 | rope::Rope, 7 | tree::{max_children, max_len, min_len, BranchChildren, LeafSlice, Node}, 8 | FallibleOrd, Measurable, 9 | }; 10 | 11 | /// An efficient incremental [`Rope`] builder. 12 | /// 13 | /// This is used to efficiently build ropes from sequences of [`M`][Measurable] 14 | /// chunks. 15 | /// 16 | /// Unlike repeatedly calling [`Rope::insert()`] on the end of a rope, 17 | /// this API runs in time linear to the amount of data fed to it, and 18 | /// is overall much faster. 19 | /// 20 | /// # Example 21 | /// ``` 22 | /// # use any_rope::RopeBuilder; 23 | /// # use any_rope::Width; 24 | /// # 25 | /// let mut builder = RopeBuilder::new(); 26 | /// 27 | /// builder.append(Width(1)); 28 | /// builder.append(Width(2)); 29 | /// builder.append(Width(70)); 30 | /// builder.append(Width(0)); 31 | /// builder.append(Width(0)); 32 | /// 33 | /// let rope = builder.finish(); 34 | /// 35 | /// assert_eq!( 36 | /// rope, 37 | /// [Width(1), Width(2), Width(70), Width(0), Width(0)].as_slice() 38 | /// ); 39 | /// ``` 40 | #[derive(Debug, Clone)] 41 | pub struct RopeBuilder 42 | where 43 | M: Measurable, 44 | [(); max_len::()]: Sized, 45 | [(); max_children::()]: Sized, 46 | { 47 | stack: SmallVec<[Arc>; 4]>, 48 | buffer: Vec, 49 | last_chunk_len: usize, 50 | } 51 | 52 | impl RopeBuilder 53 | where 54 | M: Measurable, 55 | [(); max_len::()]: Sized, 56 | [(); max_children::()]: Sized, 57 | { 58 | /// Creates a new RopeBuilder, ready for input. 59 | pub fn new() -> Self { 60 | RopeBuilder { 61 | stack: { 62 | let mut stack = SmallVec::new(); 63 | stack.push(Arc::new(Node::new())); 64 | stack 65 | }, 66 | buffer: Vec::new(), 67 | last_chunk_len: 0, 68 | } 69 | } 70 | 71 | /// Appends `chunk` to the end of the in-progress [`Rope`]. 72 | /// 73 | /// Call this method repeatedly to incrementally build up a 74 | /// [`Rope`]. The passed slice chunk can be as large or small as 75 | /// desired, but larger chunks are more efficient. 76 | pub fn append_slice(&mut self, chunk: &[M]) { 77 | self.append_internal(chunk, false); 78 | } 79 | 80 | /// Appends a single [`M`][Measurable] to the end of the in-progress 81 | /// [`Rope`] 82 | /// 83 | /// Call this method repeatedly to incrementally build up a [`Rope`]. 84 | pub fn append(&mut self, element: M) { 85 | self.append_internal(&[element], false); 86 | } 87 | 88 | /// Finishes the build, and returns the [`Rope`]. 89 | /// 90 | /// Note: this method consumes the builder. If you want to continue 91 | /// building other ropes with the same prefix, you can clone the builder 92 | /// before calling this function. 93 | pub fn finish(mut self) -> Rope { 94 | // Append the last leaf 95 | self.append_internal(&[], true); 96 | self.finish_internal(true) 97 | } 98 | 99 | /// Builds a rope all at once from a single slice. 100 | /// 101 | /// This avoids the creation and use of the internal buffer. This is 102 | /// for internal use only, because the public-facing API has 103 | /// [Rope::from_slice()], which actually uses this for its implementation. 104 | pub(crate) fn build_at_once(mut self, chunk: &[M]) -> Rope { 105 | self.append_internal(chunk, true); 106 | self.finish_internal(true) 107 | } 108 | 109 | /// NOT PART OF THE PUBLIC API (hidden from docs for a reason!). 110 | /// 111 | /// Appends `contents` to the in-progress rope as a single leaf 112 | /// node (chunk). This is useful for building ropes with specific 113 | /// chunk configurations for testing purposes. It will happily append 114 | /// both empty and more-than-max-size chunks. 115 | /// 116 | /// This makes no attempt to be consistent with the standard 117 | /// [RopeBuilder::append()] method, and should not be used in 118 | /// conjunction with it. 119 | #[doc(hidden)] 120 | pub fn _append_chunk(&mut self, contents: &[M]) { 121 | self.append_leaf_node(Arc::new(Node::Leaf(LeafSlice::from_slice(contents)))); 122 | } 123 | 124 | /// NOT PART OF THE PUBLIC API (hidden from docs for a reason!). 125 | /// 126 | /// Finishes the build without doing any tree fixing to adhere 127 | /// to the btree invariants. To be used with [RopeBuilder::append_chunk()] 128 | /// to construct ropes with specific chunk boundaries for testing. 129 | #[doc(hidden)] 130 | pub fn _finish_no_fix(self) -> Rope { 131 | self.finish_internal(false) 132 | } 133 | 134 | //----------------------------------------------------------------- 135 | 136 | // Internal workings of `append()`. 137 | fn append_internal(&mut self, chunk: &[M], is_last_chunk: bool) { 138 | let mut chunk = chunk; 139 | 140 | // Repeatedly chop slices off the end of the input, creating 141 | // leaf nodes out of them and appending them to the tree. 142 | while !chunk.is_empty() || (!self.buffer.is_empty() && is_last_chunk) { 143 | // Get the slice for the next leaf 144 | let (leaf_slice, remainder) = self.get_next_leaf_slice(chunk, is_last_chunk); 145 | chunk = remainder; 146 | 147 | self.last_chunk_len = chunk.len(); 148 | 149 | // Append the leaf to the rope 150 | match leaf_slice { 151 | NextSlice::None => break, 152 | NextSlice::UseBuffer => { 153 | let leaf_slice = LeafSlice::from_slice(self.buffer.as_slice()); 154 | self.append_leaf_node(Arc::new(Node::Leaf(leaf_slice))); 155 | self.buffer.clear(); 156 | } 157 | NextSlice::Slice(s) => { 158 | self.append_leaf_node(Arc::new(Node::Leaf(LeafSlice::from_slice(s)))); 159 | } 160 | } 161 | } 162 | } 163 | 164 | // Internal workings of `finish()`. 165 | // 166 | // When `fix_tree` is false, the resulting node tree is NOT fixed up 167 | // to adhere to the btree invariants. This is useful for some testing 168 | // code. But generally, `fix_tree` should be set to true. 169 | fn finish_internal(mut self, fix_tree: bool) -> Rope { 170 | // Zip up all the remaining nodes on the stack 171 | let mut stack_index = self.stack.len() - 1; 172 | while stack_index >= 1 { 173 | let node = self.stack.pop().unwrap(); 174 | if let Node::Branch(ref mut children) = *Arc::make_mut(&mut self.stack[stack_index - 1]) 175 | { 176 | children.push((node.info(), node)); 177 | } else { 178 | unreachable!(); 179 | } 180 | stack_index -= 1; 181 | } 182 | 183 | // Create the rope. 184 | let mut rope = Rope { 185 | root: self.stack.pop().unwrap(), 186 | }; 187 | 188 | // Fix up the tree to be well-formed. 189 | if fix_tree { 190 | Arc::make_mut(&mut rope.root).zip_fix_right(); 191 | if self.last_chunk_len < min_len::() && self.last_chunk_len != rope.len() 192 | { 193 | // Merge the last chunk if it was too small. 194 | let index = 195 | rope.measure() - rope.index_to_measure(rope.len() - self.last_chunk_len); 196 | Arc::make_mut(&mut rope.root).fix_tree_seam(index, &M::Measure::fallible_cmp); 197 | } 198 | rope.pull_up_singular_nodes(); 199 | } 200 | 201 | return rope; 202 | } 203 | 204 | // Returns (next_leaf_slice, remaining_slice) 205 | #[inline(always)] 206 | fn get_next_leaf_slice<'a>( 207 | &mut self, 208 | slice: &'a [M], 209 | is_last_chunk: bool, 210 | ) -> (NextSlice<'a, M>, &'a [M]) { 211 | assert!( 212 | self.buffer.len() < max_len::(), 213 | "RopeBuilder: buffer is already full when receiving a chunk! This should never happen!", 214 | ); 215 | 216 | // Simplest case: empty buffer and enough in `slice` for a full 217 | // chunk, so just chop a chunk off from `slice` and use that. 218 | if self.buffer.is_empty() && slice.len() >= max_len::() { 219 | let split_index = max_len::().min(slice.len() - 1); 220 | return ( 221 | NextSlice::Slice(&slice[..split_index]), 222 | &slice[split_index..], 223 | ); 224 | } 225 | // If the buffer + `slice` is enough for a full chunk, push enough 226 | // of `slice` onto the buffer to fill it and use that. 227 | else if (slice.len() + self.buffer.len()) >= max_len::() { 228 | let split_index = max_len::() - self.buffer.len(); 229 | self.buffer.extend_from_slice(&slice[..split_index]); 230 | return (NextSlice::UseBuffer, &slice[split_index..]); 231 | } 232 | // If we don't have enough slice for a full chunk. 233 | else { 234 | // If it's our last chunk, wrap it all up! 235 | if is_last_chunk { 236 | if self.buffer.is_empty() { 237 | return if slice.is_empty() { 238 | (NextSlice::None, &[]) 239 | } else { 240 | (NextSlice::Slice(slice), &[]) 241 | }; 242 | } else { 243 | self.buffer.extend_from_slice(slice); 244 | return (NextSlice::UseBuffer, &[]); 245 | } 246 | } 247 | // Otherwise, just push to the buffer. 248 | else { 249 | self.buffer.extend_from_slice(slice); 250 | return (NextSlice::None, &[]); 251 | } 252 | } 253 | } 254 | 255 | fn append_leaf_node(&mut self, leaf: Arc>) { 256 | let last = self.stack.pop().unwrap(); 257 | match *last { 258 | Node::Leaf(_) => { 259 | if last.leaf_slice().is_empty() { 260 | self.stack.push(leaf); 261 | } else { 262 | let mut children = BranchChildren::new(); 263 | children.push((last.info(), last)); 264 | children.push((leaf.info(), leaf)); 265 | self.stack.push(Arc::new(Node::Branch(children))); 266 | } 267 | } 268 | 269 | Node::Branch(_) => { 270 | self.stack.push(last); 271 | let mut left = leaf; 272 | let mut stack_index = (self.stack.len() - 1) as isize; 273 | loop { 274 | if stack_index < 0 { 275 | // We're above the root, so do a root split. 276 | let mut children = BranchChildren::new(); 277 | children.push((left.info(), left)); 278 | self.stack.insert(0, Arc::new(Node::Branch(children))); 279 | break; 280 | } else if self.stack[stack_index as usize].child_count() 281 | < (max_children::() - 1) 282 | { 283 | // There's room to add a child, so do that. 284 | Arc::make_mut(&mut self.stack[stack_index as usize]) 285 | .children_mut() 286 | .push((left.info(), left)); 287 | break; 288 | } else { 289 | // Not enough room to fit a child, so split. 290 | left = Arc::new(Node::Branch( 291 | Arc::make_mut(&mut self.stack[stack_index as usize]) 292 | .children_mut() 293 | .push_split((left.info(), left)), 294 | )); 295 | std::mem::swap(&mut left, &mut self.stack[stack_index as usize]); 296 | stack_index -= 1; 297 | } 298 | } 299 | } 300 | } 301 | } 302 | } 303 | 304 | impl Default for RopeBuilder 305 | where 306 | M: Measurable, 307 | [(); max_len::()]: Sized, 308 | [(); max_children::()]: Sized, 309 | { 310 | fn default() -> Self { 311 | Self::new() 312 | } 313 | } 314 | 315 | enum NextSlice<'a, M> 316 | where 317 | M: Measurable, 318 | [(); max_len::()]: Sized, 319 | [(); max_children::()]: Sized, 320 | { 321 | None, 322 | UseBuffer, 323 | Slice(&'a [M]), 324 | } 325 | 326 | //=========================================================================== 327 | 328 | #[cfg(test)] 329 | mod tests { 330 | use super::*; 331 | use crate::Width; 332 | 333 | /// 70 elements, total width of 135. 334 | fn lorem_ipsum() -> Vec { 335 | (0..70) 336 | .map(|num| match num % 14 { 337 | 0 | 7 => Width(1), 338 | 1 | 8 => Width(2), 339 | 2 => Width(4), 340 | 3 | 10 => Width(0), 341 | 4 | 11 => Width(0), 342 | 5 => Width(5), 343 | 6 => Width(1), 344 | 9 => Width(8), 345 | 12 => Width(3), 346 | 13 => Width(0), 347 | _ => unreachable!(), 348 | }) 349 | .collect() 350 | } 351 | 352 | #[test] 353 | fn rope_builder_01() { 354 | let mut builder = RopeBuilder::new(); 355 | 356 | for _ in 0..5 { 357 | builder.append_slice(&[Width(1), Width(2), Width(4), Width(0), Width(0)]); 358 | builder.append_slice(&[Width(5), Width(1)]); 359 | builder.append_slice(&[Width(1), Width(2), Width(8), Width(0), Width(0)]); 360 | builder.append_slice(&[Width(3), Width(0)]); 361 | } 362 | 363 | let rope = builder.finish(); 364 | 365 | assert_eq!(rope, lorem_ipsum()); 366 | 367 | rope.assert_integrity(); 368 | rope.assert_invariants(); 369 | } 370 | 371 | #[test] 372 | fn rope_builder_02() { 373 | let mut builder = RopeBuilder::new(); 374 | 375 | for _ in 0..5 { 376 | builder.append(Width(1)); 377 | builder.append(Width(2)); 378 | builder.append(Width(4)); 379 | builder.append(Width(0)); 380 | builder.append(Width(0)); 381 | builder.append_slice(&[Width(5), Width(1)]); 382 | builder.append(Width(1)); 383 | builder.append(Width(2)); 384 | builder.append(Width(8)); 385 | builder.append(Width(0)); 386 | builder.append(Width(0)); 387 | builder.append_slice(&[Width(3), Width(0)]); 388 | } 389 | 390 | let rope = builder.finish(); 391 | 392 | assert_eq!(rope, lorem_ipsum()); 393 | 394 | rope.assert_integrity(); 395 | rope.assert_invariants(); 396 | } 397 | 398 | #[test] 399 | fn rope_builder_default_01() { 400 | let mut builder = RopeBuilder::default(); 401 | 402 | for _ in 0..5 { 403 | builder.append_slice(&[Width(1), Width(2), Width(4), Width(0), Width(0)]); 404 | builder.append_slice(&[Width(5), Width(1)]); 405 | builder.append_slice(&[Width(1), Width(2), Width(8), Width(0), Width(0)]); 406 | builder.append_slice(&[Width(3), Width(0)]); 407 | } 408 | 409 | let rope = builder.finish(); 410 | 411 | assert_eq!(rope, lorem_ipsum()); 412 | 413 | rope.assert_integrity(); 414 | rope.assert_invariants(); 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /src/slice_utils.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | use crate::Measurable; 4 | 5 | #[inline(always)] 6 | pub fn measure_of(slice: &[M]) -> M::Measure { 7 | slice 8 | .iter() 9 | .map(|measurable| measurable.measure()) 10 | .fold(M::Measure::default(), |accum, measure| accum + measure) 11 | } 12 | 13 | /// Gets the width sum up to a given `index` in the `slice`. 14 | #[inline(always)] 15 | pub fn index_to_measure(slice: &[M], index: usize) -> M::Measure { 16 | slice 17 | .iter() 18 | .take(index) 19 | .map(|measurable| measurable.measure()) 20 | .fold(M::Measure::default(), |accum, measure| accum + measure) 21 | } 22 | 23 | /// Finds the index of the element whose starting width sum matches `width`. 24 | #[inline(always)] 25 | pub fn start_measure_to_index( 26 | slice: &[M], 27 | start: M::Measure, 28 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 29 | ) -> usize { 30 | let mut index = 0; 31 | let mut accum = M::Measure::default(); 32 | 33 | for measurable in slice { 34 | let measure = measurable.measure(); 35 | let next_accum = accum + measure; 36 | 37 | if cmp(&next_accum, &start).is_gt() 38 | || (cmp(&measure, &M::Measure::default()).is_eq() && cmp(&start, &next_accum).is_eq()) 39 | { 40 | break; 41 | } 42 | accum = next_accum; 43 | index += 1; 44 | } 45 | 46 | index 47 | } 48 | 49 | /// Finds the index of the element whose ending width sum matches `width`. 50 | #[inline(always)] 51 | pub fn end_measure_to_index( 52 | slice: &[M], 53 | end: M::Measure, 54 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 55 | ) -> usize { 56 | let mut index = 0; 57 | let mut accum = M::Measure::default(); 58 | 59 | for measurable in slice { 60 | let measure = measurable.measure(); 61 | // This makes it so that every 0 width node exactly at `width` is also captured. 62 | if cmp(&accum, &end).is_gt() 63 | || (cmp(&measure, &M::Measure::default()).is_ne() && cmp(&end, &accum).is_eq()) 64 | { 65 | break; 66 | } 67 | 68 | accum = accum + measure; 69 | index += 1; 70 | } 71 | 72 | index 73 | } 74 | -------------------------------------------------------------------------------- /src/tree/branch_children.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | cmp::Ordering, 3 | fmt, 4 | iter::{Iterator, Zip}, 5 | slice, 6 | sync::Arc, 7 | }; 8 | 9 | use crate::{ 10 | tree::{max_children, max_len, Node, SliceInfo}, 11 | Measurable, 12 | }; 13 | 14 | /// A fixed-capacity vec of child Arc-pointers and child metadata. 15 | /// 16 | /// The unsafe guts of this.is_le() are implemented in BranchChildrenInternal 17 | /// lower down in this file. 18 | #[derive(Clone)] 19 | #[repr(C)] 20 | pub(crate) struct BranchChildren(inner::BranchChildrenInternal) 21 | where 22 | M: Measurable, 23 | [(); max_len::()]: Sized, 24 | [(); max_children::()]: Sized; 25 | 26 | impl BranchChildren 27 | where 28 | M: Measurable, 29 | [(); max_len::()]: Sized, 30 | [(); max_children::()]: Sized, 31 | { 32 | /// Creates a new empty array. 33 | pub fn new() -> Self { 34 | BranchChildren(inner::BranchChildrenInternal::new()) 35 | } 36 | 37 | /// Current length of the array. 38 | pub fn len(&self) -> usize { 39 | self.0.len() 40 | } 41 | 42 | /// Returns whether the array is full or not. 43 | pub fn is_full(&self) -> bool { 44 | self.len() == max_children::() 45 | } 46 | 47 | /// Access to the nodes array. 48 | pub fn nodes(&self) -> &[Arc>] { 49 | self.0.nodes() 50 | } 51 | 52 | /// Mutable access to the nodes array. 53 | pub fn nodes_mut(&mut self) -> &mut [Arc>] { 54 | self.0.nodes_mut() 55 | } 56 | 57 | /// Access to the info array. 58 | pub fn info(&self) -> &[SliceInfo] { 59 | self.0.info() 60 | } 61 | 62 | /// Mutable access to the info array. 63 | pub fn info_mut(&mut self) -> &mut [SliceInfo] { 64 | self.0.info_mut() 65 | } 66 | 67 | /// Mutable access to both the info and nodes arrays simultaneously. 68 | pub fn data_mut(&mut self) -> (&mut [SliceInfo], &mut [Arc>]) { 69 | self.0.data_mut() 70 | } 71 | 72 | /// Updates the [`SliceInfo`] of the child at `index`. 73 | pub fn update_child_info(&mut self, index: usize) { 74 | let (info, nodes) = self.0.data_mut(); 75 | info[index] = nodes[index].info() 76 | } 77 | 78 | /// Pushes an item into the end of the array. 79 | /// 80 | /// Increases length by one. Panics if already full. 81 | pub fn push(&mut self, item: (SliceInfo, Arc>)) { 82 | self.0.push(item) 83 | } 84 | 85 | /// Pushes an element onto the end of the array, and then splits it in half, 86 | /// returning the right half. 87 | /// 88 | /// This works even when the array is full. 89 | pub fn push_split(&mut self, new_child: (SliceInfo, Arc>)) -> Self { 90 | let r_count = (self.len() + 1) / 2; 91 | let l_count = (self.len() + 1) - r_count; 92 | 93 | let mut right = self.split_off(l_count); 94 | right.push(new_child); 95 | right 96 | } 97 | 98 | /// Attempts to merge two nodes, and if it's too much data to merge 99 | /// equi-distributes it between the two. 100 | /// 101 | /// Returns: 102 | /// 103 | /// - True: merge was successful. 104 | /// - False: merge failed, equidistributed instead. 105 | pub fn merge_distribute(&mut self, index1: usize, index2: usize) -> bool { 106 | assert!(index1 < index2); 107 | assert!(index2 < self.len()); 108 | let remove_right = { 109 | let ((_, node1), (_, node2)) = self.get_two_mut(index1, index2); 110 | let node1 = Arc::make_mut(node1); 111 | let node2 = Arc::make_mut(node2); 112 | match *node1 { 113 | Node::Leaf(ref mut slice1) => { 114 | if let Node::Leaf(ref mut slice2) = *node2 { 115 | if (slice1.len() + slice2.len()) <= max_children::() { 116 | slice1.push_slice(slice2); 117 | true 118 | } else { 119 | let right = slice1.push_slice_split(slice2); 120 | *slice2 = right; 121 | false 122 | } 123 | } else { 124 | panic!("Siblings have different node types"); 125 | } 126 | } 127 | 128 | Node::Branch(ref mut children1) => { 129 | if let Node::Branch(ref mut children2) = *node2 { 130 | if (children1.len() + children2.len()) <= max_children::() { 131 | for _ in 0..children2.len() { 132 | children1.push(children2.remove(0)); 133 | } 134 | true 135 | } else { 136 | children1.distribute_with(children2); 137 | false 138 | } 139 | } else { 140 | panic!("Siblings have different node types"); 141 | } 142 | } 143 | } 144 | }; 145 | 146 | if remove_right { 147 | self.remove(index2); 148 | self.update_child_info(index1); 149 | return true; 150 | } else { 151 | self.update_child_info(index1); 152 | self.update_child_info(index2); 153 | return false; 154 | } 155 | } 156 | 157 | /// Equi-distributes the children between the two child arrays, 158 | /// preserving ordering. 159 | pub fn distribute_with(&mut self, other: &mut Self) { 160 | let r_target_len = (self.len() + other.len()) / 2; 161 | while other.len() < r_target_len { 162 | other.insert(0, self.pop()); 163 | } 164 | while other.len() > r_target_len { 165 | self.push(other.remove(0)); 166 | } 167 | } 168 | 169 | /// If the children are leaf nodes, compacts them to take up the fewest 170 | /// nodes. 171 | pub fn compact_leaves(&mut self) { 172 | if !self.nodes()[0].is_leaf() || self.len() < 2 { 173 | return; 174 | } 175 | 176 | let mut i = 1; 177 | while i < self.len() { 178 | if (self.nodes()[i - 1].leaf_slice().len() + self.nodes()[i].leaf_slice().len()) 179 | <= max_len::() 180 | { 181 | // Scope to contain borrows 182 | { 183 | let ((_, node_l), (_, node_r)) = self.get_two_mut(i - 1, i); 184 | let slice_l = Arc::make_mut(node_l).leaf_slice_mut(); 185 | let slice_r = node_r.leaf_slice(); 186 | slice_l.push_slice(slice_r); 187 | } 188 | self.remove(i); 189 | } else if self.nodes()[i - 1].leaf_slice().len() < max_len::() { 190 | // Scope to contain borrows 191 | { 192 | let ((_, node_l), (_, node_r)) = self.get_two_mut(i - 1, i); 193 | let slice_l = Arc::make_mut(node_l).leaf_slice_mut(); 194 | let slice_r = Arc::make_mut(node_r).leaf_slice_mut(); 195 | let split_index_r = max_len::() - slice_l.len(); 196 | slice_l.push_slice(&slice_r[..split_index_r]); 197 | slice_r.truncate_front(split_index_r); 198 | } 199 | i += 1; 200 | } else { 201 | i += 1; 202 | } 203 | } 204 | 205 | for i in 0..self.len() { 206 | self.update_child_info(i); 207 | } 208 | } 209 | 210 | /// Pops an item off the end of the array and returns it. 211 | /// 212 | /// Decreases length by one. Panics if already empty. 213 | pub fn pop(&mut self) -> (SliceInfo, Arc>) { 214 | self.0.pop() 215 | } 216 | 217 | /// Inserts an item into the the array at the given index. 218 | /// 219 | /// Increases length by one. Panics if already full. Preserves ordering 220 | /// of the other items. 221 | pub fn insert(&mut self, index: usize, item: (SliceInfo, Arc>)) { 222 | self.0.insert(index, item) 223 | } 224 | 225 | /// Inserts an element into a the array, and then splits it in half, 226 | /// returning the right half. 227 | /// 228 | /// This works even when the array is full. 229 | pub fn insert_split( 230 | &mut self, 231 | index: usize, 232 | item: (SliceInfo, Arc>), 233 | ) -> Self { 234 | assert!(self.len() > 0); 235 | assert!(index <= self.len()); 236 | let extra = if index < self.len() { 237 | let extra = self.pop(); 238 | self.insert(index, item); 239 | extra 240 | } else { 241 | item 242 | }; 243 | 244 | self.push_split(extra) 245 | } 246 | 247 | /// Removes the item at the given index from the the array. 248 | /// 249 | /// Decreases length by one. Preserves ordering of the other items. 250 | pub fn remove(&mut self, index: usize) -> (SliceInfo, Arc>) { 251 | self.0.remove(index) 252 | } 253 | 254 | /// Splits the array in two at `index`, returning the right part of the 255 | /// split. 256 | /// 257 | /// TODO: implement this more efficiently. 258 | pub fn split_off(&mut self, index: usize) -> Self { 259 | assert!(index <= self.len()); 260 | 261 | let mut other = BranchChildren::new(); 262 | let count = self.len() - index; 263 | for _ in 0..count { 264 | other.push(self.remove(index)); 265 | } 266 | 267 | other 268 | } 269 | 270 | /// Fetches two children simultaneously, returning mutable references 271 | /// to their info and nodes. 272 | /// 273 | /// `index1` must be less than `index2`. 274 | pub fn get_two_mut( 275 | &mut self, 276 | index1: usize, 277 | index2: usize, 278 | ) -> ( 279 | (&mut SliceInfo, &mut Arc>), 280 | (&mut SliceInfo, &mut Arc>), 281 | ) { 282 | assert!(index1 < index2); 283 | assert!(index2 < self.len()); 284 | 285 | let split_index = index1 + 1; 286 | let (info, nodes) = self.data_mut(); 287 | let (info1, info2) = info.split_at_mut(split_index); 288 | let (nodes1, nodes2) = nodes.split_at_mut(split_index); 289 | 290 | ( 291 | (&mut info1[index1], &mut nodes1[index1]), 292 | ( 293 | &mut info2[index2 - split_index], 294 | &mut nodes2[index2 - split_index], 295 | ), 296 | ) 297 | } 298 | 299 | /// Creates an iterator over the array's items. 300 | pub fn iter(&self) -> Zip>, slice::Iter>>> { 301 | Iterator::zip(self.info().iter(), self.nodes().iter()) 302 | } 303 | 304 | #[allow(clippy::needless_range_loop)] 305 | pub fn combined_info(&self) -> SliceInfo { 306 | let info = self.info(); 307 | let mut acc = SliceInfo::::new::(); 308 | 309 | // Doing this with an explicit loop is notably faster than 310 | // using an iterator in this case. 311 | for i in 0..info.len() { 312 | acc += info[i]; 313 | } 314 | 315 | acc 316 | } 317 | 318 | /// Returns the child index and left-side-accumulated [`SliceInfo`] of the 319 | /// first child that matches the given predicate. 320 | /// 321 | /// If no child matches the predicate, the last child is returned. 322 | #[inline(always)] 323 | pub fn search_by(&self, pred: F) -> (usize, SliceInfo) 324 | where 325 | // (left-accumulated start info, left-accumulated end info) 326 | F: Fn(SliceInfo) -> bool, 327 | { 328 | debug_assert!(self.len() > 0); 329 | 330 | let mut accum = SliceInfo::::new::(); 331 | let mut index = 0; 332 | for info in self.info()[0..(self.len() - 1)].iter() { 333 | let next_accum = accum + *info; 334 | if pred(next_accum) { 335 | break; 336 | } 337 | accum = next_accum; 338 | index += 1; 339 | } 340 | 341 | (index, accum) 342 | } 343 | 344 | /// Returns the child index and left-side-accumulated [`SliceInfo`] of the 345 | /// child that contains the given index. 346 | /// 347 | /// One-past-the end is valid, and will return the last child. 348 | pub fn search_index(&self, index: usize) -> (usize, SliceInfo) { 349 | let (index, accum) = self.search_by(|end| index < end.len as usize); 350 | 351 | debug_assert!( 352 | index <= (accum.len + self.info()[index].len) as usize, 353 | "Index out of bounds." 354 | ); 355 | 356 | (index, accum) 357 | } 358 | 359 | /// Returns the child index and left-side-accumulated [`SliceInfo`]o of the 360 | /// child that contains the given width. 361 | /// 362 | /// One-past-the end is valid, and will return the last child. 363 | pub fn search_start_measure( 364 | &self, 365 | measure: M::Measure, 366 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 367 | ) -> (usize, SliceInfo) { 368 | debug_assert!(self.len() > 0); 369 | 370 | let mut accum = SliceInfo::::new::(); 371 | let mut index = 0; 372 | for info in self.info()[..self.info().len() - 1].iter() { 373 | let new_accum = accum + *info; 374 | 375 | if cmp(&measure, &new_accum.measure).is_le() { 376 | break; 377 | } 378 | 379 | accum = new_accum; 380 | index += 1; 381 | } 382 | 383 | debug_assert!( 384 | cmp(&measure, &(accum.measure + self.info()[index].measure)).is_le(), 385 | "Index out of bounds." 386 | ); 387 | 388 | (index, accum) 389 | } 390 | 391 | /// Returns the child index and left-side-accumulated [`SliceInfo`] of the 392 | /// child that contains the given width. 393 | /// 394 | /// One-past-the end is valid, and will return the last child. 395 | pub fn search_end_measure( 396 | &self, 397 | measure: M::Measure, 398 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 399 | ) -> (usize, SliceInfo) { 400 | // The search uses the `<=` comparison because any slice may end with 0 width 401 | // elements, and the use of the `<` comparison would leave those behind. 402 | let (index, accum) = self.search_by(|end| cmp(&measure, &end.measure).is_lt()); 403 | 404 | debug_assert!( 405 | cmp(&measure, &(accum.measure + self.info()[index].measure)).is_le(), 406 | "Index out of bounds." 407 | ); 408 | 409 | (index, accum) 410 | } 411 | 412 | /// Same as [`search_start_width()`][Self::search_start_width] above, 413 | /// except that it only calulates the left-side-accumulated _measure_, 414 | /// rather than the full [`SliceInfo`]. 415 | /// 416 | /// Return is (child_index, left_acc_measure) 417 | /// 418 | /// One-past-the end is valid, and will return the last child. 419 | #[inline(always)] 420 | pub fn search_measure_only( 421 | &self, 422 | measure: M::Measure, 423 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 424 | ) -> (usize, M::Measure) { 425 | debug_assert!(self.len() > 0); 426 | 427 | let mut accum = M::Measure::default(); 428 | let mut index = 0; 429 | 430 | for info in self.info()[..self.info().len() - 1].iter() { 431 | let new_accum = accum + info.measure; 432 | 433 | if cmp(&measure, &new_accum).is_lt() { 434 | break; 435 | } 436 | accum = new_accum; 437 | index += 1; 438 | } 439 | 440 | debug_assert!( 441 | cmp(&measure, &(accum + self.info()[index].measure)).is_le(), 442 | "Index out of bounds." 443 | ); 444 | 445 | (index, accum) 446 | } 447 | 448 | /// Returns the child indices at the start and end of the given measure 449 | /// range, and returns their left-side-accumulated measure as well. 450 | /// 451 | /// Return is: 452 | /// ( 453 | /// (left_node_index, left_acc_left_side_width), 454 | /// (right_node_index, right_acc_left_side_width), 455 | /// ) 456 | /// 457 | /// One-past-the end is valid, and corresponds to the last child. 458 | #[inline(always)] 459 | pub fn search_measure_range( 460 | &self, 461 | start_bound: M::Measure, 462 | end_bound: M::Measure, 463 | cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering, 464 | ) -> ((usize, M::Measure), (usize, M::Measure)) { 465 | debug_assert!(self.len() > 0); 466 | 467 | let mut accum = M::Measure::default(); 468 | let mut index = 0; 469 | 470 | // Find left child and info 471 | for info in self.info()[..(self.len() - 1)].iter() { 472 | let next_accum = accum + info.measure; 473 | if cmp(&start_bound, &next_accum).is_le() { 474 | break; 475 | } 476 | accum = next_accum; 477 | index += 1; 478 | } 479 | let l_child_i = index; 480 | let l_acc_info = accum; 481 | 482 | // Find right child and info 483 | for info in self.info()[index..(self.len() - 1)].iter() { 484 | let next_accum = accum + info.measure; 485 | if cmp(&end_bound, &next_accum).is_lt() { 486 | break; 487 | } 488 | accum = next_accum; 489 | index += 1; 490 | } 491 | 492 | #[cfg(any(test, debug_assertions))] 493 | assert!( 494 | cmp(&end_bound, &(accum + self.info()[index].measure)).is_le(), 495 | "Index out of bounds." 496 | ); 497 | 498 | ((l_child_i, l_acc_info), (index, accum)) 499 | } 500 | 501 | // Debug function, to help verify tree integrity 502 | pub fn is_info_accurate(&self) -> bool { 503 | for (info, node) in self.info().iter().zip(self.nodes().iter()) { 504 | if *info != node.info() { 505 | return false; 506 | } 507 | } 508 | true 509 | } 510 | } 511 | 512 | impl fmt::Debug for BranchChildren 513 | where 514 | M: Measurable + fmt::Debug, 515 | M::Measure: fmt::Debug, 516 | [(); max_len::()]: Sized, 517 | [(); max_children::()]: Sized, 518 | { 519 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 520 | f.debug_struct("NodeChildren") 521 | .field("len", &self.len()) 522 | .field("info", &&self.info()) 523 | .field("nodes", &&self.nodes()) 524 | .finish() 525 | } 526 | } 527 | 528 | //=========================================================================== 529 | 530 | /// The unsafe guts of [`BranchChildren`][super::BranchChildren], exposed 531 | /// through a safe API. 532 | /// 533 | /// Try to keep this as small as possible, and implement functionality on 534 | /// [`BranchChildren`][super::BranchChildren] via the safe APIs whenever 535 | /// possible. 536 | /// 537 | /// It's split out this way because it was too easy to accidentally access the 538 | /// fixed size arrays directly, leading to memory-unsafety bugs when 539 | /// accidentally accessing elements that are semantically out of bounds. This 540 | /// happened once, and it was a pain to track down--as memory safety bugs often 541 | /// are. 542 | mod inner { 543 | use std::{mem, mem::MaybeUninit, ptr, sync::Arc}; 544 | 545 | use super::{max_children, Node, SliceInfo}; 546 | use crate::{tree::max_len, Measurable}; 547 | 548 | /// This is essentially a fixed-capacity, stack-allocated [Vec<(M, 549 | /// SliceInfo)>]. 550 | #[repr(C)] 551 | pub(crate) struct BranchChildrenInternal 552 | where 553 | M: Measurable, 554 | [(); max_len::()]: Sized, 555 | [(); max_children::()]: Sized, 556 | { 557 | /// An array of the child nodes. 558 | /// INVARIANT: The nodes from 0..len must be initialized 559 | nodes: [MaybeUninit>>; max_children::()], 560 | /// An array of the child node [`SliceInfo`]s 561 | /// INVARIANT: The nodes from 0..len must be initialized 562 | info: [MaybeUninit>; max_children::()], 563 | len: u8, 564 | } 565 | 566 | impl BranchChildrenInternal 567 | where 568 | M: Measurable, 569 | [(); max_len::()]: Sized, 570 | [(); max_children::()]: Sized, 571 | { 572 | /// Creates a new empty array. 573 | #[inline(always)] 574 | pub fn new() -> Self { 575 | // SAFETY: Uninit data is valid for arrays of MaybeUninit. 576 | // len is zero, so it's ok for all of them to be uninit 577 | BranchChildrenInternal { 578 | nodes: unsafe { MaybeUninit::uninit().assume_init() }, 579 | info: unsafe { MaybeUninit::uninit().assume_init() }, 580 | len: 0, 581 | } 582 | } 583 | 584 | /// Current length of the array. 585 | #[inline(always)] 586 | pub fn len(&self) -> usize { 587 | self.len as usize 588 | } 589 | 590 | /// Access to the nodes array. 591 | #[inline(always)] 592 | pub fn nodes(&self) -> &[Arc>] { 593 | // SAFETY: MaybeUninit is layout compatible with T, and 594 | // the nodes from 0..len are guaranteed to be initialized 595 | unsafe { mem::transmute(&self.nodes[..(self.len())]) } 596 | } 597 | 598 | /// Mutable access to the nodes array. 599 | #[inline(always)] 600 | pub fn nodes_mut(&mut self) -> &mut [Arc>] { 601 | // SAFETY: MaybeUninit is layout compatible with T, and 602 | // the nodes from 0..len are guaranteed to be initialized 603 | unsafe { mem::transmute(&mut self.nodes[..(self.len as usize)]) } 604 | } 605 | 606 | /// Access to the info array. 607 | #[inline(always)] 608 | pub fn info(&self) -> &[SliceInfo] { 609 | // SAFETY: MaybeUninit is layout compatible with T, and 610 | // the info from 0..len are guaranteed to be initialized 611 | unsafe { mem::transmute(&self.info[..(self.len())]) } 612 | } 613 | 614 | /// Mutable access to the info array. 615 | #[inline(always)] 616 | pub fn info_mut(&mut self) -> &mut [SliceInfo] { 617 | // SAFETY: MaybeUninit is layout compatible with T, and 618 | // the info from 0..len are guaranteed to be initialized 619 | unsafe { mem::transmute(&mut self.info[..(self.len as usize)]) } 620 | } 621 | 622 | /// Mutable access to both the info and nodes arrays simultaneously. 623 | #[inline(always)] 624 | pub fn data_mut(&mut self) -> (&mut [SliceInfo], &mut [Arc>]) { 625 | // SAFETY: MaybeUninit is layout compatible with T, and 626 | // the info from 0..len are guaranteed to be initialized 627 | ( 628 | unsafe { mem::transmute(&mut self.info[..(self.len as usize)]) }, 629 | unsafe { mem::transmute(&mut self.nodes[..(self.len as usize)]) }, 630 | ) 631 | } 632 | 633 | /// Pushes an item into the end of the array. 634 | /// 635 | /// Increases length by one. Panics if already full. 636 | #[inline(always)] 637 | pub fn push(&mut self, item: (SliceInfo, Arc>)) { 638 | assert!(self.len() < max_children::()); 639 | self.info[self.len()] = MaybeUninit::new(item.0); 640 | self.nodes[self.len as usize] = MaybeUninit::new(item.1); 641 | // We have just initialized both info and node and 0..=len, so we can increase 642 | // it 643 | self.len += 1; 644 | } 645 | 646 | /// Pops an item off the end of the array and returns it. 647 | /// 648 | /// Decreases length by one. Panics if already empty. 649 | #[inline(always)] 650 | pub fn pop(&mut self) -> (SliceInfo, Arc>) { 651 | assert!(self.len() > 0); 652 | self.len -= 1; 653 | // SAFETY: before this, len was long enough to guarantee that both must be init 654 | // We just decreased the length, guaranteeing that the elements will never be 655 | // read again 656 | (unsafe { self.info[self.len()].assume_init() }, unsafe { 657 | ptr::read(&self.nodes[self.len()]).assume_init() 658 | }) 659 | } 660 | 661 | /// Inserts an item into the the array at the given index. 662 | /// 663 | /// Increases length by one. Panics if already full. Preserves ordering 664 | /// of the other items. 665 | #[inline(always)] 666 | pub fn insert(&mut self, index: usize, item: (SliceInfo, Arc>)) { 667 | assert!(index <= self.len()); 668 | assert!(self.len() < max_children::()); 669 | 670 | let len = self.len(); 671 | // This unsafe code simply shifts the elements of the arrays over 672 | // to make space for the new inserted value. The `.info` array 673 | // shifting can be done with a safe call to `copy_within()`. 674 | // However, the `.nodes` array shift cannot, because of the 675 | // specific drop semantics needed for safety. 676 | unsafe { 677 | let ptr = self.nodes.as_mut_ptr(); 678 | ptr::copy(ptr.add(index), ptr.add(index + 1), len - index); 679 | } 680 | self.info.copy_within(index..len, index + 1); 681 | 682 | // We have just made space for the two new elements, so insert them 683 | self.info[index] = MaybeUninit::new(item.0); 684 | self.nodes[index] = MaybeUninit::new(item.1); 685 | // Now that all elements from 0..=len are initialized, we can increase the 686 | // length 687 | self.len += 1; 688 | } 689 | 690 | /// Removes the item at the given index from the the array. 691 | /// 692 | /// Decreases length by one. Preserves ordering of the other items. 693 | #[inline(always)] 694 | pub fn remove(&mut self, index: usize) -> (SliceInfo, Arc>) { 695 | assert!(self.len() > 0); 696 | assert!(index < self.len()); 697 | 698 | // Read out the elements, they must not be touched again. We copy the elements 699 | // after them into them, and decrease the length at the end 700 | let item = (unsafe { self.info[index].assume_init() }, unsafe { 701 | ptr::read(&self.nodes[index]).assume_init() 702 | }); 703 | 704 | let len = self.len(); 705 | // This unsafe code simply shifts the elements of the arrays over 706 | // to fill in the gap left by the removed element. The `.info` 707 | // array shifting can be done with a safe call to `copy_within()`. 708 | // However, the `.nodes` array shift cannot, because of the 709 | // specific drop semantics needed for safety. 710 | unsafe { 711 | let ptr = self.nodes.as_mut_ptr(); 712 | ptr::copy(ptr.add(index + 1), ptr.add(index), len - index - 1); 713 | } 714 | self.info.copy_within((index + 1)..len, index); 715 | 716 | // Now that the gap is filled, decrease the length 717 | self.len -= 1; 718 | 719 | return item; 720 | } 721 | } 722 | 723 | impl Drop for BranchChildrenInternal 724 | where 725 | M: Measurable, 726 | [(); max_len::()]: Sized, 727 | [(); max_children::()]: Sized, 728 | { 729 | fn drop(&mut self) { 730 | // The `.nodes` array contains `MaybeUninit` wrappers, which need 731 | // to be manually dropped if valid. We drop only the valid ones 732 | // here. 733 | for node in &mut self.nodes[..self.len as usize] { 734 | unsafe { ptr::drop_in_place(node.as_mut_ptr()) }; 735 | } 736 | } 737 | } 738 | 739 | impl Clone for BranchChildrenInternal 740 | where 741 | M: Measurable, 742 | [(); max_len::()]: Sized, 743 | [(); max_children::()]: Sized, 744 | { 745 | fn clone(&self) -> Self { 746 | // Create an empty NodeChildrenInternal first, then fill it 747 | let mut clone_array = BranchChildrenInternal::new(); 748 | 749 | // Copy nodes... carefully. 750 | for (clone_arc, arc) in Iterator::zip( 751 | clone_array.nodes[..self.len()].iter_mut(), 752 | self.nodes[..self.len()].iter(), 753 | ) { 754 | *clone_arc = MaybeUninit::new(Arc::clone(unsafe { &*arc.as_ptr() })); 755 | } 756 | 757 | // Copy TextInfo 758 | for (clone_info, info) in Iterator::zip( 759 | clone_array.info[..self.len()].iter_mut(), 760 | self.info[..self.len()].iter(), 761 | ) { 762 | *clone_info = *info; 763 | } 764 | 765 | // Set length 766 | clone_array.len = self.len; 767 | 768 | // Some sanity checks for debug builds 769 | #[cfg(debug_assertions)] 770 | { 771 | for (a, b) in Iterator::zip( 772 | clone_array.info[..clone_array.len()].iter(), 773 | self.info[..self.len()].iter(), 774 | ) { 775 | assert_eq!(unsafe { a.assume_init().len }, unsafe { 776 | b.assume_init().len 777 | },); 778 | } 779 | 780 | for (a, b) in Iterator::zip( 781 | clone_array.nodes[..clone_array.len()].iter(), 782 | self.nodes[..clone_array.len()].iter(), 783 | ) { 784 | assert!(Arc::ptr_eq(unsafe { &*a.as_ptr() }, unsafe { 785 | &*b.as_ptr() 786 | },)); 787 | } 788 | } 789 | 790 | clone_array 791 | } 792 | } 793 | } 794 | 795 | //=========================================================================== 796 | 797 | #[cfg(test)] 798 | mod tests { 799 | use std::sync::Arc; 800 | 801 | use super::*; 802 | use crate::{ 803 | tree::{LeafSlice, Node, SliceInfo}, 804 | Width, 805 | }; 806 | 807 | #[test] 808 | fn search_width_01() { 809 | let mut children = BranchChildren::new(); 810 | children.push(( 811 | SliceInfo::::new::(), 812 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[ 813 | Width(1), 814 | Width(2), 815 | Width(4), 816 | ]))), 817 | )); 818 | children.push(( 819 | SliceInfo::::new::(), 820 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(0), Width(0)]))), 821 | )); 822 | children.push(( 823 | SliceInfo::::new::(), 824 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(9), Width(1)]))), 825 | )); 826 | 827 | children.update_child_info(0); 828 | children.update_child_info(1); 829 | children.update_child_info(2); 830 | 831 | assert_eq!(children.search_start_measure(0, usize::cmp).0, 0); 832 | assert_eq!(children.search_start_measure(1, usize::cmp).0, 0); 833 | assert_eq!(children.search_start_measure(0, usize::cmp).1.measure, 0); 834 | assert_eq!(children.search_start_measure(1, usize::cmp).1.measure, 0); 835 | 836 | assert_eq!(children.search_start_measure(6, usize::cmp).0, 0); 837 | assert_eq!(children.search_start_measure(7, usize::cmp).0, 0); 838 | assert_eq!(children.search_start_measure(6, usize::cmp).1.measure, 0); 839 | assert_eq!(children.search_start_measure(7, usize::cmp).1.measure, 0); 840 | 841 | assert_eq!(children.search_start_measure(7, usize::cmp).0, 0); 842 | assert_eq!(children.search_start_measure(8, usize::cmp).0, 2); 843 | assert_eq!(children.search_start_measure(7, usize::cmp).1.measure, 0); 844 | assert_eq!(children.search_start_measure(8, usize::cmp).1.measure, 7); 845 | 846 | assert_eq!(children.search_start_measure(16, usize::cmp).0, 2); 847 | assert_eq!(children.search_start_measure(17, usize::cmp).0, 2); 848 | assert_eq!(children.search_start_measure(16, usize::cmp).1.measure, 7); 849 | assert_eq!(children.search_start_measure(17, usize::cmp).1.measure, 7); 850 | } 851 | 852 | #[test] 853 | #[should_panic] 854 | fn search_width_02() { 855 | let mut children = BranchChildren::new(); 856 | children.push(( 857 | SliceInfo::::new::(), 858 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[ 859 | Width(1), 860 | Width(2), 861 | Width(4), 862 | ]))), 863 | )); 864 | children.push(( 865 | SliceInfo::::new::(), 866 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(0), Width(0)]))), 867 | )); 868 | children.push(( 869 | SliceInfo::::new::(), 870 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(9), Width(1)]))), 871 | )); 872 | 873 | children.update_child_info(0); 874 | children.update_child_info(1); 875 | children.update_child_info(2); 876 | 877 | children.search_start_measure(18, usize::cmp); 878 | } 879 | 880 | #[test] 881 | fn search_width_range_01() { 882 | let mut children = BranchChildren::new(); 883 | children.push(( 884 | SliceInfo::::new::(), 885 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[ 886 | Width(1), 887 | Width(2), 888 | Width(4), 889 | ]))), 890 | )); 891 | children.push(( 892 | SliceInfo::::new::(), 893 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(0), Width(0)]))), 894 | )); 895 | children.push(( 896 | SliceInfo::::new::(), 897 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(9), Width(1)]))), 898 | )); 899 | 900 | children.update_child_info(0); 901 | children.update_child_info(1); 902 | children.update_child_info(2); 903 | 904 | let at_0_0 = children.search_measure_range(0, 0, usize::cmp); 905 | let at_7_7 = children.search_measure_range(7, 7, usize::cmp); 906 | let at_8_8 = children.search_measure_range(8, 8, usize::cmp); 907 | let at_16_16 = children.search_measure_range(16, 16, usize::cmp); 908 | 909 | assert_eq!((at_0_0.0).0, 0); 910 | assert_eq!((at_0_0.1).0, 0); 911 | assert_eq!((at_0_0.0).1, 0); 912 | assert_eq!((at_0_0.1).1, 0); 913 | 914 | assert_eq!((at_7_7.0).0, 0); 915 | assert_eq!((at_7_7.1).0, 2); 916 | assert_eq!((at_7_7.0).1, 0); 917 | assert_eq!((at_7_7.1).1, 7); 918 | 919 | assert_eq!((at_8_8.0).0, 2); 920 | assert_eq!((at_8_8.1).0, 2); 921 | assert_eq!((at_8_8.0).1, 7); 922 | assert_eq!((at_8_8.1).1, 7); 923 | 924 | assert_eq!((at_16_16.0).0, 2); 925 | assert_eq!((at_16_16.1).0, 2); 926 | assert_eq!((at_16_16.0).1, 7); 927 | assert_eq!((at_16_16.1).1, 7); 928 | 929 | let at_0_7 = children.search_measure_range(0, 7, usize::cmp); 930 | let at_7_16 = children.search_measure_range(7, 16, usize::cmp); 931 | 932 | assert_eq!((at_0_7.0).0, 0); 933 | assert_eq!((at_0_7.1).0, 2); 934 | assert_eq!((at_0_7.0).1, 0); 935 | assert_eq!((at_0_7.1).1, 7); 936 | 937 | assert_eq!((at_7_16.0).0, 0); 938 | assert_eq!((at_7_16.1).0, 2); 939 | assert_eq!((at_7_16.0).1, 0); 940 | assert_eq!((at_7_16.1).1, 7); 941 | 942 | let at_2_4 = children.search_measure_range(6, 8, usize::cmp); 943 | 944 | assert_eq!((at_2_4.0).0, 0); 945 | assert_eq!((at_2_4.1).0, 2); 946 | assert_eq!((at_2_4.0).1, 0); 947 | assert_eq!((at_2_4.1).1, 7); 948 | } 949 | 950 | #[test] 951 | #[should_panic] 952 | fn search_index_range_02() { 953 | let mut children = BranchChildren::new(); 954 | children.push(( 955 | SliceInfo::::new::(), 956 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[ 957 | Width(1), 958 | Width(2), 959 | Width(4), 960 | ]))), 961 | )); 962 | children.push(( 963 | SliceInfo::::new::(), 964 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(0), Width(0)]))), 965 | )); 966 | children.push(( 967 | SliceInfo::::new::(), 968 | Arc::new(Node::Leaf(LeafSlice::from_slice(&[Width(9), Width(1)]))), 969 | )); 970 | 971 | children.update_child_info(0); 972 | children.update_child_info(1); 973 | children.update_child_info(2); 974 | 975 | children.search_measure_range(17, 18, usize::cmp); 976 | } 977 | } 978 | -------------------------------------------------------------------------------- /src/tree/leaf_slice.rs: -------------------------------------------------------------------------------- 1 | use std::{borrow::Borrow, ops::Deref}; 2 | 3 | use self::inner::LeafSmallVec; 4 | use super::max_len; 5 | use crate::{max_children, Measurable}; 6 | 7 | /// A custom small string. The unsafe guts of this are in [`LeafSmallVec`] 8 | /// further down in this file. 9 | #[derive(Clone, Default)] 10 | #[repr(C)] 11 | pub(crate) struct LeafSlice(inner::LeafSmallVec) 12 | where 13 | M: Measurable, 14 | [(); max_len::()]: Sized, 15 | [(); max_children::()]: Sized; 16 | 17 | impl LeafSlice 18 | where 19 | M: Measurable, 20 | [(); max_len::()]: Sized, 21 | [(); max_children::()]: Sized, 22 | { 23 | /// Creates a new [`Leaf`] from a slice. 24 | pub fn from_slice(value: &[M]) -> Self { 25 | Self(LeafSmallVec::from_slice(value)) 26 | } 27 | 28 | pub fn insert_slice(&mut self, index: usize, slice: &[M]) { 29 | self.0.insert_slice(index, slice); 30 | } 31 | 32 | /// Inserts a [`&[M]`][Measurable] at `index` and splits the resulting 33 | /// string in half, returning the right half. 34 | pub fn insert_slice_split(&mut self, split_index: usize, slice: &[M]) -> Self { 35 | let tot_len = self.len() + slice.len(); 36 | let mid_index = tot_len / 2; 37 | 38 | self.0.insert_slice(split_index, slice); 39 | let right = LeafSlice::from_slice(&self[mid_index..]); 40 | self.truncate(mid_index); 41 | 42 | self.0.inline_if_possible(); 43 | right 44 | } 45 | 46 | /// Appends a [`&[M]`][Measurable] to end the of the [`LeafSlice`]. 47 | pub fn push_slice(&mut self, slice: &[M]) { 48 | let len = self.len(); 49 | self.0.insert_slice(len, slice); 50 | } 51 | 52 | /// Appends a [`&[M]`][Measurable] and splits the resulting string in half, 53 | /// returning the right half. 54 | /// 55 | /// Only splits on code point boundaries and will never split CRLF pairs, 56 | /// so if the whole string is a single code point or CRLF pair, the split 57 | /// will fail and the returned string will be empty. 58 | pub fn push_slice_split(&mut self, slice: &[M]) -> Self { 59 | let len = self.len(); 60 | self.insert_slice_split(len, slice) 61 | } 62 | 63 | /// Drops the text after `index`. 64 | pub fn truncate(&mut self, index: usize) { 65 | self.0.truncate(index); 66 | self.0.inline_if_possible(); 67 | } 68 | 69 | /// Drops the text before `index`, shifting the 70 | /// rest of the text to fill in the space. 71 | pub fn truncate_front(&mut self, index: usize) { 72 | self.0.remove_range(0, index); 73 | self.0.inline_if_possible(); 74 | } 75 | 76 | /// Removes the text in the index interval `[start_index, end_index)`. 77 | pub fn remove_range(&mut self, start_index: usize, end_index: usize) { 78 | self.0.remove_range(start_index, end_index); 79 | self.0.inline_if_possible(); 80 | } 81 | 82 | /// Splits the [`LeafSlice`] at `index`. 83 | /// 84 | /// The left part remains in the original, and the right part is 85 | /// returned in a new [`LeafSlice`]. 86 | pub fn split_off(&mut self, index: usize) -> Self { 87 | let other = LeafSlice(self.0.split_off(index)); 88 | self.0.inline_if_possible(); 89 | other 90 | } 91 | } 92 | 93 | impl std::cmp::PartialEq for LeafSlice 94 | where 95 | M: Measurable + PartialEq, 96 | [(); max_len::()]: Sized, 97 | [(); max_children::()]: Sized, 98 | { 99 | fn eq(&self, other: &Self) -> bool { 100 | let (s1, s2): (&[M], &[M]) = (self, other); 101 | s1 == s2 102 | } 103 | } 104 | 105 | impl<'a, M> PartialEq> for &'a [M] 106 | where 107 | M: Measurable + PartialEq, 108 | [(); max_len::()]: Sized, 109 | [(); max_children::()]: Sized, 110 | { 111 | fn eq(&self, other: &LeafSlice) -> bool { 112 | *self == (other as &[M]) 113 | } 114 | } 115 | 116 | impl<'a, M> PartialEq<&'a [M]> for LeafSlice 117 | where 118 | M: Measurable + PartialEq, 119 | [(); max_len::()]: Sized, 120 | [(); max_children::()]: Sized, 121 | { 122 | fn eq(&self, other: &&'a [M]) -> bool { 123 | (self as &[M]) == *other 124 | } 125 | } 126 | 127 | impl std::fmt::Display for LeafSlice 128 | where 129 | M: Measurable + std::fmt::Display, 130 | [(); max_len::()]: Sized, 131 | [(); max_children::()]: Sized, 132 | { 133 | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 134 | let mut iter = self.iter(); 135 | f.write_str("[")?; 136 | 137 | iter.next() 138 | .map(|measurable| f.write_fmt(format_args!("{}", measurable))) 139 | .transpose()?; 140 | 141 | for measurable in iter { 142 | f.write_fmt(format_args!(", {}", measurable))?; 143 | } 144 | 145 | f.write_str("]") 146 | } 147 | } 148 | 149 | impl std::fmt::Debug for LeafSlice 150 | where 151 | M: Measurable + std::fmt::Debug, 152 | [(); max_len::()]: Sized, 153 | [(); max_children::()]: Sized, 154 | { 155 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 156 | LeafSlice::deref(self).fmt(f) 157 | } 158 | } 159 | 160 | impl Deref for LeafSlice 161 | where 162 | M: Measurable, 163 | [(); max_len::()]: Sized, 164 | [(); max_children::()]: Sized, 165 | { 166 | type Target = [M]; 167 | 168 | fn deref(&self) -> &[M] { 169 | self.0.as_slice() 170 | } 171 | } 172 | 173 | impl AsRef<[M]> for LeafSlice 174 | where 175 | M: Measurable, 176 | [(); max_len::()]: Sized, 177 | [(); max_children::()]: Sized, 178 | { 179 | fn as_ref(&self) -> &[M] { 180 | self.0.as_slice() 181 | } 182 | } 183 | 184 | impl Borrow<[M]> for LeafSlice 185 | where 186 | M: Measurable, 187 | [(); max_len::()]: Sized, 188 | [(); max_children::()]: Sized, 189 | { 190 | fn borrow(&self) -> &[M] { 191 | self.0.as_slice() 192 | } 193 | } 194 | 195 | //======================================================================= 196 | 197 | /// The unsafe guts of NodeText, exposed through a safe API. 198 | /// 199 | /// Try to keep this as small as possible, and implement functionality on 200 | /// NodeText via the safe APIs whenever possible. 201 | mod inner { 202 | use smallvec::{Array, SmallVec}; 203 | 204 | use super::Measurable; 205 | use crate::tree::max_len; 206 | 207 | /// The backing internal buffer type for [`LeafSlice`][super::LeafSlice]. 208 | #[derive(Copy, Clone)] 209 | struct BackingArray([M; max_len::()]) 210 | where 211 | M: Measurable, 212 | [(); max_len::()]: Sized; 213 | 214 | /// We need a very specific size of array, which is not necessarily 215 | /// supported directly by the impls in the smallvec crate. We therefore 216 | /// have to implement this unsafe trait for our specific array size. 217 | /// TODO: once integer const generics land, and smallvec updates its APIs 218 | /// to use them, switch over and get rid of this unsafe impl. 219 | unsafe impl Array for BackingArray 220 | where 221 | M: Measurable, 222 | [(); max_len::()]: Sized, 223 | { 224 | type Item = M; 225 | 226 | fn size() -> usize { 227 | max_len::() 228 | } 229 | } 230 | 231 | /// Internal small string for [`LeafSlice`][super::LeafSlice]. 232 | #[derive(Clone, Default)] 233 | #[repr(C)] 234 | pub struct LeafSmallVec 235 | where 236 | M: Measurable, 237 | [(); max_len::()]: Sized, 238 | { 239 | buffer: SmallVec>, 240 | } 241 | 242 | impl LeafSmallVec 243 | where 244 | M: Measurable, 245 | [(); max_len::()]: Sized, 246 | { 247 | #[inline(always)] 248 | pub fn with_capacity(capacity: usize) -> Self { 249 | LeafSmallVec { 250 | buffer: SmallVec::with_capacity(capacity), 251 | } 252 | } 253 | 254 | #[inline(always)] 255 | pub fn from_slice(slice: &[M]) -> Self { 256 | let mut leaf_small_vec = LeafSmallVec::with_capacity(slice.len()); 257 | leaf_small_vec.insert_slice(0, slice); 258 | leaf_small_vec 259 | } 260 | 261 | #[inline(always)] 262 | pub fn len(&self) -> usize { 263 | self.buffer.len() 264 | } 265 | 266 | pub fn as_slice(&self) -> &[M] { 267 | &self.buffer 268 | } 269 | 270 | /// Inserts a [`&[M]`][Measurable] at `index`. 271 | #[inline(always)] 272 | pub fn insert_slice(&mut self, index: usize, slice: &[M]) { 273 | // Copy the `slice` into the appropriate space in the buffer. 274 | self.buffer.insert_many(index, slice.iter().cloned()); 275 | } 276 | 277 | /// Removes text in range `[start_index, end_index)` 278 | #[inline(always)] 279 | pub fn remove_range(&mut self, start_index: usize, end_index: usize) { 280 | assert!(start_index <= end_index); 281 | // Already checked by copy_within/is_char_boundary. 282 | debug_assert!(end_index <= self.len()); 283 | self.buffer.drain(start_index..end_index); 284 | } 285 | 286 | /// Removes text after `index`. 287 | #[inline(always)] 288 | pub fn truncate(&mut self, index: usize) { 289 | // Already checked by is_char_boundary. 290 | debug_assert!(index <= self.len()); 291 | self.buffer.truncate(index); 292 | } 293 | 294 | /// Splits at `index`, returning the right part and leaving the 295 | /// left part in the original. 296 | #[inline(always)] 297 | pub fn split_off(&mut self, index: usize) -> Self { 298 | debug_assert!(index <= self.len()); 299 | let len = self.len(); 300 | let mut other = LeafSmallVec::with_capacity(len - index); 301 | other.buffer.extend(self.buffer.drain(index..len)); 302 | other 303 | } 304 | 305 | /// Re-inlines the data if it's been heap allocated but can fit inline. 306 | #[inline(always)] 307 | pub fn inline_if_possible(&mut self) { 308 | if self.buffer.spilled() && (self.buffer.len() <= self.buffer.inline_size()) { 309 | self.buffer.shrink_to_fit(); 310 | } 311 | } 312 | } 313 | 314 | //----------------------------------------------------------------------- 315 | 316 | #[cfg(test)] 317 | mod tests { 318 | use super::*; 319 | use crate::Width; 320 | 321 | #[test] 322 | fn vec_basics() { 323 | let vec = LeafSmallVec::from_slice(&[Width(1), Width(2), Width(3), Width(0), Width(0)]); 324 | assert_eq!(vec.as_slice(), &[ 325 | Width(1), 326 | Width(2), 327 | Width(3), 328 | Width(0), 329 | Width(0) 330 | ]); 331 | assert_eq!(5, vec.len()); 332 | } 333 | 334 | #[test] 335 | fn insert_slice_01() { 336 | let mut vec = LeafSmallVec::from_slice(&[Width(1), Width(2)]); 337 | vec.insert_slice(2, &[Width(5), Width(0), Width(0)]); 338 | assert_eq!(vec.as_slice(), &[ 339 | Width(1), 340 | Width(2), 341 | Width(5), 342 | Width(0), 343 | Width(0) 344 | ]); 345 | } 346 | 347 | #[test] 348 | #[should_panic] 349 | fn insert_slice_02() { 350 | let mut vec = LeafSmallVec::from_slice(&[Width(2), Width(0)]); 351 | vec.insert_slice(3, &[Width(1)]); 352 | } 353 | 354 | #[test] 355 | fn remove_range_01() { 356 | let mut vec = 357 | LeafSmallVec::from_slice(&[Width(1), Width(2), Width(1), Width(0), Width(0)]); 358 | vec.remove_range(2, 3); 359 | assert_eq!(vec.as_slice(), &[Width(1), Width(2), Width(0), Width(0)]); 360 | } 361 | 362 | #[test] 363 | #[should_panic] 364 | fn remove_range_02() { 365 | let mut vec = LeafSmallVec::from_slice(&[Width(5), Width(0), Width(0), Width(2)]); 366 | vec.remove_range(4, 2); 367 | } 368 | 369 | #[test] 370 | #[should_panic] 371 | fn remove_range_03() { 372 | let mut vec = LeafSmallVec::from_slice(&[Width(5), Width(0), Width(0), Width(2)]); 373 | vec.remove_range(2, 7); 374 | } 375 | 376 | #[test] 377 | fn truncate_01() { 378 | let mut vec = LeafSmallVec::from_slice(&[Width(3), Width(0), Width(0), Width(4)]); 379 | vec.truncate(3); 380 | assert_eq!(vec.as_slice(), &[Width(3), Width(0), Width(0)]); 381 | } 382 | 383 | #[test] 384 | #[should_panic] 385 | fn truncate_02() { 386 | let mut vec = LeafSmallVec::from_slice(&[Width(6)]); 387 | vec.truncate(7); 388 | } 389 | 390 | #[test] 391 | fn split_off_01() { 392 | let mut vec_1 = LeafSmallVec::from_slice(&[Width(1), Width(3), Width(0), Width(0)]); 393 | let vec_2 = vec_1.split_off(2); 394 | assert_eq!(vec_1.as_slice(), &[Width(1), Width(3)]); 395 | assert_eq!(vec_2.as_slice(), &[Width(0), Width(0)]); 396 | } 397 | 398 | #[test] 399 | #[should_panic] 400 | fn split_off_02() { 401 | let mut s1 = 402 | LeafSmallVec::from_slice(&[Width(1), Width(2), Width(3), Width(0), Width(0)]); 403 | s1.split_off(7); 404 | } 405 | } 406 | } 407 | -------------------------------------------------------------------------------- /src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | mod branch_children; 2 | mod leaf_slice; 3 | mod node; 4 | mod slice_info; 5 | 6 | pub(crate) use self::{ 7 | branch_children::BranchChildren, leaf_slice::LeafSlice, node::Node, slice_info::SliceInfo, 8 | }; 9 | 10 | // Type used for storing tree metadata, such as indices and widths. 11 | pub(crate) type Count = u64; 12 | 13 | // Real constants used in release builds. 14 | #[cfg(not(test))] 15 | mod constants { 16 | use std::{ 17 | fmt::Debug, 18 | mem::{align_of, size_of}, 19 | ops::{Add, Sub}, 20 | sync::Arc, 21 | }; 22 | 23 | use smallvec::SmallVec; 24 | 25 | use super::SliceInfo; 26 | 27 | // Because stdlib's max is not const for some reason. 28 | // TODO: replace with stdlib max once it's const. 29 | const fn cmax(a: usize, b: usize) -> usize { 30 | if a > b { a } else { b } 31 | } 32 | 33 | // Aim for Node + Arc counters to be 1024 bytes. Keeping the nodes 34 | // multiples of large powers of two makes it easier for the memory 35 | // allocator to avoid fragmentation. 36 | const TARGET_TOTAL_SIZE: usize = 1024; 37 | 38 | // Space that the strong and weak Arc counters take up in `ArcInner`. 39 | const ARC_COUNTERS_SIZE: usize = size_of::() * 2; 40 | 41 | // Misc useful info that we need below. 42 | const fn node_children_align() -> usize 43 | where 44 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 45 | { 46 | cmax(align_of::>(), align_of::<(SliceInfo, bool)>()) 47 | } 48 | 49 | const fn node_align() -> usize { 50 | align_of::>() 51 | } 52 | 53 | const fn start_offset() -> usize 54 | where 55 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 56 | { 57 | let node_inner_align = cmax(node_children_align::(), node_align::()); 58 | // The `+ node_inner_align` is because of Node's enum discriminant. 59 | ARC_COUNTERS_SIZE + node_inner_align 60 | } 61 | 62 | // Node maximums. 63 | pub const fn max_children() -> usize 64 | where 65 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 66 | { 67 | let node_list_align = align_of::>(); 68 | let info_list_align = align_of::>(); 69 | let field_gap = if node_list_align >= info_list_align { 70 | 0 71 | } else { 72 | // This is over-conservative, because in reality it depends 73 | // on the number of elements. But handling that is probably 74 | // more complexity than it's worth. 75 | info_list_align - node_list_align 76 | }; 77 | 78 | // The -NODE_CHILDREN_ALIGN is for the `len` field in `NodeChildrenInternal`. 79 | let target_size = 80 | TARGET_TOTAL_SIZE - start_offset::() - node_children_align::() - field_gap; 81 | 82 | target_size / (size_of::>() + size_of::>()) 83 | } 84 | pub const fn max_len() -> usize 85 | where 86 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 87 | { 88 | let smallvec_overhead = size_of::>(); 89 | (TARGET_TOTAL_SIZE - start_offset::() - smallvec_overhead) / size_of::() 90 | } 91 | 92 | // Node minimums. 93 | // Note: min_len is intentionally a little smaller than half 94 | // max_len, to give a little wiggle room when on the edge of 95 | // merging/splitting. 96 | pub const fn min_children() -> usize 97 | where 98 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 99 | { 100 | max_children::() / 2 101 | } 102 | pub const fn min_len() -> usize 103 | where 104 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 105 | { 106 | (max_len::() / 2) - (max_len::() / 32) 107 | } 108 | } 109 | 110 | // Smaller constants used in debug builds. These are different from release 111 | // in order to trigger deeper trees without having to use huge slice data in 112 | // the tests. 113 | #[cfg(test)] 114 | mod test_constants { 115 | use std::{ 116 | fmt::Debug, 117 | ops::{Add, Sub}, 118 | }; 119 | 120 | pub const fn max_children() -> usize 121 | where 122 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 123 | { 124 | 5 125 | } 126 | pub const fn min_children() -> usize 127 | where 128 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 129 | { 130 | max_children::() / 2 131 | } 132 | 133 | pub const fn max_len() -> usize 134 | where 135 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 136 | { 137 | 9 138 | } 139 | pub const fn min_len() -> usize 140 | where 141 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 142 | { 143 | (max_len::() / 2) - (max_len::() / 32) 144 | } 145 | } 146 | 147 | #[cfg(not(test))] 148 | pub use self::constants::{max_children, max_len, min_children, min_len}; 149 | #[cfg(test)] 150 | pub use self::test_constants::{max_children, max_len, min_children, min_len}; 151 | -------------------------------------------------------------------------------- /src/tree/node.rs: -------------------------------------------------------------------------------- 1 | use std::{cmp::Ordering, sync::Arc}; 2 | 3 | use crate::{ 4 | fallible_min, 5 | slice_utils::{end_measure_to_index, index_to_measure, start_measure_to_index}, 6 | tree::{ 7 | max_children, max_len, min_children, min_len, BranchChildren, Count, LeafSlice, SliceInfo, 8 | }, 9 | Measurable, 10 | }; 11 | 12 | #[derive(Debug, Clone)] 13 | #[repr(u8, C)] 14 | pub(crate) enum Node 15 | where 16 | M: Measurable, 17 | [(); max_len::()]: Sized, 18 | [(); max_children::()]: Sized, 19 | { 20 | Leaf(LeafSlice), 21 | Branch(BranchChildren), 22 | } 23 | 24 | impl Node 25 | where 26 | M: Measurable, 27 | [(); max_len::()]: Sized, 28 | [(); max_children::()]: Sized, 29 | { 30 | /// Creates an empty [`Node`]. 31 | #[inline(always)] 32 | pub fn new() -> Self { 33 | Node::Leaf(LeafSlice::from_slice(&[])) 34 | } 35 | 36 | /// Total number of items in the [`Node`]. 37 | #[inline(always)] 38 | pub fn len(&self) -> usize { 39 | self.info().len as usize 40 | } 41 | 42 | /// Total [`M::Measure`] in the [`Node`] 43 | /// 44 | /// [`M::Measure`]: Measurable::Measure 45 | #[inline(always)] 46 | pub fn measure(&self) -> M::Measure { 47 | self.info().measure 48 | } 49 | 50 | /// Fetches a chunk mutably, and allows it to be edited via a closure. 51 | /// 52 | /// There are three parameters: 53 | /// - width: the chunk that contains this width is fetched, 54 | /// - node_info: this is the [`SliceInfo`] of the node it's being called on. 55 | /// This makes it a little awkward to call, but is needed since it's 56 | /// actually the parent node that contains the [`SliceInfo`], so the info 57 | /// needs to be passed in. 58 | /// - edit: the closure that receives the chunk and does the edits. 59 | /// 60 | /// The closure is effectively the termination case for the recursion, 61 | /// and takes essentially same parameters and returns the same things as 62 | /// the method itself. In particular, the closure receives the width offset 63 | /// of the width within the given chunk and the [`SliceInfo`] of the chunk. 64 | /// The main difference is that it receives a [`LeafSlice`] instead of a 65 | /// node. 66 | /// 67 | /// The closure is expected to return the updated [`SliceInfo`] of the 68 | /// [`Node`], and if the node had to be split, then it also returns 69 | /// the right-hand [`Node`] along with its [`SliceInfo`] as well. 70 | /// 71 | /// The main method call will then return the total updated [`SliceInfo`] 72 | /// for the whole tree, and a new [`Node`] only if the whole tree had 73 | /// to be split. It is up to the caller to check for that new 74 | /// [`Node`], and handle it by creating a new root with both the 75 | /// original [`Node`] and the new node as children. 76 | pub fn edit_chunk_at_measure( 77 | &mut self, 78 | measure: M::Measure, 79 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 80 | info: SliceInfo, 81 | mut edit: F, 82 | ) -> ( 83 | SliceInfo, 84 | Option<(SliceInfo, Arc>)>, 85 | ) 86 | where 87 | F: FnMut( 88 | M::Measure, 89 | SliceInfo, 90 | &mut LeafSlice, 91 | ) -> ( 92 | SliceInfo, 93 | Option<(SliceInfo, Arc>)>, 94 | ), 95 | { 96 | match self { 97 | Node::Leaf(slice) => edit(measure, info, slice), 98 | Node::Branch(children) => { 99 | // Compact leaf children if we're very close to maximum leaf 100 | // fragmentation. This basically guards against excessive memory 101 | // ballooning when repeatedly appending to the end of a rope. 102 | // The constant here was arrived at experimentally, and is otherwise 103 | // fairly arbitrary. 104 | const fn frag_min_bytes() -> usize { 105 | (max_len::() * min_children::()) 106 | + (max_len::() / 32) 107 | } 108 | if children.is_full() 109 | && children.nodes()[0].is_leaf() 110 | && (children.combined_info().len as usize) < frag_min_bytes::() 111 | { 112 | children.compact_leaves(); 113 | } 114 | 115 | // Find the child we care about. 116 | let (child_i, acc_measure) = children.search_measure_only(measure, cmp); 117 | let child_info = children.info()[child_i]; 118 | 119 | // Recurse into the child. 120 | let (l_info, residual) = Arc::make_mut(&mut children.nodes_mut()[child_i]) 121 | .edit_chunk_at_measure(measure - acc_measure, cmp, child_info, edit); 122 | 123 | children.info_mut()[child_i] = l_info; 124 | 125 | // Handle the residual node if there is one and return. 126 | if let Some((r_info, r_node)) = residual { 127 | if children.len() < max_children::() { 128 | children.insert(child_i + 1, (r_info, r_node)); 129 | (info - child_info + l_info + r_info, None) 130 | } else { 131 | let r = children.insert_split(child_i + 1, (r_info, r_node)); 132 | let r_info = r.combined_info(); 133 | ( 134 | children.combined_info(), 135 | Some((r_info, Arc::new(Node::Branch(r)))), 136 | ) 137 | } 138 | } else { 139 | (info - child_info + l_info, None) 140 | } 141 | } 142 | } 143 | } 144 | 145 | /// Removes elements in the range `start_index..end_index`. 146 | /// 147 | /// The parameters `left_edge` and `right_edge`, if true, remove 0 width 148 | /// elements at the edges of the range. 149 | /// 150 | /// Returns (in this order): 151 | /// - The updated [`SliceInfo`] for the node. 152 | /// - Whether [`fix_tree_seam()`][Node::fix_tree_seam] needs to be run after 153 | /// this. 154 | /// 155 | /// WARNING: does not correctly handle all slice being removed. That 156 | /// should be special-cased in calling code. 157 | pub fn remove_range( 158 | &mut self, 159 | start: M::Measure, 160 | end: M::Measure, 161 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 162 | incl_left: bool, 163 | incl_right: bool, 164 | ) -> (SliceInfo, bool) { 165 | let info = self.info(); 166 | match self { 167 | Node::Leaf(slice) => remove_from_slice(slice, start, end, cmp, incl_left, incl_right), 168 | Node::Branch(children) => { 169 | remove_from_children(children, start, end, cmp, incl_left, incl_right, info) 170 | } 171 | } 172 | } 173 | 174 | pub fn append_at_depth(&mut self, mut other: Arc>, depth: usize) -> Option> { 175 | if depth == 0 { 176 | if let Node::Branch(ref mut children_l) = *self { 177 | if let Node::Branch(ref mut children_r) = *Arc::make_mut(&mut other) { 178 | if (children_l.len() + children_r.len()) <= max_children::() { 179 | for _ in 0..children_r.len() { 180 | children_l.push(children_r.remove(0)); 181 | } 182 | return None; 183 | } else { 184 | children_l.distribute_with(children_r); 185 | // Return lower down, to avoid borrow-checker. 186 | } 187 | } else { 188 | panic!("Tree-append siblings have differing types."); 189 | } 190 | } else if !other.is_leaf() { 191 | panic!("Tree-append siblings have differing types."); 192 | } 193 | 194 | return Some(other); 195 | } else if let Node::Branch(ref mut children) = *self { 196 | let last_i = children.len() - 1; 197 | let residual = 198 | Arc::make_mut(&mut children.nodes_mut()[last_i]).append_at_depth(other, depth - 1); 199 | children.update_child_info(last_i); 200 | if let Some(extra_node) = residual { 201 | if children.len() < max_children::() { 202 | children.push((extra_node.info(), extra_node)); 203 | return None; 204 | } else { 205 | let r_children = children.push_split((extra_node.info(), extra_node)); 206 | return Some(Arc::new(Node::Branch(r_children))); 207 | } 208 | } else { 209 | return None; 210 | } 211 | } else { 212 | panic!("Reached leaf before getting to target depth."); 213 | } 214 | } 215 | 216 | pub fn prepend_at_depth(&mut self, other: Arc>, depth: usize) -> Option> { 217 | if depth == 0 { 218 | match *self { 219 | Node::Leaf(_) => { 220 | if !other.is_leaf() { 221 | panic!("Tree-append siblings have differing types."); 222 | } else { 223 | return Some(other); 224 | } 225 | } 226 | Node::Branch(ref mut children_r) => { 227 | let mut other = other; 228 | if let Node::Branch(ref mut children_l) = *Arc::make_mut(&mut other) { 229 | if (children_l.len() + children_r.len()) <= max_children::() 230 | { 231 | for _ in 0..children_l.len() { 232 | children_r.insert(0, children_l.pop()); 233 | } 234 | return None; 235 | } else { 236 | children_l.distribute_with(children_r); 237 | // Return lower down, to avoid borrow-checker. 238 | } 239 | } else { 240 | panic!("Tree-append siblings have differing types."); 241 | } 242 | return Some(other); 243 | } 244 | } 245 | } else if let Node::Branch(ref mut children) = *self { 246 | let residual = 247 | Arc::make_mut(&mut children.nodes_mut()[0]).prepend_at_depth(other, depth - 1); 248 | children.update_child_info(0); 249 | if let Some(extra_node) = residual { 250 | if children.len() < max_children::() { 251 | children.insert(0, (extra_node.info(), extra_node)); 252 | return None; 253 | } else { 254 | let mut r_children = children.insert_split(0, (extra_node.info(), extra_node)); 255 | std::mem::swap(children, &mut r_children); 256 | return Some(Arc::new(Node::Branch(r_children))); 257 | } 258 | } else { 259 | return None; 260 | } 261 | } else { 262 | panic!("Reached leaf before getting to target depth."); 263 | } 264 | } 265 | 266 | /// Splits the [`Node`] at `measure`, returning the right side of the 267 | /// split. 268 | pub fn end_split( 269 | &mut self, 270 | measure: M::Measure, 271 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 272 | ) -> Self { 273 | debug_assert!(measure != M::Measure::default()); 274 | debug_assert!(measure != (self.info().measure)); 275 | match *self { 276 | Node::Leaf(ref mut slice) => { 277 | let index = end_measure_to_index(slice, measure, cmp); 278 | Node::Leaf(slice.split_off(index)) 279 | } 280 | Node::Branch(ref mut children) => { 281 | let (child_i, acc_info) = children.search_end_measure(measure, cmp); 282 | let child_info = children.info()[child_i]; 283 | 284 | if measure == acc_info.measure { 285 | Node::Branch(children.split_off(child_i)) 286 | } else if measure == (acc_info.measure + child_info.measure) { 287 | Node::Branch(children.split_off(child_i + 1)) 288 | } else { 289 | let mut r_children = children.split_off(child_i + 1); 290 | 291 | // Recurse 292 | let r_node = Arc::make_mut(&mut children.nodes_mut()[child_i]) 293 | .end_split(measure - acc_info.measure, cmp); 294 | 295 | r_children.insert(0, (r_node.info(), Arc::new(r_node))); 296 | 297 | children.update_child_info(child_i); 298 | r_children.update_child_info(0); 299 | 300 | Node::Branch(r_children) 301 | } 302 | } 303 | } 304 | } 305 | 306 | /// Splits the [`Node`] index `width`, returning the right side of the 307 | /// split. 308 | pub fn start_split( 309 | &mut self, 310 | measure: M::Measure, 311 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 312 | ) -> Self { 313 | debug_assert!(measure != M::Measure::default()); 314 | debug_assert!(measure != (self.info().measure)); 315 | match *self { 316 | Node::Leaf(ref mut slice) => { 317 | let index = start_measure_to_index(slice, measure, cmp); 318 | Node::Leaf(slice.split_off(index)) 319 | } 320 | Node::Branch(ref mut children) => { 321 | let (child_i, acc_info) = children.search_start_measure(measure, cmp); 322 | let child_info = children.info()[child_i]; 323 | 324 | if measure == acc_info.measure { 325 | Node::Branch(children.split_off(child_i)) 326 | } else if measure == (acc_info.measure + child_info.measure) { 327 | Node::Branch(children.split_off(child_i + 1)) 328 | } else { 329 | let mut r_children = children.split_off(child_i + 1); 330 | 331 | // Recurse 332 | let r_node = Arc::make_mut(&mut children.nodes_mut()[child_i]) 333 | .end_split(measure - acc_info.measure, cmp); 334 | 335 | r_children.insert(0, (r_node.info(), Arc::new(r_node))); 336 | 337 | children.update_child_info(child_i); 338 | r_children.update_child_info(0); 339 | 340 | Node::Branch(r_children) 341 | } 342 | } 343 | } 344 | } 345 | 346 | /// Returns the chunk that contains the given index, and the [`SliceInfo`] 347 | /// corresponding to the start of the chunk. 348 | pub fn get_chunk_at_index(&self, mut index: usize) -> (&[M], SliceInfo) { 349 | let mut node = self; 350 | let mut info = SliceInfo::::new::(); 351 | 352 | loop { 353 | match *node { 354 | Node::Leaf(ref slice) => { 355 | return (slice, info); 356 | } 357 | Node::Branch(ref children) => { 358 | let (child_i, acc_info) = children.search_index(index); 359 | info += acc_info; 360 | node = &*children.nodes()[child_i]; 361 | index -= acc_info.len as usize; 362 | } 363 | } 364 | } 365 | } 366 | 367 | /// Returns the chunk that contains the given width, and the [`SliceInfo`] 368 | /// corresponding to the start of the chunk. 369 | pub fn get_first_chunk_at_measure( 370 | &self, 371 | mut measure: M::Measure, 372 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 373 | ) -> (&[M], SliceInfo) { 374 | let mut node = self; 375 | let mut info = SliceInfo::::new::(); 376 | 377 | loop { 378 | match *node { 379 | Node::Leaf(ref slice) => { 380 | return (slice, info); 381 | } 382 | Node::Branch(ref children) => { 383 | let (child_i, acc_info) = children.search_start_measure(measure, cmp); 384 | info += acc_info; 385 | 386 | node = &*children.nodes()[child_i]; 387 | measure = measure - acc_info.measure; 388 | } 389 | } 390 | } 391 | } 392 | 393 | /// Returns the chunk that contains the given width, and the [`SliceInfo`] 394 | /// corresponding to the start of the chunk. 395 | pub fn get_last_chunk_at_measure( 396 | &self, 397 | mut measure: M::Measure, 398 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 399 | ) -> (&[M], SliceInfo) { 400 | let mut node = self; 401 | let mut info = SliceInfo::::new::(); 402 | 403 | loop { 404 | match *node { 405 | Node::Leaf(ref slice) => { 406 | return (slice, info); 407 | } 408 | Node::Branch(ref children) => { 409 | let (child_i, acc_info) = children.search_end_measure(measure, cmp); 410 | info += acc_info; 411 | 412 | node = &*children.nodes()[child_i]; 413 | measure = measure - acc_info.measure; 414 | } 415 | } 416 | } 417 | } 418 | 419 | /// Returns the [`SliceInfo`] at the given starting width sum. 420 | #[inline(always)] 421 | pub fn start_measure_to_slice_info( 422 | &self, 423 | measure: M::Measure, 424 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 425 | ) -> SliceInfo { 426 | let (chunk, info) = self.get_first_chunk_at_measure(measure, cmp); 427 | let bi = start_measure_to_index(chunk, measure - info.measure, cmp); 428 | SliceInfo { 429 | len: info.len + bi as Count, 430 | measure, 431 | } 432 | } 433 | 434 | /// Returns the [`SliceInfo`] at the given ending width sum. 435 | #[inline(always)] 436 | pub fn end_measure_to_slice_info( 437 | &self, 438 | measure: M::Measure, 439 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 440 | ) -> SliceInfo { 441 | let (chunk, info) = self.get_last_chunk_at_measure(measure, cmp); 442 | let bi = end_measure_to_index(chunk, measure - info.measure, cmp); 443 | SliceInfo { 444 | len: info.len + bi as Count, 445 | measure, 446 | } 447 | } 448 | 449 | /// Returns the [`SliceInfo`] at the given index. 450 | #[inline(always)] 451 | pub fn index_to_slice_info(&self, index: usize) -> SliceInfo { 452 | let (chunk, info) = self.get_chunk_at_index(index); 453 | let measure = index_to_measure(chunk, index - info.len as usize); 454 | SliceInfo { 455 | len: index as Count, 456 | measure: info.measure + measure, 457 | } 458 | } 459 | 460 | pub fn info(&self) -> SliceInfo { 461 | match *self { 462 | Node::Leaf(ref slice) => SliceInfo::::from_slice(slice), 463 | Node::Branch(ref children) => children.combined_info(), 464 | } 465 | } 466 | 467 | //----------------------------------------- 468 | 469 | pub fn child_count(&self) -> usize { 470 | if let Node::Branch(ref children) = *self { 471 | children.len() 472 | } else { 473 | panic!() 474 | } 475 | } 476 | 477 | pub fn children(&self) -> &BranchChildren { 478 | match *self { 479 | Node::Branch(ref children) => children, 480 | _ => panic!(), 481 | } 482 | } 483 | 484 | pub fn children_mut(&mut self) -> &mut BranchChildren { 485 | match *self { 486 | Node::Branch(ref mut children) => children, 487 | _ => panic!(), 488 | } 489 | } 490 | 491 | pub fn leaf_slice(&self) -> &[M] { 492 | match *self { 493 | Node::Leaf(ref slice) => slice, 494 | _ => unreachable!(), 495 | } 496 | } 497 | 498 | pub fn leaf_slice_mut(&mut self) -> &mut LeafSlice { 499 | match *self { 500 | Node::Leaf(ref mut slice) => slice, 501 | _ => panic!(), 502 | } 503 | } 504 | 505 | pub fn is_leaf(&self) -> bool { 506 | match *self { 507 | Node::Leaf(_) => true, 508 | Node::Branch(_) => false, 509 | } 510 | } 511 | 512 | pub fn is_undersized(&self) -> bool { 513 | match *self { 514 | Node::Leaf(ref slice) => slice.len() < min_len::(), 515 | Node::Branch(ref children) => children.len() < min_children::(), 516 | } 517 | } 518 | 519 | /// How many nodes deep the tree is. 520 | /// 521 | /// This counts root and leafs. For example, a single leaf node 522 | /// has depth 1. 523 | pub fn depth(&self) -> usize { 524 | let mut node = self; 525 | let mut depth = 0; 526 | 527 | loop { 528 | match *node { 529 | Node::Leaf(_) => return depth, 530 | Node::Branch(ref children) => { 531 | depth += 1; 532 | node = &*children.nodes()[0]; 533 | } 534 | } 535 | } 536 | } 537 | 538 | /// Debugging tool to make sure that all of the meta-data of the 539 | /// tree is consistent with the actual data. 540 | pub fn assert_integrity(&self) { 541 | match *self { 542 | Node::Leaf(_) => {} 543 | Node::Branch(ref children) => { 544 | for (info, node) in children.iter() { 545 | assert_eq!(info.len, node.info().len); 546 | node.assert_integrity(); 547 | } 548 | } 549 | } 550 | } 551 | 552 | /// Checks that the entire tree is the same height everywhere. 553 | pub fn assert_balance(&self) -> usize { 554 | // Depth, child count, and leaf node emptiness 555 | match *self { 556 | Node::Leaf(_) => 1, 557 | Node::Branch(ref children) => { 558 | let first_depth = children.nodes()[0].assert_balance(); 559 | for node in &children.nodes()[1..] { 560 | assert_eq!(node.assert_balance(), first_depth); 561 | } 562 | first_depth + 1 563 | } 564 | } 565 | } 566 | 567 | /// Checks that all internal nodes have the minimum number of 568 | /// children and all non-root leaf nodes are non-empty. 569 | pub fn assert_node_size(&self, is_root: bool) { 570 | match *self { 571 | Node::Leaf(ref slice) => { 572 | // Leaf size 573 | if !is_root { 574 | assert!(slice.len() > 0); 575 | } 576 | } 577 | Node::Branch(ref children) => { 578 | // Child count 579 | if is_root { 580 | assert!(children.len() > 1); 581 | } else { 582 | assert!(children.len() >= min_children::()); 583 | } 584 | 585 | for node in children.nodes() { 586 | node.assert_node_size(false); 587 | } 588 | } 589 | } 590 | } 591 | 592 | /// Fixes dangling nodes down the left side of the tree. 593 | /// 594 | /// Returns whether it did anything or not that would affect the 595 | /// parent. 596 | pub fn zip_fix_left(&mut self) -> bool { 597 | if let Node::Branch(ref mut children) = *self { 598 | let mut did_stuff = false; 599 | loop { 600 | let do_merge = (children.len() > 1) 601 | && match *children.nodes()[0] { 602 | Node::Leaf(ref slice) => slice.len() < min_len::(), 603 | Node::Branch(ref children2) => { 604 | children2.len() < min_children::() 605 | } 606 | }; 607 | 608 | if do_merge { 609 | did_stuff |= children.merge_distribute(0, 1); 610 | } 611 | 612 | if !Arc::make_mut(&mut children.nodes_mut()[0]).zip_fix_left() { 613 | break; 614 | } 615 | } 616 | did_stuff 617 | } else { 618 | false 619 | } 620 | } 621 | 622 | /// Fixes dangling nodes down the right side of the tree. 623 | /// 624 | /// Returns whether it did anything or not that would affect the 625 | /// parent. True: did stuff, false: didn't do stuff 626 | pub fn zip_fix_right(&mut self) -> bool { 627 | if let Node::Branch(ref mut children) = *self { 628 | let mut did_stuff = false; 629 | loop { 630 | let last_i = children.len() - 1; 631 | let do_merge = (children.len() > 1) 632 | && match *children.nodes()[last_i] { 633 | Node::Leaf(ref slice) => slice.len() < min_len::(), 634 | Node::Branch(ref children2) => { 635 | children2.len() < min_children::() 636 | } 637 | }; 638 | 639 | if do_merge { 640 | did_stuff |= children.merge_distribute(last_i - 1, last_i); 641 | } 642 | 643 | if !Arc::make_mut(children.nodes_mut().last_mut().unwrap()).zip_fix_right() { 644 | break; 645 | } 646 | } 647 | did_stuff 648 | } else { 649 | false 650 | } 651 | } 652 | 653 | /// Fixes up the tree after [`remove_range()`][Node::remove_range] or 654 | /// [`Rope::append()`]. 655 | /// Takes the width of the start of the removal range. 656 | /// 657 | /// Returns whether it did anything or not that would affect the 658 | /// parent. True: did stuff, false: didn't do stuff 659 | pub fn fix_tree_seam( 660 | &mut self, 661 | measure: M::Measure, 662 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 663 | ) -> bool { 664 | if let Node::Branch(ref mut children) = *self { 665 | let mut did_stuff = false; 666 | loop { 667 | // Do merging 668 | if children.len() > 1 { 669 | let (child_i, start_info) = children.search_start_measure(measure, cmp); 670 | let mut do_merge = match *children.nodes()[child_i] { 671 | Node::Leaf(ref slice) => slice.len() < min_len::(), 672 | Node::Branch(ref children2) => { 673 | children2.len() < min_children::() 674 | } 675 | }; 676 | 677 | if child_i == 0 { 678 | if do_merge { 679 | did_stuff |= children.merge_distribute(0, 1); 680 | } 681 | } else { 682 | do_merge |= { 683 | cmp(&start_info.measure, &measure).is_eq() 684 | && match *children.nodes()[child_i - 1] { 685 | Node::Leaf(ref slice) => { 686 | slice.len() < min_len::() 687 | } 688 | Node::Branch(ref children2) => { 689 | children2.len() < min_children::() 690 | } 691 | } 692 | }; 693 | if do_merge { 694 | let res = children.merge_distribute(child_i - 1, child_i); 695 | did_stuff |= res 696 | } 697 | } 698 | } 699 | 700 | // Do recursion 701 | let (child_i, start_info) = children.search_start_measure(measure, cmp); 702 | 703 | if cmp(&start_info.measure, &measure).is_eq() && child_i != 0 { 704 | let tmp = children.info()[child_i - 1].measure; 705 | let effect_1 = Arc::make_mut(&mut children.nodes_mut()[child_i - 1]) 706 | .fix_tree_seam(tmp, cmp); 707 | let effect_2 = Arc::make_mut(&mut children.nodes_mut()[child_i]) 708 | .fix_tree_seam(M::Measure::default(), cmp); 709 | if (!effect_1) && (!effect_2) { 710 | break; 711 | } 712 | } else if !Arc::make_mut(&mut children.nodes_mut()[child_i]) 713 | .fix_tree_seam(measure - start_info.measure, cmp) 714 | { 715 | break; 716 | } 717 | } 718 | debug_assert!(children.is_info_accurate()); 719 | did_stuff 720 | } else { 721 | false 722 | } 723 | } 724 | } 725 | 726 | fn remove_from_slice( 727 | slice: &mut LeafSlice, 728 | start: M::Measure, 729 | end: M::Measure, 730 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 731 | incl_left: bool, 732 | incl_right: bool, 733 | ) -> (SliceInfo, bool) 734 | where 735 | M: Measurable, 736 | [(); max_len::()]: Sized, 737 | [(); max_children::()]: Sized, 738 | { 739 | let start_index = if incl_left { 740 | start_measure_to_index(slice, start, cmp) 741 | } else { 742 | end_measure_to_index(slice, start, cmp) 743 | }; 744 | // In this circumstance, nothing needs to be done, since we're removing 745 | // in the middle of an element. 746 | let non_zero_width = slice 747 | .get(start_index) 748 | .map(|m| cmp(&m.measure(), &M::Measure::default()).is_gt()) 749 | .unwrap_or(true); 750 | 751 | if cmp(&start, &end).is_eq() && non_zero_width { 752 | return (SliceInfo::::from_slice(slice), false); 753 | } 754 | 755 | let end_index = if incl_right { 756 | end_measure_to_index(slice, end, cmp) 757 | } else { 758 | start_measure_to_index(slice, end, cmp) 759 | }; 760 | 761 | slice.remove_range(start_index, end_index); 762 | (SliceInfo::::from_slice(slice), false) 763 | } 764 | 765 | fn remove_from_children( 766 | children: &mut BranchChildren, 767 | start: M::Measure, 768 | end: M::Measure, 769 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 770 | incl_left: bool, 771 | incl_right: bool, 772 | info: SliceInfo, 773 | ) -> (SliceInfo, bool) 774 | where 775 | M: Measurable, 776 | [(); max_len::()]: Sized, 777 | [(); max_children::()]: Sized, 778 | { 779 | let ((left_child, left_accum), (right_child, right_accum)) = 780 | children.search_measure_range(start, end, cmp); 781 | 782 | if left_child == right_child { 783 | let child_info = children.info()[left_child]; 784 | let (new_info, mut needs_fix) = handle_measure_range( 785 | children, left_child, left_accum, start, end, cmp, incl_left, incl_right, 786 | ); 787 | 788 | if children.len() > 0 { 789 | merge_child(children, left_child); 790 | 791 | // If we couldn't get all children >= minimum size, then 792 | // we'll need to fix that later. 793 | if children.nodes()[left_child.min(children.len() - 1)].is_undersized() { 794 | needs_fix = true; 795 | } 796 | } 797 | 798 | (info - child_info + new_info, needs_fix) 799 | // We're dealing with more than one child. 800 | } else { 801 | let mut needs_fix = false; 802 | 803 | // Calculate the start..end range of nodes to be removed. 804 | let first = left_child + 1; 805 | let (last, right_child_exists) = { 806 | let right_measure = children.info()[right_child].measure; 807 | if right_accum + right_measure == end { 808 | (right_child + 1, false) 809 | } else { 810 | (right_child, true) 811 | } 812 | }; 813 | 814 | // Remove the children 815 | for _ in first..last { 816 | children.remove(first); 817 | } 818 | 819 | let between_two_children = 820 | cmp(&start, &right_accum).is_lt() && cmp(&right_accum, &end).is_lt(); 821 | 822 | // Handle right child 823 | if right_child_exists { 824 | let (_, fix) = handle_measure_range( 825 | children, 826 | first, 827 | right_accum, 828 | start, 829 | end, 830 | cmp, 831 | incl_left || between_two_children, 832 | incl_right, 833 | ); 834 | needs_fix |= fix; 835 | } 836 | 837 | // Handle left child 838 | let (_, fix) = { 839 | handle_measure_range( 840 | children, 841 | left_child, 842 | left_accum, 843 | start, 844 | end, 845 | cmp, 846 | incl_left, 847 | incl_right || between_two_children, 848 | ) 849 | }; 850 | needs_fix |= fix; 851 | 852 | if children.len() > 0 { 853 | // Handle merging 854 | let merge_extent = 1 + if right_child_exists { 1 } else { 0 }; 855 | for i in (left_child..(left_child + merge_extent)).rev() { 856 | merge_child(children, i); 857 | } 858 | 859 | // If we couldn't get all children >= minimum size, then 860 | // we'll need to fix that later. 861 | if children.nodes()[left_child.min(children.len() - 1)].is_undersized() { 862 | needs_fix = true; 863 | } 864 | } 865 | 866 | (children.combined_info(), needs_fix) 867 | } 868 | } 869 | 870 | /// Shared code for handling children. 871 | /// Returns (in this order): 872 | /// 873 | /// - Whether the tree may need invariant fixing. 874 | /// - Updated SliceInfo of the node. 875 | fn handle_measure_range( 876 | children: &mut BranchChildren, 877 | child_i: usize, 878 | accum: M::Measure, 879 | start_measure: M::Measure, 880 | end_measure: M::Measure, 881 | cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering, 882 | incl_left: bool, 883 | incl_right: bool, 884 | ) -> (SliceInfo, bool) 885 | where 886 | M: Measurable, 887 | [(); max_len::()]: Sized, 888 | [(); max_children::()]: Sized, 889 | { 890 | // Recurse into child 891 | let child_measure = children.info()[child_i].measure; 892 | let (new_info, needs_fix) = Arc::make_mut(&mut children.nodes_mut()[child_i]).remove_range( 893 | start_measure - fallible_min(accum, start_measure), 894 | fallible_min(end_measure - accum, child_measure), 895 | cmp, 896 | incl_left, 897 | incl_right, 898 | ); 899 | 900 | // Handle result 901 | if new_info.len == 0 { 902 | children.remove(child_i); 903 | } else { 904 | children.info_mut()[child_i] = new_info; 905 | } 906 | 907 | (new_info, needs_fix) 908 | } 909 | 910 | /// Merges a child with its sibling. 911 | fn merge_child(children: &mut BranchChildren, child_i: usize) 912 | where 913 | M: Measurable, 914 | [(); max_len::()]: Sized, 915 | [(); max_children::()]: Sized, 916 | { 917 | if child_i < children.len() && children.len() > 1 && children.nodes()[child_i].is_undersized() { 918 | if child_i == 0 { 919 | children.merge_distribute(child_i, child_i + 1); 920 | } else { 921 | children.merge_distribute(child_i - 1, child_i); 922 | } 923 | } 924 | } 925 | -------------------------------------------------------------------------------- /src/tree/slice_info.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fmt::Debug, 3 | ops::{Add, AddAssign, Sub, SubAssign}, 4 | }; 5 | 6 | use crate::{slice_utils::measure_of, tree::Count, Measurable}; 7 | 8 | #[derive(Debug, Copy, Clone, PartialEq)] 9 | pub struct SliceInfo 10 | where 11 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 12 | { 13 | pub(crate) len: Count, 14 | pub(crate) measure: T, 15 | } 16 | 17 | impl SliceInfo 18 | where 19 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 20 | { 21 | #[inline] 22 | pub fn new() -> SliceInfo { 23 | SliceInfo { 24 | len: 0, 25 | measure: M::Measure::default(), 26 | } 27 | } 28 | 29 | #[inline] 30 | pub fn from_slice(slice: &[M]) -> SliceInfo { 31 | SliceInfo { 32 | len: slice.len() as Count, 33 | measure: measure_of(slice), 34 | } 35 | } 36 | } 37 | 38 | impl Add for SliceInfo 39 | where 40 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 41 | { 42 | type Output = Self; 43 | 44 | #[inline] 45 | fn add(self, rhs: Self) -> Self { 46 | Self { 47 | len: self.len + rhs.len, 48 | measure: self.measure + rhs.measure, 49 | } 50 | } 51 | } 52 | 53 | impl AddAssign for SliceInfo 54 | where 55 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 56 | { 57 | #[inline] 58 | fn add_assign(&mut self, other: Self) { 59 | *self = *self + other; 60 | } 61 | } 62 | 63 | impl Sub for SliceInfo 64 | where 65 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 66 | { 67 | type Output = Self; 68 | 69 | #[inline] 70 | fn sub(self, rhs: Self) -> Self { 71 | Self { 72 | len: self.len - rhs.len, 73 | measure: self.measure - rhs.measure, 74 | } 75 | } 76 | } 77 | 78 | impl SubAssign for SliceInfo 79 | where 80 | T: Debug + Copy + Clone + PartialEq + Add + Sub, 81 | { 82 | #[inline] 83 | fn sub_assign(&mut self, other: Self) { 84 | *self = *self - other; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/fix_tree.rs: -------------------------------------------------------------------------------- 1 | use any_rope::{Measurable, Rope}; 2 | use rand::Rng; 3 | 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 5 | enum Lipsum { 6 | Lorem, 7 | Ipsum, 8 | Dolor(usize), 9 | Sit, 10 | Amet, 11 | Consectur(&'static str), 12 | Adipiscing(bool), 13 | } 14 | 15 | impl Measurable for Lipsum { 16 | type Measure = usize; 17 | 18 | fn measure(&self) -> usize { 19 | match self { 20 | Lipsum::Lorem => 1, 21 | Lipsum::Ipsum => 2, 22 | Lipsum::Dolor(width) => *width, 23 | Lipsum::Sit => 0, 24 | Lipsum::Amet => 0, 25 | Lipsum::Consectur(text) => text.len(), 26 | Lipsum::Adipiscing(boolean) => *boolean as usize, 27 | } 28 | } 29 | } 30 | use self::Lipsum::*; 31 | 32 | #[test] 33 | #[cfg_attr(miri, ignore)] 34 | fn remove_at_chunk_boundery() { 35 | let mut rng = rand::thread_rng(); 36 | 37 | let medium_vec: Vec = { 38 | (0..100000) 39 | .map(|_| match rng.gen::() % 14 { 40 | 0 | 7 => Lorem, 41 | 1 | 8 => Ipsum, 42 | 2 => Dolor(4), 43 | 3 | 10 => Sit, 44 | 4 | 11 => Amet, 45 | 5 => Consectur("hello"), 46 | 6 => Adipiscing(true), 47 | 9 => Dolor(8), 48 | 12 => Consectur("bye"), 49 | 13 => Adipiscing(false), 50 | _ => unreachable!(), 51 | }) 52 | .collect() 53 | }; 54 | 55 | let mut r = Rope::from_slice(medium_vec.as_slice()); 56 | // remove exactly at a chunk boundry 57 | // to trigger an edgecase in fix_tree_seam 58 | r.remove_exclusive(31354..58881, usize::cmp); 59 | 60 | // Verify rope integrity 61 | r.assert_integrity(); 62 | r.assert_invariants(); 63 | } 64 | -------------------------------------------------------------------------------- /tests/from_slice.rs: -------------------------------------------------------------------------------- 1 | use any_rope::{Measurable, Rope}; 2 | use rand::Rng; 3 | 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 5 | enum Lipsum { 6 | Lorem, 7 | Ipsum, 8 | Dolor(usize), 9 | Sit, 10 | Amet, 11 | Consectur(&'static str), 12 | Adipiscing(bool), 13 | } 14 | 15 | impl Measurable for Lipsum { 16 | type Measure = usize; 17 | 18 | fn measure(&self) -> usize { 19 | match self { 20 | Lipsum::Lorem => 1, 21 | Lipsum::Ipsum => 2, 22 | Lipsum::Dolor(width) => *width, 23 | Lipsum::Sit => 0, 24 | Lipsum::Amet => 0, 25 | Lipsum::Consectur(text) => text.len(), 26 | Lipsum::Adipiscing(boolean) => *boolean as usize, 27 | } 28 | } 29 | } 30 | use self::Lipsum::*; 31 | 32 | /// 70 elements, total width of 135. 33 | #[test] 34 | #[cfg_attr(miri, ignore)] 35 | fn from_str() { 36 | let mut rng = rand::thread_rng(); 37 | 38 | let small_vec: Vec = { 39 | (0..1000) 40 | .map(|_| match rng.gen::() % 14 { 41 | 0 | 7 => Lorem, 42 | 1 | 8 => Ipsum, 43 | 2 => Dolor(4), 44 | 3 | 10 => Sit, 45 | 4 | 11 => Amet, 46 | 5 => Consectur("hello"), 47 | 6 => Adipiscing(true), 48 | 9 => Dolor(8), 49 | 12 => Consectur("bye"), 50 | 13 => Adipiscing(false), 51 | _ => unreachable!(), 52 | }) 53 | .collect() 54 | }; 55 | // Build rope from file contents 56 | let rope = Rope::from_slice(small_vec.as_slice()); 57 | 58 | // Verify rope integrity 59 | rope.assert_integrity(); 60 | rope.assert_invariants(); 61 | 62 | // Verify that they match 63 | assert_eq!(rope, small_vec.as_slice()); 64 | } 65 | -------------------------------------------------------------------------------- /tests/shrink_to_fit.rs: -------------------------------------------------------------------------------- 1 | use any_rope::{Measurable, Rope}; 2 | use rand::{rngs::ThreadRng, Rng}; 3 | 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 5 | enum Lipsum { 6 | Lorem, 7 | Ipsum, 8 | Dolor(usize), 9 | Sit, 10 | Amet, 11 | Consectur(&'static str), 12 | Adipiscing(bool), 13 | } 14 | 15 | impl Measurable for Lipsum { 16 | type Measure = usize; 17 | 18 | fn measure(&self) -> usize { 19 | match self { 20 | Lipsum::Lorem => 1, 21 | Lipsum::Ipsum => 2, 22 | Lipsum::Dolor(width) => *width, 23 | Lipsum::Sit => 0, 24 | Lipsum::Amet => 0, 25 | Lipsum::Consectur(text) => text.len(), 26 | Lipsum::Adipiscing(boolean) => *boolean as usize, 27 | } 28 | } 29 | } 30 | use self::Lipsum::*; 31 | 32 | fn random_slice(rng: &mut ThreadRng) -> Vec { 33 | (0..rng.gen::() % 10) 34 | .map(|_| match rng.gen::() % 14 { 35 | 0 | 7 => Lorem, 36 | 1 | 8 => Ipsum, 37 | 2 => Dolor(4), 38 | 3 | 10 => Sit, 39 | 4 | 11 => Amet, 40 | 5 => Consectur("hello"), 41 | 6 => Adipiscing(true), 42 | 9 => Dolor(8), 43 | 12 => Consectur("bye"), 44 | 13 => Adipiscing(false), 45 | _ => unreachable!(), 46 | }) 47 | .collect() 48 | } 49 | 50 | #[test] 51 | #[cfg_attr(miri, ignore)] 52 | fn shrink_to_fit() { 53 | let mut rng = rand::thread_rng(); 54 | let mut rope = Rope::::new(); 55 | 56 | // Do a bunch of random incoherent inserts 57 | for _ in 0..1000 { 58 | let measure = rope.measure().max(1); 59 | println!("new insertion\n\n"); 60 | rope.insert_slice( 61 | rng.gen::() % measure, 62 | random_slice(&mut rng).as_slice(), 63 | usize::cmp, 64 | ); 65 | } 66 | 67 | let rope2 = rope.clone(); 68 | rope.shrink_to_fit(); 69 | 70 | assert_eq!(rope, rope2); 71 | assert!(rope.capacity() < rope2.capacity()); 72 | 73 | // Make sure the rope is sound 74 | rope.assert_integrity(); 75 | rope.assert_invariants(); 76 | 77 | rope2.assert_integrity(); 78 | rope2.assert_invariants(); 79 | } 80 | --------------------------------------------------------------------------------