├── clippy.toml ├── .editorconfig ├── .gitignore ├── .vscode └── settings.json ├── fuzz ├── .gitignore ├── Cargo.toml ├── fuzz_targets │ ├── rope.rs │ └── ord.rs └── Cargo.lock ├── benches ├── automerge-paper.json.gz ├── utils.rs ├── bench_ord.rs ├── automerge.rs └── bench_rope.rs ├── src ├── generic_impl │ ├── mod.rs │ ├── len_finder.rs │ ├── gap_buffer.rs │ ├── ord.rs │ └── rope.rs ├── rle.rs └── iter.rs ├── README.md ├── LICENSE ├── Cargo.toml ├── tests ├── integration.rs └── range_num_map │ └── mod.rs ├── examples └── rope.rs └── Cargo.lock /clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-types = [] 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.rs] 2 | indent_size = 4 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | flamegraph.svg 3 | .idea 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["elems"] 3 | } 4 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | artifacts 4 | coverage 5 | -------------------------------------------------------------------------------- /benches/automerge-paper.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loro-dev/generic-btree/HEAD/benches/automerge-paper.json.gz -------------------------------------------------------------------------------- /src/generic_impl/mod.rs: -------------------------------------------------------------------------------- 1 | mod gap_buffer; 2 | mod len_finder; 3 | mod ord; 4 | mod rope; 5 | pub use len_finder::{LengthFinder, UseLengthFinder}; 6 | pub use ord::{OrdTreeMap, OrdTreeSet}; 7 | pub use rope::Rope; 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generic B-Tree 2 | 3 | It’s a pure safe BTree that can be used to build your own special-purpose btree 4 | data structure. It’s mainly developed to optimize the performance of Loro CRDT’s 5 | components. 6 | 7 | It can be used to build: 8 | 9 | - Rope 10 | - Run length encoding data structure 11 | - RangeMap that uses range as its key 12 | - BTreeSet & BTreeMap 13 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generic-btree-fuzz" 3 | version = "0.0.0" 4 | publish = false 5 | edition = "2021" 6 | 7 | [package.metadata] 8 | cargo-fuzz = true 9 | 10 | [dependencies] 11 | arbitrary = { version = "1.2.3", features = ["derive"] } 12 | libfuzzer-sys = "0.4" 13 | 14 | [dependencies.generic-btree] 15 | path = ".." 16 | 17 | # Prevent this from interfering with workspaces 18 | [workspace] 19 | members = ["."] 20 | 21 | [profile.release] 22 | debug = true 23 | 24 | [[bin]] 25 | name = "ord" 26 | path = "fuzz_targets/ord.rs" 27 | test = false 28 | doc = false 29 | 30 | [[bin]] 31 | name = "rope" 32 | path = "fuzz_targets/rope.rs" 33 | test = false 34 | doc = false 35 | -------------------------------------------------------------------------------- /benches/utils.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | 3 | use pprof::flamegraph::{Direction, Options}; 4 | 5 | pub struct PProfGuard { 6 | path: String, 7 | guard: pprof::ProfilerGuard<'static>, 8 | } 9 | 10 | impl PProfGuard { 11 | #[must_use] 12 | pub fn new(name: &str) -> Self { 13 | let guard = pprof::ProfilerGuard::new(10_000).unwrap(); 14 | Self { 15 | path: name.to_string(), 16 | guard, 17 | } 18 | } 19 | } 20 | 21 | impl Drop for PProfGuard { 22 | fn drop(&mut self) { 23 | if let Ok(report) = self.guard.report().build() { 24 | let file = File::create(self.path.as_str()).unwrap(); 25 | let mut options = Options::default(); 26 | options.direction = Direction::Inverted; 27 | options.flame_chart = false; 28 | report.flamegraph_with_options(file, &mut options).unwrap(); 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /benches/bench_ord.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeSet; 2 | 3 | use criterion::{criterion_group, criterion_main, Criterion}; 4 | use generic_btree::{HeapVec, OrdTreeSet}; 5 | use rand::{Rng, SeedableRng}; 6 | mod utils; 7 | 8 | pub fn bench(c: &mut Criterion) { 9 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 10 | let data: HeapVec = (0..100_000).map(|_| rng.gen()).collect(); 11 | c.bench_function("OrdTree 100K insert", |b| { 12 | let guard = utils::PProfGuard::new("target/ord-tree.svg"); 13 | b.iter(|| { 14 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 15 | for &value in data.iter() { 16 | tree.insert(value); 17 | } 18 | }); 19 | drop(guard) 20 | }); 21 | 22 | c.bench_function("std BTree 100K insert", |b| { 23 | b.iter(|| { 24 | let mut tree: BTreeSet = BTreeSet::new(); 25 | for &value in data.iter() { 26 | tree.insert(value); 27 | } 28 | }); 29 | }); 30 | } 31 | 32 | criterion_group!(benches, bench); 33 | criterion_main!(benches); 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Zixuan Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/rope.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use arbitrary::Arbitrary; 4 | use generic_btree::Rope; 5 | use libfuzzer_sys::fuzz_target; 6 | 7 | #[derive(Arbitrary, Debug)] 8 | enum Action { 9 | Insert { pos: u8, content: u8 }, 10 | Delete { pos: u8, len: u8 }, 11 | } 12 | 13 | fuzz_target!(|data: Vec| { 14 | let mut rope = Rope::new(); 15 | let mut truth = String::new(); 16 | for action in data { 17 | match action { 18 | Action::Insert { pos, content } => { 19 | let pos = pos as usize % (truth.len() + 1); 20 | let s = content.to_string(); 21 | truth.insert_str(pos, &s); 22 | rope.insert(pos, &s); 23 | } 24 | Action::Delete { pos, len } => { 25 | let pos = pos as usize % (truth.len() + 1); 26 | let mut len = len as usize % 10; 27 | len = len.min(truth.len() - pos); 28 | 29 | rope.delete_range(pos..(pos + len)); 30 | truth.drain(pos..pos + len); 31 | } 32 | } 33 | } 34 | 35 | rope.check(); 36 | assert_eq!(rope.to_string(), truth); 37 | }); 38 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/ord.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use std::collections::BTreeSet; 4 | 5 | use arbitrary::Arbitrary; 6 | use generic_btree::OrdTreeSet; 7 | use libfuzzer_sys::fuzz_target; 8 | 9 | #[derive(Debug, Arbitrary)] 10 | enum Action { 11 | Insert(u8), 12 | Delete, 13 | } 14 | 15 | fuzz_target!(|actions: Vec| { 16 | let mut tree_a: BTreeSet = BTreeSet::new(); 17 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 18 | for action in actions { 19 | match action { 20 | Action::Insert(value) => { 21 | tree_a.insert(value); 22 | tree.insert(value); 23 | } 24 | Action::Delete => { 25 | let value = tree_a.iter().nth(3).copied(); 26 | if let Some(value) = value { 27 | tree_a.remove(&value); 28 | tree.delete(&value); 29 | } else { 30 | let value = tree_a.iter().nth(0).copied(); 31 | if let Some(value) = value { 32 | tree_a.remove(&value); 33 | tree.delete(&value); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | assert_eq!( 41 | tree_a.iter().collect::>(), 42 | tree.iter().collect::>() 43 | ); 44 | }); 45 | -------------------------------------------------------------------------------- /benches/automerge.rs: -------------------------------------------------------------------------------- 1 | use arbitrary::Arbitrary; 2 | use std::io::Read; 3 | 4 | use flate2::read::GzDecoder; 5 | use serde_json::Value; 6 | 7 | #[derive(Arbitrary)] 8 | pub struct TextAction { 9 | pub pos: usize, 10 | pub ins: String, 11 | pub del: usize, 12 | } 13 | 14 | pub fn get_automerge_actions() -> Vec { 15 | const RAW_DATA: &[u8; 901823] = include_bytes!("./automerge-paper.json.gz"); 16 | let mut actions = Vec::new(); 17 | let mut d = GzDecoder::new(&RAW_DATA[..]); 18 | let mut s = String::new(); 19 | d.read_to_string(&mut s).unwrap(); 20 | let json: Value = serde_json::from_str(&s).unwrap(); 21 | let txns = json.as_object().unwrap().get("txns"); 22 | for txn in txns.unwrap().as_array().unwrap() { 23 | let patches = txn 24 | .as_object() 25 | .unwrap() 26 | .get("patches") 27 | .unwrap() 28 | .as_array() 29 | .unwrap(); 30 | for patch in patches { 31 | let pos = patch[0].as_u64().unwrap() as usize; 32 | let del_here = patch[1].as_u64().unwrap() as usize; 33 | let ins_content = patch[2].as_str().unwrap(); 34 | actions.push(TextAction { 35 | pos, 36 | ins: ins_content.to_string(), 37 | del: del_here, 38 | }); 39 | } 40 | } 41 | actions 42 | } 43 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generic-btree" 3 | version = "0.10.7" 4 | edition = "2021" 5 | description = "Generic BTree for versatile purposes" 6 | readme = "README.md" 7 | license = "MIT" 8 | homepage = "https://github.com/loro-dev/generic-btree" 9 | repository = "https://github.com/loro-dev/generic-btree" 10 | authors = ["zxch3n "] 11 | keywords = ["btree", "data-structure"] 12 | include = ["Cargo.toml", "/src/**/*.rs", "/benches/**/*.rs"] 13 | documentation = "https://docs.rs/generic-btree" 14 | 15 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 16 | 17 | [dependencies] 18 | arref = "0.1.0" 19 | rustc-hash = "2.1.1" 20 | heapless = "0.9.1" 21 | itertools = "0.11.0" 22 | proc-macro2 = "1.0.67" 23 | thunderdome = { version = "0.6.2", package = "loro-thunderdome" } 24 | 25 | 26 | [dev-dependencies] 27 | arbitrary = { version = "1.2.3", features = ["derive"] } 28 | criterion = "0.7.0" 29 | jumprope = "1.0.0" 30 | ahash = "0.8.11" 31 | rand = "0.8.5" 32 | color-backtrace = "0.7.0" 33 | ctor = "0.1.26" 34 | pprof = { version = "0.15.0", features = [ 35 | "flamegraph", 36 | "criterion", 37 | "frame-pointer", 38 | ] } 39 | serde_json = "1.0.93" 40 | flate2 = "1.0.25" 41 | 42 | 43 | [[bench]] 44 | name = "bench_ord" 45 | harness = false 46 | 47 | [[bench]] 48 | name = "bench_rope" 49 | harness = false 50 | 51 | [profile.release] 52 | debug = true 53 | 54 | [features] 55 | test = [] 56 | -------------------------------------------------------------------------------- /src/generic_impl/len_finder.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use thunderdome::Index; 4 | 5 | use crate::rle::HasLength; 6 | use crate::{BTreeTrait, FindResult, Query}; 7 | 8 | /// A generic length finder 9 | pub struct LengthFinder { 10 | pub left: usize, 11 | pub slot: u8, 12 | pub parent: Option, 13 | } 14 | 15 | impl LengthFinder { 16 | #[inline(always)] 17 | pub fn new() -> Self { 18 | Self { 19 | left: 0, 20 | slot: 0, 21 | parent: None, 22 | } 23 | } 24 | } 25 | 26 | impl Default for LengthFinder { 27 | #[inline(always)] 28 | fn default() -> Self { 29 | Self::new() 30 | } 31 | } 32 | 33 | pub trait UseLengthFinder { 34 | fn get_len(cache: &B::Cache) -> usize; 35 | } 36 | 37 | impl + UseLengthFinder> Query 38 | for LengthFinder 39 | { 40 | type QueryArg = usize; 41 | 42 | #[inline(always)] 43 | fn init(target: &Self::QueryArg) -> Self { 44 | Self { 45 | left: *target, 46 | slot: 0, 47 | parent: None, 48 | } 49 | } 50 | 51 | #[inline(always)] 52 | fn find_node( 53 | &mut self, 54 | _: &Self::QueryArg, 55 | child_caches: &[crate::Child], 56 | ) -> crate::FindResult { 57 | let mut last_left = self.left; 58 | let is_internal = child_caches.first().unwrap().is_internal(); 59 | for (i, cache) in child_caches.iter().enumerate() { 60 | let len = B::get_len(&cache.cache); 61 | if self.left >= len { 62 | last_left = self.left; 63 | self.left -= len; 64 | } else { 65 | if is_internal { 66 | self.parent = Some(cache.arena.unwrap()); 67 | } else { 68 | self.slot = i as u8; 69 | } 70 | return FindResult::new_found(i, self.left); 71 | } 72 | } 73 | 74 | self.left = last_left; 75 | if is_internal { 76 | self.parent = Some(child_caches.last().unwrap().arena.unwrap()); 77 | } else { 78 | self.slot = child_caches.len() as u8 - 1; 79 | } 80 | FindResult::new_missing(child_caches.len() - 1, last_left) 81 | } 82 | 83 | #[inline(always)] 84 | fn confirm_elem( 85 | &mut self, 86 | _: &Self::QueryArg, 87 | elem: &::Elem, 88 | ) -> (usize, bool) { 89 | (self.left, self.left < elem.rle_len()) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /tests/integration.rs: -------------------------------------------------------------------------------- 1 | use range_num_map::RangeNumMap; 2 | 3 | mod range_num_map; 4 | 5 | mod test_range_num_map { 6 | use super::*; 7 | 8 | #[test] 9 | fn basic() { 10 | let mut range_map = RangeNumMap::new(); 11 | range_map.insert(1..10, 0); 12 | assert_eq!(range_map.get(0), None); 13 | assert_eq!(range_map.get(7), Some(0)); 14 | assert_eq!(range_map.get(8), Some(0)); 15 | assert_eq!(range_map.get(9), Some(0)); 16 | assert_eq!(range_map.get(10), None); 17 | range_map.insert(2..8, 1); 18 | assert_eq!(range_map.get(1), Some(0)); 19 | assert_eq!(range_map.get(2), Some(1)); 20 | assert_eq!(range_map.get(7), Some(1)); 21 | assert_eq!(range_map.get(8), Some(0)); 22 | assert_eq!(range_map.get(9), Some(0)); 23 | assert_eq!(range_map.get(10), None); 24 | } 25 | 26 | #[test] 27 | fn write_buffer_get_item() { 28 | let mut range_map = RangeNumMap::new(); 29 | for i in 0..100 { 30 | range_map.insert(i..i + 1, i as isize); 31 | } 32 | for i in 0..100 { 33 | assert_eq!(range_map.get(i), Some(i as isize)) 34 | } 35 | 36 | assert_eq!(range_map.get(100), None); 37 | range_map.insert(0..100, 100); 38 | assert_eq!(range_map.get(100), None); 39 | for i in 0..100 { 40 | assert_eq!(range_map.get(i), Some(100)) 41 | } 42 | } 43 | 44 | #[test] 45 | fn write_buffer_iter() { 46 | let mut range_map = RangeNumMap::new(); 47 | for i in 0..100 { 48 | range_map.insert(i..i + 1, i as isize); 49 | } 50 | 51 | range_map.insert(50..100, 100); 52 | for (r, value) in range_map.iter() { 53 | if r.start < 50 { 54 | assert_eq!(value, r.start as isize); 55 | } else { 56 | assert_eq!(value, 100); 57 | } 58 | } 59 | } 60 | 61 | #[test] 62 | fn write_buffer_drain() { 63 | let mut range_map = RangeNumMap::new(); 64 | for i in 0..100 { 65 | range_map.insert(i..i + 1, i as isize); 66 | } 67 | 68 | range_map.insert(50..80, 100); 69 | for (r, value) in range_map.drain(25..100) { 70 | if r.start < 50 || r.start >= 80 { 71 | assert_eq!(value, r.start as isize); 72 | } else { 73 | assert_eq!(value, 100); 74 | } 75 | } 76 | } 77 | 78 | #[test] 79 | fn range_plus() { 80 | let mut range_map = RangeNumMap::new(); 81 | for i in 0..100 { 82 | range_map.insert(i..i + 1, i as isize); 83 | } 84 | 85 | range_map.plus(50..110, 100); 86 | for (r, value) in range_map.iter() { 87 | assert!(r.start < 100); 88 | if r.start < 50 { 89 | assert_eq!(value, r.start as isize); 90 | } else { 91 | assert_eq!(value, r.start as isize + 100); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/rope.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::io::Read; 3 | 4 | use arbitrary::{Arbitrary, Unstructured}; 5 | use flate2::read::GzDecoder; 6 | use rand::{Rng, SeedableRng}; 7 | use serde_json::Value; 8 | 9 | use generic_btree::{HeapVec, Rope}; 10 | 11 | #[derive(Arbitrary, Debug, Clone, Copy)] 12 | enum RandomAction { 13 | Insert { pos: u8, content: u8 }, 14 | Delete { pos: u8, len: u8 }, 15 | } 16 | 17 | #[derive(Arbitrary)] 18 | pub struct TextAction { 19 | pub pos: usize, 20 | pub ins: String, 21 | pub del: usize, 22 | } 23 | 24 | pub fn get_automerge_actions() -> Vec { 25 | const RAW_DATA: &[u8; 901823] = include_bytes!("../benches/automerge-paper.json.gz"); 26 | let mut actions = Vec::new(); 27 | let mut d = GzDecoder::new(&RAW_DATA[..]); 28 | let mut s = String::new(); 29 | d.read_to_string(&mut s).unwrap(); 30 | let json: Value = serde_json::from_str(&s).unwrap(); 31 | let txns = json.as_object().unwrap().get("txns"); 32 | for txn in txns.unwrap().as_array().unwrap() { 33 | let patches = txn 34 | .as_object() 35 | .unwrap() 36 | .get("patches") 37 | .unwrap() 38 | .as_array() 39 | .unwrap(); 40 | for patch in patches { 41 | let pos = patch[0].as_u64().unwrap() as usize; 42 | let del_here = patch[1].as_u64().unwrap() as usize; 43 | let ins_content = patch[2].as_str().unwrap(); 44 | actions.push(TextAction { 45 | pos, 46 | ins: ins_content.to_string(), 47 | del: del_here, 48 | }); 49 | } 50 | } 51 | actions 52 | } 53 | 54 | pub fn main() { 55 | let args: Vec = env::args().collect(); 56 | if args.len() > 1 && args[1].eq_ignore_ascii_case("automerge") { 57 | println!("Running on automerge dataset"); 58 | let actions = get_automerge_actions(); 59 | bench(actions); 60 | } else { 61 | println!("Running on random generated actions 10k"); 62 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 63 | let data: HeapVec = (0..1_000_000).map(|_| rng.gen()).collect(); 64 | let mut gen = Unstructured::new(&data); 65 | let actions: [RandomAction; 10_000] = gen.arbitrary().unwrap(); 66 | 67 | let mut rope = Rope::new(); 68 | for _ in 0..10000 { 69 | for action in actions.iter() { 70 | match *action { 71 | RandomAction::Insert { pos, content } => { 72 | let pos = pos as usize % (rope.len() + 1); 73 | let s = content.to_string(); 74 | rope.insert(pos, &s); 75 | } 76 | RandomAction::Delete { pos, len } => { 77 | let pos = pos as usize % (rope.len() + 1); 78 | let mut len = len as usize % 10; 79 | len = len.min(rope.len() - pos); 80 | rope.delete_range(pos..(pos + len)); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | 88 | #[inline(never)] 89 | fn bench(actions: Vec) { 90 | for _ in 0..100 { 91 | let mut rope = Rope::new(); 92 | for action in actions.iter() { 93 | if action.del > 0 { 94 | rope.delete_range(action.pos..action.pos + action.del); 95 | } 96 | if !action.ins.is_empty() { 97 | rope.insert(action.pos, &action.ins) 98 | } 99 | } 100 | // println!("{}", rope.to_string()); 101 | // rope.diagnose(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/rle.rs: -------------------------------------------------------------------------------- 1 | use core::ops::RangeBounds; 2 | use std::ops::Range; 3 | 4 | /// For better performance, it's advised to impl split 5 | pub trait Sliceable: HasLength + Sized { 6 | #[must_use] 7 | fn _slice(&self, range: Range) -> Self; 8 | 9 | #[must_use] 10 | #[inline(always)] 11 | fn slice(&self, range: impl RangeBounds) -> Self { 12 | let start = match range.start_bound() { 13 | std::ops::Bound::Included(x) => *x, 14 | std::ops::Bound::Excluded(x) => x + 1, 15 | std::ops::Bound::Unbounded => 0, 16 | }; 17 | 18 | let end = match range.end_bound() { 19 | std::ops::Bound::Included(x) => x + 1, 20 | std::ops::Bound::Excluded(x) => *x, 21 | std::ops::Bound::Unbounded => self.rle_len(), 22 | }; 23 | 24 | self._slice(start..end) 25 | } 26 | 27 | /// slice in-place 28 | #[inline(always)] 29 | fn slice_(&mut self, range: impl RangeBounds) { 30 | *self = self.slice(range); 31 | } 32 | 33 | #[must_use] 34 | fn split(&mut self, pos: usize) -> Self { 35 | let right = self.slice(pos..); 36 | self.slice_(..pos); 37 | right 38 | } 39 | 40 | /// Update the slice in the given range. 41 | /// This method may split `self` into two or three parts. 42 | /// If so, it will make `self` the leftmost part and return the next split parts. 43 | /// 44 | /// # Example 45 | /// 46 | /// If `self.rle_len() == 10`, `self.update(1..5)` will split self into three parts and update the middle part. 47 | /// It returns the middle and the right part. 48 | fn update_with_split( 49 | &mut self, 50 | range: impl RangeBounds, 51 | f: impl FnOnce(&mut Self), 52 | ) -> (Option, Option) { 53 | let start = match range.start_bound() { 54 | std::ops::Bound::Included(x) => *x, 55 | std::ops::Bound::Excluded(x) => x + 1, 56 | std::ops::Bound::Unbounded => 0, 57 | }; 58 | 59 | let end = match range.end_bound() { 60 | std::ops::Bound::Included(x) => x + 1, 61 | std::ops::Bound::Excluded(x) => *x, 62 | std::ops::Bound::Unbounded => self.rle_len(), 63 | }; 64 | 65 | if start >= end { 66 | return (None, None); 67 | } 68 | 69 | match (start == 0, end == self.rle_len()) { 70 | (true, true) => { 71 | f(self); 72 | (None, None) 73 | } 74 | (true, false) => { 75 | let right = self.split(end); 76 | f(self); 77 | (Some(right), None) 78 | } 79 | (false, true) => { 80 | let mut right = self.split(start); 81 | f(&mut right); 82 | (Some(right), None) 83 | } 84 | (false, false) => { 85 | let right = self.split(end); 86 | let mut middle = self.split(start); 87 | f(&mut middle); 88 | (Some(middle), Some(right)) 89 | } 90 | } 91 | } 92 | } 93 | 94 | pub trait Mergeable { 95 | /// Whether self can merge rhs with self on the left. 96 | /// 97 | /// Note: This is not symmetric. 98 | fn can_merge(&self, rhs: &Self) -> bool; 99 | fn merge_right(&mut self, rhs: &Self); 100 | fn merge_left(&mut self, left: &Self); 101 | } 102 | 103 | pub trait HasLength { 104 | fn rle_len(&self) -> usize; 105 | } 106 | 107 | pub trait TryInsert { 108 | fn try_insert(&mut self, pos: usize, elem: Self) -> Result<(), Self> 109 | where 110 | Self: Sized; 111 | } 112 | 113 | pub trait CanRemove { 114 | fn can_remove(&self) -> bool; 115 | } 116 | 117 | impl CanRemove for () { 118 | fn can_remove(&self) -> bool { 119 | true 120 | } 121 | } 122 | impl CanRemove for usize { 123 | fn can_remove(&self) -> bool { 124 | *self == 0 125 | } 126 | } 127 | impl CanRemove for isize { 128 | fn can_remove(&self) -> bool { 129 | *self == 0 130 | } 131 | } 132 | impl CanRemove for u32 { 133 | fn can_remove(&self) -> bool { 134 | *self == 0 135 | } 136 | } 137 | impl CanRemove for i32 { 138 | fn can_remove(&self) -> bool { 139 | *self == 0 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /benches/bench_rope.rs: -------------------------------------------------------------------------------- 1 | use arbitrary::{Arbitrary, Unstructured}; 2 | use criterion::{criterion_group, criterion_main, Criterion}; 3 | use generic_btree::{HeapVec, Rope}; 4 | use jumprope::JumpRope; 5 | use rand::{Rng, SeedableRng}; 6 | mod automerge; 7 | mod utils; 8 | 9 | #[derive(Arbitrary, Debug, Clone, Copy)] 10 | enum Action { 11 | Insert { pos: u8, content: u8 }, 12 | Delete { pos: u8, len: u8 }, 13 | } 14 | 15 | pub fn bench(c: &mut Criterion) { 16 | bench_random(c); 17 | bench_automerge(c) 18 | } 19 | 20 | fn bench_random(c: &mut Criterion) { 21 | let mut b = c.benchmark_group("10K random insert/delete"); 22 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 23 | let data: HeapVec = (0..1_000_000).map(|_| rng.gen()).collect(); 24 | let mut gen = Unstructured::new(&data); 25 | let actions: [Action; 10_000] = gen.arbitrary().unwrap(); 26 | b.bench_function("Rope 10K insert/delete", |b| { 27 | let guard = utils::PProfGuard::new("target/rope.svg"); 28 | b.iter(|| { 29 | let mut rope = Rope::new(); 30 | for action in actions.iter() { 31 | match *action { 32 | Action::Insert { pos, content } => { 33 | let pos = pos as usize % (rope.len() + 1); 34 | let s = content.to_string(); 35 | rope.insert(pos, &s); 36 | } 37 | Action::Delete { pos, len } => { 38 | let pos = pos as usize % (rope.len() + 1); 39 | let mut len = len as usize % 10; 40 | len = len.min(rope.len() - pos); 41 | rope.delete_range(pos..(pos + len)); 42 | } 43 | } 44 | } 45 | }); 46 | drop(guard); 47 | }); 48 | 49 | b.bench_function("RawString", |b| { 50 | b.iter(|| { 51 | let mut raw = String::new(); 52 | for action in actions.iter() { 53 | match *action { 54 | Action::Insert { pos, content } => { 55 | let pos = pos as usize % (raw.len() + 1); 56 | let s = content.to_string(); 57 | raw.insert_str(pos, &s); 58 | } 59 | Action::Delete { pos, len } => { 60 | let pos = pos as usize % (raw.len() + 1); 61 | let mut len = len as usize % 10; 62 | len = len.min(raw.len() - pos); 63 | raw.drain(pos..(pos + len)); 64 | } 65 | } 66 | } 67 | }); 68 | }); 69 | 70 | b.bench_function("JumpRope", |b| { 71 | b.iter(|| { 72 | let mut rope = JumpRope::new(); 73 | for action in actions.iter() { 74 | match *action { 75 | Action::Insert { pos, content } => { 76 | let pos = pos as usize % (rope.len_bytes() + 1); 77 | let s = content.to_string(); 78 | rope.insert(pos, &s); 79 | } 80 | Action::Delete { pos, len } => { 81 | let pos = pos as usize % (rope.len_bytes() + 1); 82 | let mut len = len as usize % 10; 83 | len = len.min(rope.len_bytes() - pos); 84 | rope.remove(pos..(pos + len)); 85 | } 86 | } 87 | } 88 | }); 89 | }); 90 | } 91 | 92 | fn bench_automerge(c: &mut Criterion) { 93 | let mut b = c.benchmark_group("Automerge paper"); 94 | let actions = automerge::get_automerge_actions(); 95 | b.bench_function("Rope", |b| { 96 | let guard = utils::PProfGuard::new("target/rope-automerge.svg"); 97 | b.iter(|| { 98 | let mut rope = Rope::new(); 99 | for action in actions.iter() { 100 | if action.del > 0 { 101 | rope.delete_range(action.pos..action.pos + action.del); 102 | } 103 | if !action.ins.is_empty() { 104 | rope.insert(action.pos, &action.ins) 105 | } 106 | } 107 | }); 108 | drop(guard); 109 | }); 110 | 111 | b.bench_function("JumpRope", |b| { 112 | b.iter(|| { 113 | let mut rope = JumpRope::new(); 114 | for action in actions.iter() { 115 | if action.del > 0 { 116 | rope.remove(action.pos..action.pos + action.del); 117 | } 118 | if !action.ins.is_empty() { 119 | rope.insert(action.pos, &action.ins) 120 | } 121 | } 122 | }); 123 | }); 124 | } 125 | 126 | criterion_group!(benches, bench); 127 | criterion_main!(benches); 128 | -------------------------------------------------------------------------------- /tests/range_num_map/mod.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Range; 2 | 3 | use generic_btree::{ 4 | rle::{CanRemove, HasLength, Mergeable, Sliceable, TryInsert}, 5 | BTree, BTreeTrait, LengthFinder, UseLengthFinder, 6 | }; 7 | 8 | /// This struct keep the mapping of ranges to numbers 9 | #[derive(Debug)] 10 | pub struct RangeNumMap(BTree); 11 | 12 | struct RangeNumMapTrait; 13 | 14 | #[derive(Debug)] 15 | struct Elem { 16 | value: Option, 17 | len: usize, 18 | } 19 | 20 | impl RangeNumMap { 21 | pub fn new() -> Self { 22 | Self(BTree::new()) 23 | } 24 | 25 | pub fn insert(&mut self, range: Range, value: isize) { 26 | self.reserve_range(&range); 27 | if let Some(range) = self.0.range::(range.clone()) { 28 | self.0 29 | .update(range.start.cursor..range.end.cursor, &mut |slice| { 30 | slice.value = Some(value); 31 | None 32 | }); 33 | } else { 34 | assert_eq!(range.start, 0); 35 | self.0.push(Elem { 36 | value: Some(value), 37 | len: range.len(), 38 | }); 39 | } 40 | } 41 | 42 | pub fn get(&mut self, index: usize) -> Option { 43 | let result = self.0.query::(&index)?; 44 | if !result.found { 45 | return None; 46 | } 47 | 48 | self.0.get_elem(result.leaf()).and_then(|x| x.value) 49 | } 50 | 51 | pub fn iter(&mut self) -> impl Iterator, isize)> + '_ { 52 | let mut index = 0; 53 | self.0.iter().filter_map(move |elem| { 54 | let len = elem.len; 55 | let value = elem.value?; 56 | let range = index..index + len; 57 | index += len; 58 | Some((range, value)) 59 | }) 60 | } 61 | 62 | pub fn plus(&mut self, range: Range, change: isize) { 63 | self.reserve_range(&range); 64 | if let Some(range) = self.0.range::(range) { 65 | self.0 66 | .update(range.start.cursor..range.end.cursor, &mut |slice| { 67 | if let Some(v) = &mut slice.value { 68 | *v += change; 69 | } 70 | 71 | None 72 | }); 73 | } 74 | } 75 | 76 | fn reserve_range(&mut self, range: &Range) { 77 | if self.len() < range.end { 78 | self.0.push(Elem { 79 | value: None, 80 | len: range.end - self.len() + 10, 81 | }); 82 | } 83 | } 84 | 85 | pub fn drain( 86 | &mut self, 87 | range: Range, 88 | ) -> impl Iterator, isize)> + '_ { 89 | let mut index = range.start; 90 | let self1 = &self.0; 91 | let from = self1.query::(&range.start); 92 | let to = self1.query::(&range.end); 93 | generic_btree::iter::Drain::new(&mut self.0, from, to).filter_map(move |elem| { 94 | let len = elem.len; 95 | let value = elem.value?; 96 | let range = index..index + len; 97 | index += len; 98 | Some((range, value)) 99 | }) 100 | } 101 | 102 | pub fn len(&self) -> usize { 103 | *self.0.root_cache() 104 | } 105 | } 106 | 107 | impl UseLengthFinder for RangeNumMapTrait { 108 | fn get_len(cache: &usize) -> usize { 109 | *cache 110 | } 111 | } 112 | 113 | impl HasLength for Elem { 114 | fn rle_len(&self) -> usize { 115 | self.len 116 | } 117 | } 118 | 119 | impl Mergeable for Elem { 120 | fn can_merge(&self, rhs: &Self) -> bool { 121 | self.value == rhs.value || rhs.len == 0 122 | } 123 | 124 | fn merge_right(&mut self, rhs: &Self) { 125 | self.len += rhs.len 126 | } 127 | 128 | fn merge_left(&mut self, left: &Self) { 129 | self.len += left.len; 130 | } 131 | } 132 | 133 | impl Sliceable for Elem { 134 | fn _slice(&self, range: Range) -> Self { 135 | Elem { 136 | value: self.value, 137 | len: range.len(), 138 | } 139 | } 140 | 141 | fn slice_(&mut self, range: impl std::ops::RangeBounds) 142 | where 143 | Self: Sized, 144 | { 145 | let len = match range.end_bound() { 146 | std::ops::Bound::Included(x) => x + 1, 147 | std::ops::Bound::Excluded(x) => *x, 148 | std::ops::Bound::Unbounded => self.len, 149 | } - match range.start_bound() { 150 | std::ops::Bound::Included(x) => *x, 151 | std::ops::Bound::Excluded(x) => x + 1, 152 | std::ops::Bound::Unbounded => 0, 153 | }; 154 | 155 | self.len = len; 156 | } 157 | } 158 | 159 | impl TryInsert for Elem { 160 | fn try_insert(&mut self, _: usize, elem: Self) -> Result<(), Self> 161 | where 162 | Self: Sized, 163 | { 164 | Err(elem) 165 | } 166 | } 167 | 168 | impl CanRemove for Elem { 169 | fn can_remove(&self) -> bool { 170 | self.len == 0 171 | } 172 | } 173 | 174 | impl BTreeTrait for RangeNumMapTrait { 175 | /// value 176 | type Elem = Elem; 177 | /// len 178 | type Cache = usize; 179 | 180 | type CacheDiff = isize; 181 | 182 | #[inline(always)] 183 | fn calc_cache_internal( 184 | cache: &mut Self::Cache, 185 | caches: &[generic_btree::Child], 186 | ) -> isize { 187 | let new_cache = caches.iter().map(|c| c.cache).sum(); 188 | let diff = new_cache as isize - *cache as isize; 189 | *cache = new_cache; 190 | diff 191 | } 192 | 193 | #[inline(always)] 194 | fn merge_cache_diff(diff1: &mut Self::CacheDiff, diff2: &Self::CacheDiff) { 195 | *diff1 += diff2; 196 | } 197 | 198 | #[inline(always)] 199 | fn get_elem_cache(elem: &Self::Elem) -> Self::Cache { 200 | elem.len 201 | } 202 | 203 | #[inline(always)] 204 | fn apply_cache_diff(cache: &mut Self::Cache, diff: &Self::CacheDiff) { 205 | *cache = (*cache as isize + diff) as usize; 206 | } 207 | 208 | #[inline(always)] 209 | fn new_cache_to_diff(cache: &Self::Cache) -> Self::CacheDiff { 210 | *cache as isize 211 | } 212 | 213 | fn sub_cache(cache_lhs: &Self::Cache, cache_rhs: &Self::Cache) -> Self::CacheDiff { 214 | *cache_lhs as isize - *cache_rhs as isize 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /fuzz/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "arbitrary" 7 | version = "1.2.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad" 10 | dependencies = [ 11 | "derive_arbitrary", 12 | ] 13 | 14 | [[package]] 15 | name = "arref" 16 | version = "0.1.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "2ccd462b64c3c72f1be8305905a85d85403d768e8690c9b8bd3b9009a5761679" 19 | 20 | [[package]] 21 | name = "atomic-polyfill" 22 | version = "0.1.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" 25 | dependencies = [ 26 | "critical-section", 27 | ] 28 | 29 | [[package]] 30 | name = "autocfg" 31 | version = "1.1.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 34 | 35 | [[package]] 36 | name = "byteorder" 37 | version = "1.4.3" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 40 | 41 | [[package]] 42 | name = "cc" 43 | version = "1.0.79" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 46 | dependencies = [ 47 | "jobserver", 48 | ] 49 | 50 | [[package]] 51 | name = "critical-section" 52 | version = "1.1.2" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 55 | 56 | [[package]] 57 | name = "derive_arbitrary" 58 | version = "1.2.3" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "8beee4701e2e229e8098bbdecdca12449bc3e322f137d269182fa1291e20bd00" 61 | dependencies = [ 62 | "proc-macro2", 63 | "quote", 64 | "syn", 65 | ] 66 | 67 | [[package]] 68 | name = "either" 69 | version = "1.11.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" 72 | 73 | [[package]] 74 | name = "fxhash" 75 | version = "0.2.1" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 78 | dependencies = [ 79 | "byteorder", 80 | ] 81 | 82 | [[package]] 83 | name = "generic-btree" 84 | version = "0.8.4" 85 | dependencies = [ 86 | "arref", 87 | "fxhash", 88 | "heapless", 89 | "itertools", 90 | "loro-thunderdome", 91 | "proc-macro2", 92 | ] 93 | 94 | [[package]] 95 | name = "generic-btree-fuzz" 96 | version = "0.0.0" 97 | dependencies = [ 98 | "arbitrary", 99 | "generic-btree", 100 | "libfuzzer-sys", 101 | ] 102 | 103 | [[package]] 104 | name = "hash32" 105 | version = "0.2.1" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" 108 | dependencies = [ 109 | "byteorder", 110 | ] 111 | 112 | [[package]] 113 | name = "heapless" 114 | version = "0.7.16" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" 117 | dependencies = [ 118 | "atomic-polyfill", 119 | "hash32", 120 | "rustc_version", 121 | "spin", 122 | "stable_deref_trait", 123 | ] 124 | 125 | [[package]] 126 | name = "itertools" 127 | version = "0.11.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 130 | dependencies = [ 131 | "either", 132 | ] 133 | 134 | [[package]] 135 | name = "jobserver" 136 | version = "0.1.25" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" 139 | dependencies = [ 140 | "libc", 141 | ] 142 | 143 | [[package]] 144 | name = "libc" 145 | version = "0.2.139" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 148 | 149 | [[package]] 150 | name = "libfuzzer-sys" 151 | version = "0.4.6" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e" 154 | dependencies = [ 155 | "arbitrary", 156 | "cc", 157 | "once_cell", 158 | ] 159 | 160 | [[package]] 161 | name = "lock_api" 162 | version = "0.4.10" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 165 | dependencies = [ 166 | "autocfg", 167 | "scopeguard", 168 | ] 169 | 170 | [[package]] 171 | name = "loro-thunderdome" 172 | version = "0.6.2" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" 175 | 176 | [[package]] 177 | name = "once_cell" 178 | version = "1.17.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 181 | 182 | [[package]] 183 | name = "proc-macro2" 184 | version = "1.0.67" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" 187 | dependencies = [ 188 | "unicode-ident", 189 | ] 190 | 191 | [[package]] 192 | name = "quote" 193 | version = "1.0.23" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 196 | dependencies = [ 197 | "proc-macro2", 198 | ] 199 | 200 | [[package]] 201 | name = "rustc_version" 202 | version = "0.4.0" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 205 | dependencies = [ 206 | "semver", 207 | ] 208 | 209 | [[package]] 210 | name = "scopeguard" 211 | version = "1.2.0" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 214 | 215 | [[package]] 216 | name = "semver" 217 | version = "1.0.19" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" 220 | 221 | [[package]] 222 | name = "spin" 223 | version = "0.9.8" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 226 | dependencies = [ 227 | "lock_api", 228 | ] 229 | 230 | [[package]] 231 | name = "stable_deref_trait" 232 | version = "1.2.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 235 | 236 | [[package]] 237 | name = "syn" 238 | version = "1.0.107" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 241 | dependencies = [ 242 | "proc-macro2", 243 | "quote", 244 | "unicode-ident", 245 | ] 246 | 247 | [[package]] 248 | name = "unicode-ident" 249 | version = "1.0.6" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 252 | -------------------------------------------------------------------------------- /src/generic_impl/gap_buffer.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Range, RangeBounds}; 2 | 3 | use crate::rle::{CanRemove, HasLength, Mergeable, Sliceable, TryInsert}; 4 | 5 | #[cfg(not(test))] 6 | pub const MAX_STRING_SIZE: usize = 128; 7 | #[cfg(test)] 8 | pub const MAX_STRING_SIZE: usize = 12; 9 | 10 | #[derive(Debug, Clone)] 11 | pub(super) struct GapBuffer { 12 | buffer: [u8; MAX_STRING_SIZE], 13 | gap_start: u16, 14 | gap_len: u16, 15 | } 16 | 17 | impl GapBuffer { 18 | pub fn new() -> Self { 19 | Self { 20 | buffer: [0; MAX_STRING_SIZE], 21 | gap_start: 0, 22 | gap_len: MAX_STRING_SIZE as u16, 23 | } 24 | } 25 | 26 | pub fn shift_at(&mut self, index: usize) { 27 | if index > self.len() { 28 | panic!("index {} out of range len={}", index, self.len()); 29 | } 30 | 31 | let gap_start = self.gap_start as usize; 32 | let gap_end = (self.gap_start + self.gap_len) as usize; 33 | match index.cmp(&gap_start) { 34 | std::cmp::Ordering::Equal => {} 35 | std::cmp::Ordering::Less => { 36 | let gap_move = gap_start - index; 37 | self.buffer 38 | .copy_within(index..gap_start, gap_end - gap_move); 39 | self.gap_start -= gap_move as u16; 40 | } 41 | std::cmp::Ordering::Greater => { 42 | let gap_move = index - gap_start; 43 | let move_end = self.buffer.len().min(gap_end + gap_move); 44 | self.buffer.copy_within(gap_end..move_end, gap_start); 45 | self.gap_start += gap_move as u16; 46 | } 47 | } 48 | } 49 | 50 | #[allow(unused)] 51 | pub fn push(&mut self, value: u8) -> Result<(), ()> { 52 | if self.gap_len == 0 { 53 | return Err(()); 54 | } 55 | self.buffer[self.gap_start as usize] = value; 56 | self.gap_start += 1; 57 | self.gap_len -= 1; 58 | Ok(()) 59 | } 60 | 61 | #[inline(always)] 62 | pub fn push_bytes(&mut self, bytes: &[u8]) -> Result<(), ()> { 63 | self.insert_bytes(self.len(), bytes) 64 | } 65 | 66 | pub fn insert_bytes(&mut self, index: usize, bytes: &[u8]) -> Result<(), ()> { 67 | if (self.gap_len as usize) < bytes.len() { 68 | return Err(()); 69 | } 70 | 71 | self.shift_at(index); 72 | self.buffer[index..index + bytes.len()].copy_from_slice(bytes); 73 | self.gap_start += bytes.len() as u16; 74 | self.gap_len -= bytes.len() as u16; 75 | Ok(()) 76 | } 77 | 78 | pub fn insert_bytes_pair( 79 | &mut self, 80 | index: usize, 81 | (left, right): (&[u8], &[u8]), 82 | ) -> Result<(), ()> { 83 | let len = left.len() + right.len(); 84 | if (self.gap_len as usize) < len { 85 | return Err(()); 86 | } 87 | 88 | self.shift_at(index); 89 | self.buffer[index..index + left.len()].copy_from_slice(left); 90 | self.buffer[index + left.len()..index + len].copy_from_slice(right); 91 | self.gap_start += len as u16; 92 | self.gap_len -= len as u16; 93 | Ok(()) 94 | } 95 | 96 | pub fn delete(&mut self, range: impl RangeBounds) { 97 | let mut start = match range.start_bound() { 98 | std::ops::Bound::Included(x) => *x, 99 | std::ops::Bound::Excluded(x) => x + 1, 100 | std::ops::Bound::Unbounded => 0, 101 | }; 102 | let mut end = match range.end_bound() { 103 | std::ops::Bound::Included(x) => x + 1, 104 | std::ops::Bound::Excluded(x) => *x, 105 | std::ops::Bound::Unbounded => self.len(), 106 | }; 107 | 108 | end = end.min(self.len()); 109 | start = start.min(self.len()).min(end); 110 | if start == end { 111 | return; 112 | } 113 | 114 | let len = end - start; 115 | self.shift_at(end); 116 | self.gap_start = start as u16; 117 | self.gap_len += len as u16; 118 | } 119 | 120 | #[inline] 121 | pub fn capacity(&self) -> usize { 122 | self.buffer.len() 123 | } 124 | 125 | #[inline] 126 | pub fn len(&self) -> usize { 127 | self.buffer.len() - self.gap_len as usize 128 | } 129 | 130 | pub fn as_bytes(&self) -> (&[u8], &[u8]) { 131 | ( 132 | &self.buffer[..self.gap_start as usize], 133 | &self.buffer[(self.gap_start + self.gap_len) as usize..], 134 | ) 135 | } 136 | 137 | #[allow(unused)] 138 | pub fn to_vec(&self) -> Vec { 139 | let mut vec = Vec::with_capacity(self.len()); 140 | let (left, right) = self.as_bytes(); 141 | vec.extend_from_slice(left); 142 | vec.extend_from_slice(right); 143 | vec 144 | } 145 | 146 | pub(crate) fn from_str(elem: &str) -> impl Iterator + '_ { 147 | let mut i = 0; 148 | let elem = elem.as_bytes(); 149 | std::iter::from_fn(move || { 150 | if i >= elem.len() { 151 | return None; 152 | } 153 | 154 | let mut gb = GapBuffer::new(); 155 | gb.push_bytes(&elem[i..(i + MAX_STRING_SIZE).min(elem.len())]) 156 | .unwrap(); 157 | i += MAX_STRING_SIZE; 158 | Some(gb) 159 | }) 160 | } 161 | } 162 | 163 | impl HasLength for GapBuffer { 164 | fn rle_len(&self) -> usize { 165 | self.len() 166 | } 167 | } 168 | 169 | impl Sliceable for GapBuffer { 170 | fn _slice(&self, range: Range) -> Self { 171 | let mut gb = Self::new(); 172 | let start = range.start; 173 | let end = range.end; 174 | 175 | let (l, r) = self.as_bytes(); 176 | if start < l.len() { 177 | gb.push_bytes(&l[start..end.min(l.len())]).unwrap(); 178 | } 179 | if end > l.len() { 180 | gb.push_bytes(&r[start.saturating_sub(l.len())..end.saturating_sub(l.len())]) 181 | .unwrap(); 182 | } 183 | 184 | debug_assert_eq!(gb.len(), end - start); 185 | gb 186 | } 187 | 188 | fn slice_(&mut self, range: impl RangeBounds) 189 | where 190 | Self: Sized, 191 | { 192 | let start = match range.start_bound() { 193 | std::ops::Bound::Included(x) => *x, 194 | std::ops::Bound::Excluded(x) => x + 1, 195 | std::ops::Bound::Unbounded => 0, 196 | }; 197 | let end = match range.end_bound() { 198 | std::ops::Bound::Included(x) => x + 1, 199 | std::ops::Bound::Excluded(x) => *x, 200 | std::ops::Bound::Unbounded => self.len(), 201 | }; 202 | 203 | self.delete(end..); 204 | self.delete(..start); 205 | debug_assert_eq!(self.len(), end - start); 206 | } 207 | 208 | fn split(&mut self, pos: usize) -> Self 209 | where 210 | Self: Sized, 211 | { 212 | self.shift_at(pos); 213 | let right = self.as_bytes().1; 214 | let mut r = Self::new(); 215 | r.push_bytes(right).unwrap(); 216 | self.gap_len = (self.capacity() - pos) as u16; 217 | r 218 | } 219 | } 220 | 221 | impl Mergeable for GapBuffer { 222 | fn can_merge(&self, rhs: &Self) -> bool { 223 | self.len() + rhs.len() <= MAX_STRING_SIZE 224 | } 225 | 226 | fn merge_right(&mut self, rhs: &Self) { 227 | let pair = rhs.as_bytes(); 228 | self.insert_bytes_pair(self.len(), pair).unwrap(); 229 | } 230 | 231 | fn merge_left(&mut self, left: &Self) { 232 | let pair = left.as_bytes(); 233 | self.insert_bytes_pair(0, pair).unwrap(); 234 | } 235 | } 236 | 237 | impl TryInsert for GapBuffer { 238 | fn try_insert(&mut self, pos: usize, elem: Self) -> Result<(), Self> 239 | where 240 | Self: Sized, 241 | { 242 | if self.len() + elem.len() > MAX_STRING_SIZE { 243 | return Err(elem); 244 | } 245 | 246 | let pair = elem.as_bytes(); 247 | self.insert_bytes_pair(pos, pair).unwrap(); 248 | Ok(()) 249 | } 250 | } 251 | 252 | impl CanRemove for GapBuffer { 253 | fn can_remove(&self) -> bool { 254 | self.len() == 0 255 | } 256 | } 257 | 258 | #[cfg(test)] 259 | mod test { 260 | use super::*; 261 | 262 | #[test] 263 | fn basic() { 264 | let mut gb: GapBuffer = GapBuffer::new(); 265 | gb.insert_bytes(0, &[3, 8]).unwrap(); 266 | assert_eq!(gb.to_vec(), vec![3, 8]); 267 | gb.insert_bytes(1, &[4, 5, 6]).unwrap(); 268 | assert_eq!(gb.to_vec(), vec![3, 4, 5, 6, 8]); 269 | assert_eq!(gb.len(), 5); 270 | gb.insert_bytes(4, &[7]).unwrap(); 271 | assert_eq!(gb.to_vec(), vec![3, 4, 5, 6, 7, 8]); 272 | gb.insert_bytes(0, &[1, 2, 9, 9]).unwrap(); 273 | assert_eq!(gb.to_vec(), vec![1, 2, 9, 9, 3, 4, 5, 6, 7, 8]); 274 | gb.delete(2..4); 275 | assert_eq!(gb.len(), 8); 276 | let (left, right) = gb.as_bytes(); 277 | assert_eq!(left, &[1, 2]); 278 | assert_eq!(right, &[3, 4, 5, 6, 7, 8]); 279 | assert_eq!(gb.to_vec(), vec![1, 2, 3, 4, 5, 6, 7, 8]) 280 | } 281 | 282 | #[test] 283 | fn slice() { 284 | let mut gb = GapBuffer::new(); 285 | gb.push_bytes(&[0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); 286 | gb.shift_at(5); 287 | let b = gb.slice(2..5); 288 | assert_eq!(b.to_vec(), vec![2, 3, 4]); 289 | 290 | gb.slice_(2..5); 291 | assert_eq!(gb.to_vec(), vec![2, 3, 4]); 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /src/iter.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | delete_range, rle::HasLength, ArenaIndex, BTree, BTreeTrait, Cursor, LeafNode, NodePath, 3 | QueryResult, 4 | }; 5 | 6 | /// iterate node (not element) from the start path to the **inclusive** end path 7 | pub(super) struct Iter<'a, B: BTreeTrait> { 8 | tree: &'a BTree, 9 | inclusive_end: NodePath, 10 | path: NodePath, 11 | done: bool, 12 | } 13 | 14 | struct TempStore { 15 | start_path: NodePath, 16 | end_path: NodePath, 17 | leaf_before_drain_range: Option, 18 | leaf_after_drain_range: Option, 19 | } 20 | 21 | pub struct Drain<'a, B: BTreeTrait> { 22 | tree: &'a mut BTree, 23 | current_path: NodePath, 24 | done: bool, 25 | end_cursor: Option, 26 | store: Option>, 27 | } 28 | 29 | impl<'a, B: BTreeTrait> Drain<'a, B> { 30 | pub fn new( 31 | tree: &'a mut BTree, 32 | start_result: Option, 33 | end_result: Option, 34 | ) -> Self { 35 | if start_result.is_none() || end_result.is_none() { 36 | return Self::none(tree); 37 | } 38 | 39 | let start_result = start_result.unwrap(); 40 | let end_result = end_result.unwrap(); 41 | let end_result = tree.split_leaf_if_needed(end_result.cursor).new_pos; 42 | let Some(start_result) = tree.split_leaf_if_needed(start_result.cursor).new_pos else { 43 | // if start from the right most leaf, the range is empty 44 | return Self::none(tree); 45 | }; 46 | let start_path = tree.get_path(start_result.leaf.into()); 47 | let end_path = tree.get_path( 48 | end_result 49 | .map(|x| x.leaf.into()) 50 | .unwrap_or_else(|| tree.last_leaf().unwrap().into()), 51 | ); 52 | let leaf_before_drain_range = { 53 | let node_idx = start_path.last().unwrap().arena; 54 | if start_result.offset == 0 { 55 | tree.prev_same_level_in_node(node_idx) 56 | } else { 57 | Some(node_idx) 58 | } 59 | }; 60 | let leaf_after_drain_range = { 61 | let node_idx = end_path.last().unwrap().arena; 62 | if let Some(end) = end_result { 63 | let len = tree.leaf_nodes.get(end.leaf.0).unwrap().elem.rle_len(); 64 | if len == end.offset { 65 | tree.next_same_level_in_node(node_idx) 66 | } else { 67 | Some(node_idx) 68 | } 69 | } else { 70 | None 71 | } 72 | }; 73 | Self { 74 | current_path: tree.get_path(start_result.leaf.into()), 75 | tree, 76 | done: false, 77 | end_cursor: end_result, 78 | store: Some(Box::new(TempStore { 79 | start_path, 80 | end_path, 81 | leaf_before_drain_range, 82 | leaf_after_drain_range, 83 | })), 84 | } 85 | } 86 | 87 | fn none(tree: &'a mut BTree) -> Drain { 88 | Self { 89 | current_path: Default::default(), 90 | done: true, 91 | end_cursor: None, 92 | tree, 93 | store: None, 94 | } 95 | } 96 | } 97 | 98 | impl<'a, B: BTreeTrait> Iterator for Drain<'a, B> { 99 | type Item = B::Elem; 100 | 101 | fn next(&mut self) -> Option { 102 | if self.done { 103 | return None; 104 | } 105 | 106 | // end iteration if pointing to the end leaf 107 | if let Some(end_cursor) = self.end_cursor { 108 | if end_cursor.leaf.0 == self.current_path.last().unwrap().arena.unwrap_leaf() { 109 | return None; 110 | } 111 | } 112 | 113 | let idx = *self.current_path.last().unwrap(); 114 | if !self.tree.next_sibling(&mut self.current_path) { 115 | self.done = true; 116 | } 117 | 118 | // NOTE: we removed the node here, the tree is in an invalid state 119 | let node = self 120 | .tree 121 | .leaf_nodes 122 | .remove(idx.arena.unwrap_leaf()) 123 | .unwrap(); 124 | Some(node.elem) 125 | } 126 | } 127 | 128 | impl<'a, B: BTreeTrait> Drain<'a, B> { 129 | fn ensure_finished(&mut self) { 130 | while self.next().is_some() {} 131 | } 132 | } 133 | 134 | impl<'a, B: BTreeTrait> Drop for Drain<'a, B> { 135 | fn drop(&mut self) { 136 | self.ensure_finished(); 137 | let TempStore { 138 | start_path, 139 | end_path, 140 | leaf_before_drain_range, 141 | leaf_after_drain_range, 142 | } = *self.store.take().unwrap(); 143 | // the deepest internal node level 144 | let mut level = start_path.len() - 2; 145 | let mut deleted = Vec::new(); 146 | 147 | // The deepest internal node level, need to filter deleted children 148 | // to ensure is_empty() has correct result 149 | self.tree.filter_deleted_children(start_path[level].arena); 150 | self.tree.filter_deleted_children(end_path[level].arena); 151 | while start_path[level].arena != end_path[level].arena { 152 | let start_node = self.tree.get_internal(start_path[level].arena); 153 | let end_node = self.tree.get_internal(end_path[level].arena); 154 | let del_start = if start_node.is_empty() { 155 | start_path[level].arr 156 | } else { 157 | start_path[level].arr + 1 158 | }; 159 | let del_end = if end_node.is_empty() { 160 | end_path[level].arr + 1 161 | } else { 162 | end_path[level].arr 163 | }; 164 | 165 | // remove del_start.. in start_node's parent 166 | // remove ..del_end in end_node's parent 167 | let start_arena = start_path[level - 1].arena; 168 | let end_arena = end_path[level - 1].arena; 169 | if start_arena == end_arena { 170 | // parent is the same, delete start..end 171 | let parent = self.tree.get_internal_mut(start_arena); 172 | for x in &parent.children[del_start as usize..del_end as usize] { 173 | deleted.push(x.arena); 174 | } 175 | 176 | delete_range(&mut parent.children, del_start as usize..del_end as usize); 177 | self.tree 178 | .update_children_parent_slot_from(start_arena, del_start as usize); 179 | } else { 180 | // parent is different 181 | { 182 | // delete start.. 183 | let start_parent = self.tree.get_internal_mut(start_arena); 184 | for x in &start_parent.children[del_start as usize..] { 185 | deleted.push(x.arena); 186 | } 187 | delete_range(&mut start_parent.children, del_start as usize..); 188 | } 189 | { 190 | // delete ..end 191 | let end_parent = self.tree.get_internal_mut(end_arena); 192 | for x in &end_parent.children[..del_end as usize] { 193 | deleted.push(x.arena); 194 | } 195 | delete_range(&mut end_parent.children, ..del_end as usize); 196 | self.tree.update_children_parent_slot_from(end_arena, 0); 197 | } 198 | } 199 | 200 | level -= 1 201 | // this loop will abort before overflow, because level=0 is guaranteed to be the same 202 | } 203 | 204 | while level >= 1 { 205 | let (child, parent) = self 206 | .tree 207 | .get2_mut(start_path[level].arena, start_path[level - 1].arena); 208 | if child.is_empty() { 209 | assert_eq!( 210 | parent.children[start_path[level].arr as usize].arena, 211 | start_path[level].arena 212 | ); 213 | deleted.push(parent.children.remove(start_path[level].arr as usize).arena); 214 | self.tree.update_children_parent_slot_from( 215 | start_path[level - 1].arena, 216 | start_path[level].arr as usize, 217 | ); 218 | } else { 219 | break; 220 | } 221 | level -= 1; 222 | } 223 | 224 | // release memory 225 | for x in deleted { 226 | self.tree.purge(x); 227 | } 228 | 229 | if let Some(after) = leaf_after_drain_range { 230 | self.tree.recursive_update_cache( 231 | after, 232 | leaf_after_drain_range == leaf_before_drain_range, 233 | None, 234 | ); 235 | } 236 | 237 | // otherwise the path is invalid (e.g. the tree is empty) 238 | if let Some(before) = leaf_before_drain_range { 239 | if leaf_before_drain_range == leaf_after_drain_range { 240 | self.tree.recursive_update_cache(before, B::USE_DIFF, None); 241 | } else { 242 | self.tree.recursive_update_cache(before, false, None); 243 | if let Some(after) = leaf_after_drain_range { 244 | self.tree.recursive_update_cache(after, false, None); 245 | } 246 | } 247 | seal(self.tree, before); 248 | } else { 249 | self.tree.update_root_cache(); 250 | self.tree.try_reduce_levels(); 251 | } 252 | } 253 | } 254 | 255 | fn seal(tree: &mut BTree, leaf: ArenaIndex) { 256 | handle_lack_on_path_to_leaf(tree, leaf); 257 | if let Some(sibling) = tree.next_same_level_in_node(leaf) { 258 | handle_lack_on_path_to_leaf(tree, sibling); 259 | } 260 | tree.try_reduce_levels(); 261 | } 262 | 263 | fn handle_lack_on_path_to_leaf(tree: &mut BTree, leaf: ArenaIndex) { 264 | let mut last_lack_count = 0; 265 | let mut lack_count; 266 | loop { 267 | lack_count = 0; 268 | let path = tree.get_path(leaf); 269 | for i in 1..path.len() - 1 { 270 | let Some(node) = tree.in_nodes.get(path[i].arena.unwrap_internal()) else { 271 | unreachable!() 272 | }; 273 | let is_lack = node.is_lack(); 274 | if is_lack { 275 | let lack_info = tree.handle_lack_single_layer(path[i].arena); 276 | if lack_info.parent_lack.is_some() { 277 | lack_count += 1; 278 | } 279 | } 280 | } 281 | // parent may be lack after some children is merged 282 | if lack_count == 0 || lack_count == last_lack_count { 283 | break; 284 | } 285 | 286 | last_lack_count = lack_count; 287 | } 288 | } 289 | 290 | impl<'a, B: BTreeTrait> Iter<'a, B> { 291 | pub fn new(tree: &'a BTree, start: NodePath, inclusive_end: NodePath) -> Self { 292 | Self { 293 | tree, 294 | inclusive_end, 295 | path: start, 296 | done: false, 297 | } 298 | } 299 | } 300 | 301 | impl<'a, B: BTreeTrait> Iterator for Iter<'a, B> { 302 | type Item = (NodePath, &'a LeafNode); 303 | 304 | fn next(&mut self) -> Option { 305 | if self.done { 306 | return None; 307 | } 308 | 309 | if self.inclusive_end.last() == self.path.last() { 310 | self.done = true; 311 | } 312 | 313 | let last = *self.path.last().unwrap(); 314 | let path = self.path.clone(); 315 | if !self.tree.next_sibling(&mut self.path) { 316 | self.done = true; 317 | } 318 | 319 | let node = self.tree.leaf_nodes.get(last.arena.unwrap_leaf()).unwrap(); 320 | Some((path, node)) 321 | } 322 | } 323 | -------------------------------------------------------------------------------- /src/generic_impl/ord.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | use std::cmp::Ordering; 3 | use std::ops::Range; 4 | 5 | use crate::rle::{CanRemove, HasLength, Mergeable, Sliceable, TryInsert}; 6 | use crate::{BTree, BTreeTrait, FindResult, Query, SplitInfo}; 7 | 8 | #[derive(Debug)] 9 | #[repr(transparent)] 10 | struct OrdTrait { 11 | _phantom: core::marker::PhantomData<(Key, Value)>, 12 | } 13 | 14 | #[derive(Debug)] 15 | pub struct OrdTreeMap { 16 | tree: BTree>, 17 | len: usize, 18 | } 19 | 20 | #[derive(Debug)] 21 | pub struct OrdTreeSet(OrdTreeMap); 22 | 23 | impl OrdTreeMap { 24 | #[inline(always)] 25 | pub fn new() -> Self { 26 | Self { 27 | tree: BTree::new(), 28 | len: 0, 29 | } 30 | } 31 | 32 | #[inline(always)] 33 | pub fn insert(&mut self, key: Key, value: Value) { 34 | let Some(result) = self.tree.query::>(&key) else { 35 | self.len += 1; 36 | self.tree.push(Unmergeable((key, value))); 37 | return; 38 | }; 39 | 40 | if !result.found { 41 | self.len += 1; 42 | let tree = &mut self.tree; 43 | let data = Unmergeable((key, value)); 44 | let index = result.leaf(); 45 | let leaf = tree.leaf_nodes.get_mut(index.0).unwrap(); 46 | let parent = leaf.parent(); 47 | 48 | let mut is_full = false; 49 | // Try to merge 50 | if result.cursor.offset == 0 && data.can_merge(&leaf.elem) { 51 | leaf.elem.merge_left(&data); 52 | } else if result.cursor.offset == leaf.elem.rle_len() && leaf.elem.can_merge(&data) { 53 | leaf.elem.merge_right(&data); 54 | } else { 55 | // Insert new leaf node 56 | let child = tree.alloc_leaf_child(data, parent.unwrap_internal()); 57 | let SplitInfo { 58 | parent_idx: parent_index, 59 | insert_slot: insert_index, 60 | .. 61 | } = tree.split_leaf_if_needed(result.cursor); 62 | let parent = tree.in_nodes.get_mut(parent_index).unwrap(); 63 | parent.children.insert(insert_index, child).unwrap(); 64 | is_full = parent.is_full(); 65 | } 66 | 67 | tree.recursive_update_cache(parent, false, None); 68 | if is_full { 69 | tree.split(parent); 70 | } 71 | } else { 72 | let leaf = self.tree.get_elem_mut(result.leaf()).unwrap(); 73 | leaf.0 .1 = value; 74 | } 75 | } 76 | 77 | #[inline(always)] 78 | pub fn delete(&mut self, key: &Key) -> Option<(Key, Value)> { 79 | let q = self.tree.query::>(key)?; 80 | match self.tree.remove_leaf(q.cursor) { 81 | Some(v) => { 82 | self.len -= 1; 83 | Some(v.0) 84 | } 85 | None => None, 86 | } 87 | } 88 | 89 | #[inline(always)] 90 | pub fn iter(&self) -> impl Iterator { 91 | self.tree.iter().map(|x| &x.0) 92 | } 93 | 94 | #[inline(always)] 95 | pub fn iter_key(&self) -> impl Iterator { 96 | self.tree.iter().map(|x| &x.0 .0) 97 | } 98 | 99 | #[inline(always)] 100 | pub fn len(&self) -> usize { 101 | self.len 102 | } 103 | 104 | #[inline(always)] 105 | pub fn is_empty(&self) -> bool { 106 | self.len == 0 107 | } 108 | 109 | #[allow(unused)] 110 | pub(crate) fn check(&self) { 111 | self.tree.check() 112 | } 113 | } 114 | 115 | impl OrdTreeSet { 116 | #[inline(always)] 117 | pub fn new() -> Self { 118 | Self(OrdTreeMap::new()) 119 | } 120 | 121 | #[inline(always)] 122 | pub fn insert(&mut self, key: Key) { 123 | self.0.insert(key, ()); 124 | } 125 | 126 | #[inline(always)] 127 | pub fn delete(&mut self, key: &Key) -> bool { 128 | self.0.delete(key).is_some() 129 | } 130 | 131 | #[inline(always)] 132 | pub fn iter(&self) -> impl Iterator { 133 | self.0.iter_key() 134 | } 135 | 136 | pub fn len(&self) -> usize { 137 | self.0.len 138 | } 139 | 140 | pub fn is_empty(&self) -> bool { 141 | self.0.len == 0 142 | } 143 | 144 | #[allow(unused)] 145 | fn check(&self) { 146 | self.0.check() 147 | } 148 | } 149 | 150 | impl Default for OrdTreeSet { 151 | #[inline(always)] 152 | fn default() -> Self { 153 | Self::new() 154 | } 155 | } 156 | 157 | impl Default 158 | for OrdTreeMap 159 | { 160 | #[inline(always)] 161 | fn default() -> Self { 162 | Self::new() 163 | } 164 | } 165 | 166 | impl Default for OrdTrait { 167 | #[inline(always)] 168 | fn default() -> Self { 169 | Self { 170 | _phantom: Default::default(), 171 | } 172 | } 173 | } 174 | 175 | #[repr(transparent)] 176 | #[derive(Debug, Clone)] 177 | pub struct Unmergeable(T); 178 | 179 | impl HasLength for Unmergeable { 180 | fn rle_len(&self) -> usize { 181 | 1 182 | } 183 | } 184 | 185 | impl Sliceable for Unmergeable { 186 | fn _slice(&self, range: Range) -> Self { 187 | if range.end - range.start != 1 { 188 | panic!("Invalid range"); 189 | } 190 | 191 | self.clone() 192 | } 193 | } 194 | 195 | impl Mergeable for Unmergeable { 196 | fn can_merge(&self, _rhs: &Self) -> bool { 197 | false 198 | } 199 | 200 | fn merge_right(&mut self, _rhs: &Self) { 201 | unreachable!() 202 | } 203 | 204 | fn merge_left(&mut self, _left: &Self) { 205 | unreachable!() 206 | } 207 | } 208 | 209 | impl TryInsert for Unmergeable { 210 | fn try_insert(&mut self, _pos: usize, elem: Self) -> Result<(), Self> { 211 | Err(elem) 212 | } 213 | } 214 | 215 | impl CanRemove for Unmergeable { 216 | fn can_remove(&self) -> bool { 217 | false 218 | } 219 | } 220 | 221 | impl BTreeTrait for OrdTrait { 222 | type Elem = Unmergeable<(Key, Value)>; 223 | type Cache = Option<(Key, Key)>; 224 | type CacheDiff = (); 225 | const USE_DIFF: bool = false; 226 | 227 | #[inline(always)] 228 | fn calc_cache_internal(cache: &mut Self::Cache, caches: &[crate::Child]) { 229 | if caches.is_empty() { 230 | return; 231 | } 232 | 233 | *cache = Some(( 234 | caches[0].cache.as_ref().unwrap().0.clone(), 235 | caches[caches.len() - 1].cache.as_ref().unwrap().1.clone(), 236 | )); 237 | } 238 | 239 | #[inline(always)] 240 | fn apply_cache_diff(_: &mut Self::Cache, _: &Self::CacheDiff) { 241 | unreachable!() 242 | } 243 | 244 | #[inline(always)] 245 | fn merge_cache_diff(_: &mut Self::CacheDiff, _: &Self::CacheDiff) {} 246 | 247 | #[inline(always)] 248 | fn get_elem_cache(elem: &Self::Elem) -> Self::Cache { 249 | Some((elem.0 .0.clone(), elem.0 .0.clone())) 250 | } 251 | 252 | #[inline(always)] 253 | fn new_cache_to_diff(_: &Self::Cache) -> Self::CacheDiff {} 254 | 255 | fn sub_cache(_: &Self::Cache, _: &Self::Cache) -> Self::CacheDiff {} 256 | } 257 | 258 | impl Query> 259 | for OrdTrait 260 | { 261 | type QueryArg = Key; 262 | 263 | #[inline(always)] 264 | fn init(_target: &Self::QueryArg) -> Self { 265 | Self::default() 266 | } 267 | 268 | #[inline] 269 | fn find_node( 270 | &mut self, 271 | target: &Self::QueryArg, 272 | child_caches: &[crate::Child>], 273 | ) -> crate::FindResult { 274 | let result = child_caches.binary_search_by(|x| { 275 | let (min, max) = x.cache.as_ref().unwrap(); 276 | if target < min { 277 | core::cmp::Ordering::Greater 278 | } else if target > max { 279 | core::cmp::Ordering::Less 280 | } else { 281 | core::cmp::Ordering::Equal 282 | } 283 | }); 284 | match result { 285 | Ok(i) => FindResult::new_found(i, 0), 286 | Err(i) => FindResult::new_missing( 287 | i.min(child_caches.len() - 1), 288 | if i == child_caches.len() { 1 } else { 0 }, 289 | ), 290 | } 291 | } 292 | 293 | #[inline(always)] 294 | fn confirm_elem( 295 | &mut self, 296 | q: &Self::QueryArg, 297 | elem: & as BTreeTrait>::Elem, 298 | ) -> (usize, bool) { 299 | match q.cmp(&elem.0 .0) { 300 | Ordering::Less => (0, false), 301 | Ordering::Equal => (0, true), 302 | Ordering::Greater => (1, false), 303 | } 304 | } 305 | } 306 | 307 | #[cfg(test)] 308 | mod test { 309 | use std::cmp::Ordering; 310 | 311 | use rand::{Rng, SeedableRng}; 312 | 313 | use crate::HeapVec; 314 | 315 | use super::*; 316 | 317 | #[test] 318 | fn test() { 319 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 320 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 321 | let mut data: HeapVec = (0..1000).map(|_| rng.gen()).collect(); 322 | for &value in data.iter() { 323 | tree.insert(value); 324 | } 325 | data.sort_unstable(); 326 | assert_eq!(tree.iter().copied().collect::>(), data); 327 | tree.check(); 328 | } 329 | 330 | #[test] 331 | fn test_delete() { 332 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 333 | tree.insert(12); 334 | tree.delete(&12); 335 | assert_eq!(tree.len(), 0); 336 | } 337 | 338 | #[test] 339 | fn test_compare_pos() { 340 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 341 | for i in 0..100 { 342 | tree.insert(i); 343 | } 344 | 345 | for i in 0..99 { 346 | let a = tree.0.tree.query::>(&i).unwrap(); 347 | assert_eq!( 348 | tree.0.tree.compare_pos(a.cursor(), a.cursor()), 349 | Ordering::Equal 350 | ); 351 | for j in i + 1..100 { 352 | let b = tree.0.tree.query::>(&j).unwrap(); 353 | assert_eq!( 354 | tree.0.tree.compare_pos(a.cursor(), b.cursor()), 355 | Ordering::Less 356 | ); 357 | assert_eq!( 358 | tree.0.tree.compare_pos(b.cursor(), a.cursor()), 359 | Ordering::Greater 360 | ); 361 | } 362 | } 363 | } 364 | 365 | mod move_event_test { 366 | 367 | use super::*; 368 | 369 | #[test] 370 | fn test() { 371 | let mut tree: OrdTreeMap = OrdTreeMap::new(); 372 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 373 | let mut data: HeapVec = (0..1000).map(|_| rng.gen()).collect(); 374 | for &value in data.iter() { 375 | tree.insert(value, 0); 376 | } 377 | for value in data.drain(0..100) { 378 | tree.delete(&value); 379 | } 380 | for value in data.drain(0..800) { 381 | tree.delete(&value); 382 | } 383 | tree.tree.check(); 384 | for _ in (0..100).rev() { 385 | tree.delete(&data.pop().unwrap()); 386 | } 387 | } 388 | } 389 | 390 | #[test] 391 | #[ignore] 392 | fn depth_test() { 393 | let mut tree: OrdTreeSet = OrdTreeSet::new(); 394 | for i in 0..2_100_000 { 395 | tree.insert(i as u64); 396 | let m = (!i) + 1; 397 | if (i & m) == i { 398 | eprintln!( 399 | "i={}, Depth={}, Avg Children={}", 400 | i, 401 | tree.0.tree.depth(), 402 | tree.0.tree.internal_avg_children_num() 403 | ); 404 | } 405 | } 406 | tree.check(); 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.12" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" 25 | dependencies = [ 26 | "cfg-if", 27 | "getrandom 0.3.3", 28 | "once_cell", 29 | "version_check", 30 | "zerocopy", 31 | ] 32 | 33 | [[package]] 34 | name = "aho-corasick" 35 | version = "1.1.3" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 38 | dependencies = [ 39 | "memchr", 40 | ] 41 | 42 | [[package]] 43 | name = "aligned-vec" 44 | version = "0.6.4" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" 47 | dependencies = [ 48 | "equator", 49 | ] 50 | 51 | [[package]] 52 | name = "anes" 53 | version = "0.1.6" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 56 | 57 | [[package]] 58 | name = "anstyle" 59 | version = "1.0.11" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 62 | 63 | [[package]] 64 | name = "arbitrary" 65 | version = "1.4.2" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" 68 | dependencies = [ 69 | "derive_arbitrary", 70 | ] 71 | 72 | [[package]] 73 | name = "arrayvec" 74 | version = "0.7.6" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 77 | 78 | [[package]] 79 | name = "arref" 80 | version = "0.1.0" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "2ccd462b64c3c72f1be8305905a85d85403d768e8690c9b8bd3b9009a5761679" 83 | 84 | [[package]] 85 | name = "autocfg" 86 | version = "1.5.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 89 | 90 | [[package]] 91 | name = "backtrace" 92 | version = "0.3.75" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 95 | dependencies = [ 96 | "addr2line", 97 | "cfg-if", 98 | "libc", 99 | "miniz_oxide", 100 | "object", 101 | "rustc-demangle", 102 | "windows-targets 0.52.6", 103 | ] 104 | 105 | [[package]] 106 | name = "bitflags" 107 | version = "1.3.2" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 110 | 111 | [[package]] 112 | name = "bitflags" 113 | version = "2.9.4" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 116 | 117 | [[package]] 118 | name = "bumpalo" 119 | version = "3.19.0" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 122 | 123 | [[package]] 124 | name = "bytemuck" 125 | version = "1.23.2" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" 128 | 129 | [[package]] 130 | name = "byteorder" 131 | version = "1.5.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 134 | 135 | [[package]] 136 | name = "cast" 137 | version = "0.3.0" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 140 | 141 | [[package]] 142 | name = "cc" 143 | version = "1.2.36" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" 146 | dependencies = [ 147 | "find-msvc-tools", 148 | "shlex", 149 | ] 150 | 151 | [[package]] 152 | name = "cfg-if" 153 | version = "1.0.3" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" 156 | 157 | [[package]] 158 | name = "ciborium" 159 | version = "0.2.2" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 162 | dependencies = [ 163 | "ciborium-io", 164 | "ciborium-ll", 165 | "serde", 166 | ] 167 | 168 | [[package]] 169 | name = "ciborium-io" 170 | version = "0.2.2" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 173 | 174 | [[package]] 175 | name = "ciborium-ll" 176 | version = "0.2.2" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 179 | dependencies = [ 180 | "ciborium-io", 181 | "half", 182 | ] 183 | 184 | [[package]] 185 | name = "clap" 186 | version = "4.5.47" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" 189 | dependencies = [ 190 | "clap_builder", 191 | ] 192 | 193 | [[package]] 194 | name = "clap_builder" 195 | version = "4.5.47" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" 198 | dependencies = [ 199 | "anstyle", 200 | "clap_lex", 201 | ] 202 | 203 | [[package]] 204 | name = "clap_lex" 205 | version = "0.7.5" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 208 | 209 | [[package]] 210 | name = "color-backtrace" 211 | version = "0.7.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "e49b1973af2a47b5b44f7dd0a344598da95c872e1556b045607888784e973b91" 214 | dependencies = [ 215 | "backtrace", 216 | "termcolor", 217 | ] 218 | 219 | [[package]] 220 | name = "cpp_demangle" 221 | version = "0.4.4" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" 224 | dependencies = [ 225 | "cfg-if", 226 | ] 227 | 228 | [[package]] 229 | name = "crc32fast" 230 | version = "1.5.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" 233 | dependencies = [ 234 | "cfg-if", 235 | ] 236 | 237 | [[package]] 238 | name = "criterion" 239 | version = "0.5.1" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" 242 | dependencies = [ 243 | "anes", 244 | "cast", 245 | "ciborium", 246 | "clap", 247 | "criterion-plot 0.5.0", 248 | "is-terminal", 249 | "itertools 0.10.5", 250 | "num-traits", 251 | "once_cell", 252 | "oorandom", 253 | "plotters", 254 | "rayon", 255 | "regex", 256 | "serde", 257 | "serde_derive", 258 | "serde_json", 259 | "tinytemplate", 260 | "walkdir", 261 | ] 262 | 263 | [[package]] 264 | name = "criterion" 265 | version = "0.7.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" 268 | dependencies = [ 269 | "anes", 270 | "cast", 271 | "ciborium", 272 | "clap", 273 | "criterion-plot 0.6.0", 274 | "itertools 0.13.0", 275 | "num-traits", 276 | "oorandom", 277 | "plotters", 278 | "rayon", 279 | "regex", 280 | "serde", 281 | "serde_json", 282 | "tinytemplate", 283 | "walkdir", 284 | ] 285 | 286 | [[package]] 287 | name = "criterion-plot" 288 | version = "0.5.0" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" 291 | dependencies = [ 292 | "cast", 293 | "itertools 0.10.5", 294 | ] 295 | 296 | [[package]] 297 | name = "criterion-plot" 298 | version = "0.6.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" 301 | dependencies = [ 302 | "cast", 303 | "itertools 0.13.0", 304 | ] 305 | 306 | [[package]] 307 | name = "crossbeam-deque" 308 | version = "0.8.6" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 311 | dependencies = [ 312 | "crossbeam-epoch", 313 | "crossbeam-utils", 314 | ] 315 | 316 | [[package]] 317 | name = "crossbeam-epoch" 318 | version = "0.9.18" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 321 | dependencies = [ 322 | "crossbeam-utils", 323 | ] 324 | 325 | [[package]] 326 | name = "crossbeam-utils" 327 | version = "0.8.21" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 330 | 331 | [[package]] 332 | name = "crunchy" 333 | version = "0.2.4" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 336 | 337 | [[package]] 338 | name = "ctor" 339 | version = "0.1.26" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" 342 | dependencies = [ 343 | "quote", 344 | "syn 1.0.109", 345 | ] 346 | 347 | [[package]] 348 | name = "debugid" 349 | version = "0.8.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" 352 | dependencies = [ 353 | "uuid", 354 | ] 355 | 356 | [[package]] 357 | name = "derive_arbitrary" 358 | version = "1.4.2" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" 361 | dependencies = [ 362 | "proc-macro2", 363 | "quote", 364 | "syn 2.0.106", 365 | ] 366 | 367 | [[package]] 368 | name = "either" 369 | version = "1.15.0" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 372 | 373 | [[package]] 374 | name = "equator" 375 | version = "0.4.2" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" 378 | dependencies = [ 379 | "equator-macro", 380 | ] 381 | 382 | [[package]] 383 | name = "equator-macro" 384 | version = "0.4.2" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" 387 | dependencies = [ 388 | "proc-macro2", 389 | "quote", 390 | "syn 2.0.106", 391 | ] 392 | 393 | [[package]] 394 | name = "equivalent" 395 | version = "1.0.2" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 398 | 399 | [[package]] 400 | name = "errno" 401 | version = "0.3.13" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" 404 | dependencies = [ 405 | "libc", 406 | "windows-sys 0.60.2", 407 | ] 408 | 409 | [[package]] 410 | name = "fastrand" 411 | version = "2.3.0" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 414 | 415 | [[package]] 416 | name = "find-msvc-tools" 417 | version = "0.1.1" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" 420 | 421 | [[package]] 422 | name = "findshlibs" 423 | version = "0.10.2" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" 426 | dependencies = [ 427 | "cc", 428 | "lazy_static", 429 | "libc", 430 | "winapi", 431 | ] 432 | 433 | [[package]] 434 | name = "flate2" 435 | version = "1.1.2" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" 438 | dependencies = [ 439 | "crc32fast", 440 | "miniz_oxide", 441 | ] 442 | 443 | [[package]] 444 | name = "generic-btree" 445 | version = "0.10.6" 446 | dependencies = [ 447 | "ahash", 448 | "arbitrary", 449 | "arref", 450 | "color-backtrace", 451 | "criterion 0.7.0", 452 | "ctor", 453 | "flate2", 454 | "heapless", 455 | "itertools 0.11.0", 456 | "jumprope", 457 | "loro-thunderdome", 458 | "pprof", 459 | "proc-macro2", 460 | "rand", 461 | "rustc-hash", 462 | "serde_json", 463 | ] 464 | 465 | [[package]] 466 | name = "getrandom" 467 | version = "0.2.16" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 470 | dependencies = [ 471 | "cfg-if", 472 | "libc", 473 | "wasi 0.11.1+wasi-snapshot-preview1", 474 | ] 475 | 476 | [[package]] 477 | name = "getrandom" 478 | version = "0.3.3" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 481 | dependencies = [ 482 | "cfg-if", 483 | "libc", 484 | "r-efi", 485 | "wasi 0.14.4+wasi-0.2.4", 486 | ] 487 | 488 | [[package]] 489 | name = "gimli" 490 | version = "0.31.1" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 493 | 494 | [[package]] 495 | name = "half" 496 | version = "2.6.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 499 | dependencies = [ 500 | "cfg-if", 501 | "crunchy", 502 | ] 503 | 504 | [[package]] 505 | name = "hash32" 506 | version = "0.3.1" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" 509 | dependencies = [ 510 | "byteorder", 511 | ] 512 | 513 | [[package]] 514 | name = "hashbrown" 515 | version = "0.15.5" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 518 | 519 | [[package]] 520 | name = "heapless" 521 | version = "0.9.1" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5" 524 | dependencies = [ 525 | "hash32", 526 | "stable_deref_trait", 527 | ] 528 | 529 | [[package]] 530 | name = "hermit-abi" 531 | version = "0.5.2" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" 534 | 535 | [[package]] 536 | name = "indexmap" 537 | version = "2.11.0" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" 540 | dependencies = [ 541 | "equivalent", 542 | "hashbrown", 543 | ] 544 | 545 | [[package]] 546 | name = "inferno" 547 | version = "0.11.21" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" 550 | dependencies = [ 551 | "ahash", 552 | "indexmap", 553 | "is-terminal", 554 | "itoa", 555 | "log", 556 | "num-format", 557 | "once_cell", 558 | "quick-xml", 559 | "rgb", 560 | "str_stack", 561 | ] 562 | 563 | [[package]] 564 | name = "is-terminal" 565 | version = "0.4.16" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" 568 | dependencies = [ 569 | "hermit-abi", 570 | "libc", 571 | "windows-sys 0.59.0", 572 | ] 573 | 574 | [[package]] 575 | name = "itertools" 576 | version = "0.10.5" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 579 | dependencies = [ 580 | "either", 581 | ] 582 | 583 | [[package]] 584 | name = "itertools" 585 | version = "0.11.0" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 588 | dependencies = [ 589 | "either", 590 | ] 591 | 592 | [[package]] 593 | name = "itertools" 594 | version = "0.13.0" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 597 | dependencies = [ 598 | "either", 599 | ] 600 | 601 | [[package]] 602 | name = "itoa" 603 | version = "1.0.15" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 606 | 607 | [[package]] 608 | name = "js-sys" 609 | version = "0.3.78" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" 612 | dependencies = [ 613 | "once_cell", 614 | "wasm-bindgen", 615 | ] 616 | 617 | [[package]] 618 | name = "jumprope" 619 | version = "1.1.2" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "829c74fe88dda0d2a5425b022b44921574a65c4eb78e6e39a61b40eb416a4ef8" 622 | dependencies = [ 623 | "rand", 624 | "str_indices", 625 | ] 626 | 627 | [[package]] 628 | name = "lazy_static" 629 | version = "1.5.0" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 632 | 633 | [[package]] 634 | name = "libc" 635 | version = "0.2.175" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" 638 | 639 | [[package]] 640 | name = "linux-raw-sys" 641 | version = "0.9.4" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" 644 | 645 | [[package]] 646 | name = "lock_api" 647 | version = "0.4.13" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 650 | dependencies = [ 651 | "autocfg", 652 | "scopeguard", 653 | ] 654 | 655 | [[package]] 656 | name = "log" 657 | version = "0.4.28" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 660 | 661 | [[package]] 662 | name = "loro-thunderdome" 663 | version = "0.6.2" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" 666 | 667 | [[package]] 668 | name = "memchr" 669 | version = "2.7.5" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 672 | 673 | [[package]] 674 | name = "memmap2" 675 | version = "0.9.8" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" 678 | dependencies = [ 679 | "libc", 680 | ] 681 | 682 | [[package]] 683 | name = "miniz_oxide" 684 | version = "0.8.9" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 687 | dependencies = [ 688 | "adler2", 689 | ] 690 | 691 | [[package]] 692 | name = "nix" 693 | version = "0.26.4" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" 696 | dependencies = [ 697 | "bitflags 1.3.2", 698 | "cfg-if", 699 | "libc", 700 | ] 701 | 702 | [[package]] 703 | name = "num-format" 704 | version = "0.4.4" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" 707 | dependencies = [ 708 | "arrayvec", 709 | "itoa", 710 | ] 711 | 712 | [[package]] 713 | name = "num-traits" 714 | version = "0.2.19" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 717 | dependencies = [ 718 | "autocfg", 719 | ] 720 | 721 | [[package]] 722 | name = "object" 723 | version = "0.36.7" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 726 | dependencies = [ 727 | "memchr", 728 | ] 729 | 730 | [[package]] 731 | name = "once_cell" 732 | version = "1.21.3" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 735 | 736 | [[package]] 737 | name = "oorandom" 738 | version = "11.1.5" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" 741 | 742 | [[package]] 743 | name = "plotters" 744 | version = "0.3.7" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" 747 | dependencies = [ 748 | "num-traits", 749 | "plotters-backend", 750 | "plotters-svg", 751 | "wasm-bindgen", 752 | "web-sys", 753 | ] 754 | 755 | [[package]] 756 | name = "plotters-backend" 757 | version = "0.3.7" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" 760 | 761 | [[package]] 762 | name = "plotters-svg" 763 | version = "0.3.7" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" 766 | dependencies = [ 767 | "plotters-backend", 768 | ] 769 | 770 | [[package]] 771 | name = "pprof" 772 | version = "0.15.0" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187" 775 | dependencies = [ 776 | "aligned-vec", 777 | "backtrace", 778 | "cfg-if", 779 | "criterion 0.5.1", 780 | "findshlibs", 781 | "inferno", 782 | "libc", 783 | "log", 784 | "nix", 785 | "once_cell", 786 | "smallvec", 787 | "spin", 788 | "symbolic-demangle", 789 | "tempfile", 790 | "thiserror", 791 | ] 792 | 793 | [[package]] 794 | name = "ppv-lite86" 795 | version = "0.2.21" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 798 | dependencies = [ 799 | "zerocopy", 800 | ] 801 | 802 | [[package]] 803 | name = "proc-macro2" 804 | version = "1.0.101" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 807 | dependencies = [ 808 | "unicode-ident", 809 | ] 810 | 811 | [[package]] 812 | name = "quick-xml" 813 | version = "0.26.0" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" 816 | dependencies = [ 817 | "memchr", 818 | ] 819 | 820 | [[package]] 821 | name = "quote" 822 | version = "1.0.40" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 825 | dependencies = [ 826 | "proc-macro2", 827 | ] 828 | 829 | [[package]] 830 | name = "r-efi" 831 | version = "5.3.0" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 834 | 835 | [[package]] 836 | name = "rand" 837 | version = "0.8.5" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 840 | dependencies = [ 841 | "libc", 842 | "rand_chacha", 843 | "rand_core", 844 | ] 845 | 846 | [[package]] 847 | name = "rand_chacha" 848 | version = "0.3.1" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 851 | dependencies = [ 852 | "ppv-lite86", 853 | "rand_core", 854 | ] 855 | 856 | [[package]] 857 | name = "rand_core" 858 | version = "0.6.4" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 861 | dependencies = [ 862 | "getrandom 0.2.16", 863 | ] 864 | 865 | [[package]] 866 | name = "rayon" 867 | version = "1.11.0" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" 870 | dependencies = [ 871 | "either", 872 | "rayon-core", 873 | ] 874 | 875 | [[package]] 876 | name = "rayon-core" 877 | version = "1.13.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" 880 | dependencies = [ 881 | "crossbeam-deque", 882 | "crossbeam-utils", 883 | ] 884 | 885 | [[package]] 886 | name = "regex" 887 | version = "1.11.2" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" 890 | dependencies = [ 891 | "aho-corasick", 892 | "memchr", 893 | "regex-automata", 894 | "regex-syntax", 895 | ] 896 | 897 | [[package]] 898 | name = "regex-automata" 899 | version = "0.4.10" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" 902 | dependencies = [ 903 | "aho-corasick", 904 | "memchr", 905 | "regex-syntax", 906 | ] 907 | 908 | [[package]] 909 | name = "regex-syntax" 910 | version = "0.8.6" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" 913 | 914 | [[package]] 915 | name = "rgb" 916 | version = "0.8.52" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" 919 | dependencies = [ 920 | "bytemuck", 921 | ] 922 | 923 | [[package]] 924 | name = "rustc-demangle" 925 | version = "0.1.26" 926 | source = "registry+https://github.com/rust-lang/crates.io-index" 927 | checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" 928 | 929 | [[package]] 930 | name = "rustc-hash" 931 | version = "2.1.1" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 934 | 935 | [[package]] 936 | name = "rustix" 937 | version = "1.0.8" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" 940 | dependencies = [ 941 | "bitflags 2.9.4", 942 | "errno", 943 | "libc", 944 | "linux-raw-sys", 945 | "windows-sys 0.60.2", 946 | ] 947 | 948 | [[package]] 949 | name = "rustversion" 950 | version = "1.0.22" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 953 | 954 | [[package]] 955 | name = "ryu" 956 | version = "1.0.20" 957 | source = "registry+https://github.com/rust-lang/crates.io-index" 958 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 959 | 960 | [[package]] 961 | name = "same-file" 962 | version = "1.0.6" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 965 | dependencies = [ 966 | "winapi-util", 967 | ] 968 | 969 | [[package]] 970 | name = "scopeguard" 971 | version = "1.2.0" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 974 | 975 | [[package]] 976 | name = "serde" 977 | version = "1.0.219" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 980 | dependencies = [ 981 | "serde_derive", 982 | ] 983 | 984 | [[package]] 985 | name = "serde_derive" 986 | version = "1.0.219" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 989 | dependencies = [ 990 | "proc-macro2", 991 | "quote", 992 | "syn 2.0.106", 993 | ] 994 | 995 | [[package]] 996 | name = "serde_json" 997 | version = "1.0.143" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" 1000 | dependencies = [ 1001 | "itoa", 1002 | "memchr", 1003 | "ryu", 1004 | "serde", 1005 | ] 1006 | 1007 | [[package]] 1008 | name = "shlex" 1009 | version = "1.3.0" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1012 | 1013 | [[package]] 1014 | name = "smallvec" 1015 | version = "1.15.1" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 1018 | 1019 | [[package]] 1020 | name = "spin" 1021 | version = "0.10.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" 1024 | dependencies = [ 1025 | "lock_api", 1026 | ] 1027 | 1028 | [[package]] 1029 | name = "stable_deref_trait" 1030 | version = "1.2.0" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1033 | 1034 | [[package]] 1035 | name = "str_indices" 1036 | version = "0.4.4" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" 1039 | 1040 | [[package]] 1041 | name = "str_stack" 1042 | version = "0.1.0" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" 1045 | 1046 | [[package]] 1047 | name = "symbolic-common" 1048 | version = "12.16.2" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "9da12f8fecbbeaa1ee62c1d50dc656407e007c3ee7b2a41afce4b5089eaef15e" 1051 | dependencies = [ 1052 | "debugid", 1053 | "memmap2", 1054 | "stable_deref_trait", 1055 | "uuid", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "symbolic-demangle" 1060 | version = "12.16.2" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "6fd35afe0ef9d35d3dcd41c67ddf882fc832a387221338153b7cd685a105495c" 1063 | dependencies = [ 1064 | "cpp_demangle", 1065 | "rustc-demangle", 1066 | "symbolic-common", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "syn" 1071 | version = "1.0.109" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1074 | dependencies = [ 1075 | "proc-macro2", 1076 | "quote", 1077 | "unicode-ident", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "syn" 1082 | version = "2.0.106" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 1085 | dependencies = [ 1086 | "proc-macro2", 1087 | "quote", 1088 | "unicode-ident", 1089 | ] 1090 | 1091 | [[package]] 1092 | name = "tempfile" 1093 | version = "3.21.0" 1094 | source = "registry+https://github.com/rust-lang/crates.io-index" 1095 | checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" 1096 | dependencies = [ 1097 | "fastrand", 1098 | "getrandom 0.3.3", 1099 | "once_cell", 1100 | "rustix", 1101 | "windows-sys 0.60.2", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "termcolor" 1106 | version = "1.4.1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 1109 | dependencies = [ 1110 | "winapi-util", 1111 | ] 1112 | 1113 | [[package]] 1114 | name = "thiserror" 1115 | version = "2.0.16" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" 1118 | dependencies = [ 1119 | "thiserror-impl", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "thiserror-impl" 1124 | version = "2.0.16" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" 1127 | dependencies = [ 1128 | "proc-macro2", 1129 | "quote", 1130 | "syn 2.0.106", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "tinytemplate" 1135 | version = "1.2.1" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 1138 | dependencies = [ 1139 | "serde", 1140 | "serde_json", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "unicode-ident" 1145 | version = "1.0.18" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1148 | 1149 | [[package]] 1150 | name = "uuid" 1151 | version = "1.18.1" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" 1154 | dependencies = [ 1155 | "js-sys", 1156 | "wasm-bindgen", 1157 | ] 1158 | 1159 | [[package]] 1160 | name = "version_check" 1161 | version = "0.9.5" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1164 | 1165 | [[package]] 1166 | name = "walkdir" 1167 | version = "2.5.0" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1170 | dependencies = [ 1171 | "same-file", 1172 | "winapi-util", 1173 | ] 1174 | 1175 | [[package]] 1176 | name = "wasi" 1177 | version = "0.11.1+wasi-snapshot-preview1" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 1180 | 1181 | [[package]] 1182 | name = "wasi" 1183 | version = "0.14.4+wasi-0.2.4" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" 1186 | dependencies = [ 1187 | "wit-bindgen", 1188 | ] 1189 | 1190 | [[package]] 1191 | name = "wasm-bindgen" 1192 | version = "0.2.101" 1193 | source = "registry+https://github.com/rust-lang/crates.io-index" 1194 | checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" 1195 | dependencies = [ 1196 | "cfg-if", 1197 | "once_cell", 1198 | "rustversion", 1199 | "wasm-bindgen-macro", 1200 | "wasm-bindgen-shared", 1201 | ] 1202 | 1203 | [[package]] 1204 | name = "wasm-bindgen-backend" 1205 | version = "0.2.101" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" 1208 | dependencies = [ 1209 | "bumpalo", 1210 | "log", 1211 | "proc-macro2", 1212 | "quote", 1213 | "syn 2.0.106", 1214 | "wasm-bindgen-shared", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "wasm-bindgen-macro" 1219 | version = "0.2.101" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" 1222 | dependencies = [ 1223 | "quote", 1224 | "wasm-bindgen-macro-support", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "wasm-bindgen-macro-support" 1229 | version = "0.2.101" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" 1232 | dependencies = [ 1233 | "proc-macro2", 1234 | "quote", 1235 | "syn 2.0.106", 1236 | "wasm-bindgen-backend", 1237 | "wasm-bindgen-shared", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "wasm-bindgen-shared" 1242 | version = "0.2.101" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" 1245 | dependencies = [ 1246 | "unicode-ident", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "web-sys" 1251 | version = "0.3.78" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" 1254 | dependencies = [ 1255 | "js-sys", 1256 | "wasm-bindgen", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "winapi" 1261 | version = "0.3.9" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1264 | dependencies = [ 1265 | "winapi-i686-pc-windows-gnu", 1266 | "winapi-x86_64-pc-windows-gnu", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "winapi-i686-pc-windows-gnu" 1271 | version = "0.4.0" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1274 | 1275 | [[package]] 1276 | name = "winapi-util" 1277 | version = "0.1.10" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" 1280 | dependencies = [ 1281 | "windows-sys 0.60.2", 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "winapi-x86_64-pc-windows-gnu" 1286 | version = "0.4.0" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1289 | 1290 | [[package]] 1291 | name = "windows-link" 1292 | version = "0.1.3" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 1295 | 1296 | [[package]] 1297 | name = "windows-sys" 1298 | version = "0.59.0" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1301 | dependencies = [ 1302 | "windows-targets 0.52.6", 1303 | ] 1304 | 1305 | [[package]] 1306 | name = "windows-sys" 1307 | version = "0.60.2" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 1310 | dependencies = [ 1311 | "windows-targets 0.53.3", 1312 | ] 1313 | 1314 | [[package]] 1315 | name = "windows-targets" 1316 | version = "0.52.6" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1319 | dependencies = [ 1320 | "windows_aarch64_gnullvm 0.52.6", 1321 | "windows_aarch64_msvc 0.52.6", 1322 | "windows_i686_gnu 0.52.6", 1323 | "windows_i686_gnullvm 0.52.6", 1324 | "windows_i686_msvc 0.52.6", 1325 | "windows_x86_64_gnu 0.52.6", 1326 | "windows_x86_64_gnullvm 0.52.6", 1327 | "windows_x86_64_msvc 0.52.6", 1328 | ] 1329 | 1330 | [[package]] 1331 | name = "windows-targets" 1332 | version = "0.53.3" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" 1335 | dependencies = [ 1336 | "windows-link", 1337 | "windows_aarch64_gnullvm 0.53.0", 1338 | "windows_aarch64_msvc 0.53.0", 1339 | "windows_i686_gnu 0.53.0", 1340 | "windows_i686_gnullvm 0.53.0", 1341 | "windows_i686_msvc 0.53.0", 1342 | "windows_x86_64_gnu 0.53.0", 1343 | "windows_x86_64_gnullvm 0.53.0", 1344 | "windows_x86_64_msvc 0.53.0", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "windows_aarch64_gnullvm" 1349 | version = "0.52.6" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1352 | 1353 | [[package]] 1354 | name = "windows_aarch64_gnullvm" 1355 | version = "0.53.0" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 1358 | 1359 | [[package]] 1360 | name = "windows_aarch64_msvc" 1361 | version = "0.52.6" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1364 | 1365 | [[package]] 1366 | name = "windows_aarch64_msvc" 1367 | version = "0.53.0" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 1370 | 1371 | [[package]] 1372 | name = "windows_i686_gnu" 1373 | version = "0.52.6" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1376 | 1377 | [[package]] 1378 | name = "windows_i686_gnu" 1379 | version = "0.53.0" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 1382 | 1383 | [[package]] 1384 | name = "windows_i686_gnullvm" 1385 | version = "0.52.6" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1388 | 1389 | [[package]] 1390 | name = "windows_i686_gnullvm" 1391 | version = "0.53.0" 1392 | source = "registry+https://github.com/rust-lang/crates.io-index" 1393 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 1394 | 1395 | [[package]] 1396 | name = "windows_i686_msvc" 1397 | version = "0.52.6" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1400 | 1401 | [[package]] 1402 | name = "windows_i686_msvc" 1403 | version = "0.53.0" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 1406 | 1407 | [[package]] 1408 | name = "windows_x86_64_gnu" 1409 | version = "0.52.6" 1410 | source = "registry+https://github.com/rust-lang/crates.io-index" 1411 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1412 | 1413 | [[package]] 1414 | name = "windows_x86_64_gnu" 1415 | version = "0.53.0" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 1418 | 1419 | [[package]] 1420 | name = "windows_x86_64_gnullvm" 1421 | version = "0.52.6" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1424 | 1425 | [[package]] 1426 | name = "windows_x86_64_gnullvm" 1427 | version = "0.53.0" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 1430 | 1431 | [[package]] 1432 | name = "windows_x86_64_msvc" 1433 | version = "0.52.6" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1436 | 1437 | [[package]] 1438 | name = "windows_x86_64_msvc" 1439 | version = "0.53.0" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 1442 | 1443 | [[package]] 1444 | name = "wit-bindgen" 1445 | version = "0.45.1" 1446 | source = "registry+https://github.com/rust-lang/crates.io-index" 1447 | checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" 1448 | 1449 | [[package]] 1450 | name = "zerocopy" 1451 | version = "0.8.27" 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" 1453 | checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" 1454 | dependencies = [ 1455 | "zerocopy-derive", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "zerocopy-derive" 1460 | version = "0.8.27" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" 1463 | dependencies = [ 1464 | "proc-macro2", 1465 | "quote", 1466 | "syn 2.0.106", 1467 | ] 1468 | -------------------------------------------------------------------------------- /src/generic_impl/rope.rs: -------------------------------------------------------------------------------- 1 | extern crate alloc; 2 | 3 | use core::ops::RangeBounds; 4 | use std::assert_eq; 5 | use std::fmt::Display; 6 | 7 | use crate::generic_impl::gap_buffer::MAX_STRING_SIZE; 8 | use crate::rle::Sliceable; 9 | use crate::{BTree, BTreeTrait, LeafIndex, LengthFinder, QueryResult}; 10 | 11 | use super::gap_buffer::GapBuffer; 12 | use super::len_finder::UseLengthFinder; 13 | 14 | #[derive(Debug)] 15 | struct RopeTrait; 16 | 17 | #[derive(Debug)] 18 | struct Cursor { 19 | pos: usize, 20 | leaf: LeafIndex, 21 | } 22 | 23 | // TODO: move Rope into a separate project 24 | #[derive(Debug)] 25 | pub struct Rope { 26 | tree: BTree, 27 | cursor: Option, 28 | } 29 | 30 | impl UseLengthFinder for RopeTrait { 31 | #[inline(always)] 32 | fn get_len(cache: &::Cache) -> usize { 33 | *cache as usize 34 | } 35 | } 36 | 37 | impl Rope { 38 | #[inline(always)] 39 | pub fn len(&self) -> usize { 40 | self.tree.root_cache as usize 41 | } 42 | 43 | #[inline(always)] 44 | pub fn is_empty(&self) -> bool { 45 | self.tree.root_cache == 0 46 | } 47 | 48 | pub fn insert(&mut self, index: usize, elem: &str) { 49 | if index > self.len() { 50 | panic!("index {} out of range len={}", index, self.len()); 51 | } 52 | 53 | if self.is_empty() { 54 | for chunk in GapBuffer::from_str(elem) { 55 | self.tree.push(chunk); 56 | } 57 | return; 58 | } 59 | 60 | if let Some(Cursor { pos, leaf }) = self.cursor { 61 | if pos <= index { 62 | let node = self.tree.leaf_nodes.get(leaf.0).unwrap(); 63 | if index <= pos + node.elem.len() { 64 | let mut success = true; 65 | let offset = index - pos; 66 | let valid = self 67 | .tree 68 | .update_leaf(leaf, |leaf| { 69 | if leaf.len() + elem.len() < MAX_STRING_SIZE { 70 | leaf.insert_bytes(offset, elem.as_bytes()).unwrap(); 71 | (true, None, None) 72 | } else { 73 | let mut right = leaf.split(offset); 74 | if leaf.len() + elem.len() < MAX_STRING_SIZE { 75 | success = leaf.push_bytes(elem.as_bytes()).is_ok(); 76 | } else { 77 | success = right.insert_bytes(0, elem.as_bytes()).is_ok(); 78 | } 79 | 80 | (true, Some(right), None) 81 | } 82 | }) 83 | .0; 84 | 85 | if !valid { 86 | self.cursor = None; 87 | } 88 | 89 | if success { 90 | return; 91 | } 92 | } 93 | } 94 | } 95 | 96 | let (q, f) = self.tree.query_with_finder_return::(&index); 97 | self.cursor = q.and_then(|q| { 98 | if q.offset() == 0 { 99 | if f.slot == 0 || f.parent.is_none() { 100 | None 101 | } else { 102 | let node = self.tree.in_nodes.get(f.parent.unwrap()).unwrap(); 103 | let child = &node.children[f.slot as usize - 1]; 104 | Some(Cursor { 105 | pos: index - child.cache as usize, 106 | leaf: child.arena.unwrap().into(), 107 | }) 108 | } 109 | } else { 110 | Some(Cursor { 111 | pos: index - q.offset(), 112 | leaf: q.leaf(), 113 | }) 114 | } 115 | }); 116 | 117 | self.tree 118 | .insert_many_by_cursor(q.map(|x| x.cursor), GapBuffer::from_str(elem)); 119 | } 120 | 121 | pub fn delete_range(&mut self, range: impl RangeBounds) { 122 | if self.is_empty() { 123 | return; 124 | } 125 | 126 | let start = match range.start_bound() { 127 | core::ops::Bound::Included(x) => *x, 128 | core::ops::Bound::Excluded(x) => *x + 1, 129 | core::ops::Bound::Unbounded => 0, 130 | }; 131 | let end = match range.end_bound() { 132 | core::ops::Bound::Included(&x) => x + 1, 133 | core::ops::Bound::Excluded(&x) => x, 134 | core::ops::Bound::Unbounded => self.len(), 135 | }; 136 | let end = end.min(self.len()); 137 | let start = start.min(end); 138 | if start == end { 139 | return; 140 | } 141 | 142 | if let Some(Cursor { pos, leaf }) = self.cursor { 143 | if pos <= start { 144 | let node = self.tree.leaf_nodes.get(leaf.0).unwrap(); 145 | if end <= pos + node.elem.len() { 146 | let start_offset = start - pos; 147 | let end_offset = end - pos; 148 | let valid = self 149 | .tree 150 | .update_leaf(leaf, |leaf| { 151 | leaf.delete(start_offset..end_offset); 152 | (true, None, None) 153 | }) 154 | .0; 155 | 156 | if !valid { 157 | self.cursor = None; 158 | } 159 | 160 | return; 161 | } 162 | } 163 | } 164 | 165 | if end - start == 1 { 166 | let q = self 167 | .tree 168 | .update_leaf_by_search::(&start, |leaf, pos| { 169 | leaf.delete(pos.cursor.offset..pos.cursor.offset + 1); 170 | Some((-1, None, None)) 171 | }); 172 | self.cursor = q.0.map(|q| Cursor { 173 | pos: start - q.offset, 174 | leaf: q.leaf, 175 | }); 176 | 177 | return; 178 | } 179 | 180 | self.cursor = None; 181 | let from = self.tree.query::(&start); 182 | let to = self.tree.query::(&end); 183 | match (from, to) { 184 | (Some(from), Some(to)) if from.cursor.leaf == to.cursor.leaf => { 185 | let leaf = self.tree.leaf_nodes.get_mut(from.arena()).unwrap(); 186 | if from.cursor.offset == 0 && to.cursor.offset == leaf.elem.len() { 187 | // delete the whole leaf 188 | self.tree.remove_leaf(from.cursor); 189 | } else { 190 | leaf.elem.delete(from.cursor.offset..to.cursor.offset); 191 | self.tree.recursive_update_cache( 192 | from.leaf().into(), 193 | true, 194 | Some(start as isize - end as isize), 195 | ); 196 | } 197 | } 198 | _ => { 199 | crate::iter::Drain::new(&mut self.tree, from, to); 200 | } 201 | } 202 | } 203 | 204 | fn iter(&self) -> impl Iterator { 205 | let mut node_iter = self 206 | .tree 207 | .first_path() 208 | .map(|first| crate::iter::Iter::new(&self.tree, first, self.tree.last_path().unwrap())); 209 | std::iter::from_fn(move || match &mut node_iter { 210 | Some(node_iter) => { 211 | if let Some(node) = node_iter.next() { 212 | Some(&node.1.elem) 213 | } else { 214 | None 215 | } 216 | } 217 | None => None, 218 | }) 219 | } 220 | 221 | pub fn slice(&mut self, _range: impl RangeBounds) { 222 | unimplemented!() 223 | } 224 | 225 | pub fn new() -> Self { 226 | Self { 227 | tree: BTree::new(), 228 | cursor: None, 229 | } 230 | } 231 | 232 | #[allow(unused)] 233 | fn node_len(&self) -> usize { 234 | self.tree.node_len() 235 | } 236 | 237 | #[allow(unused)] 238 | fn update_in_place(&mut self, pos: usize, new: &str) { 239 | todo!() 240 | } 241 | 242 | pub fn clear(&mut self) { 243 | self.tree.clear(); 244 | } 245 | 246 | #[allow(unused)] 247 | pub fn check(&self) { 248 | // dbg!(&self.tree); 249 | self.tree.check() 250 | } 251 | 252 | pub fn diagnose(&self) { 253 | self.tree.diagnose_balance(); 254 | } 255 | } 256 | 257 | impl Default for Rope { 258 | fn default() -> Self { 259 | Self::new() 260 | } 261 | } 262 | 263 | impl Display for Rope { 264 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 265 | let mut ans = Vec::with_capacity(self.len()); 266 | for elem in self.iter() { 267 | let (left, right) = elem.as_bytes(); 268 | ans.extend_from_slice(left); 269 | ans.extend_from_slice(right); 270 | } 271 | 272 | f.write_str(std::str::from_utf8(ans.as_slice()).unwrap()) 273 | } 274 | } 275 | 276 | impl BTreeTrait for RopeTrait { 277 | type Elem = GapBuffer; 278 | type Cache = isize; 279 | type CacheDiff = isize; 280 | 281 | #[inline(always)] 282 | fn calc_cache_internal(cache: &mut Self::Cache, caches: &[crate::Child]) -> isize { 283 | let new_cache = caches.iter().map(|x| x.cache).sum::(); 284 | let diff = new_cache - *cache; 285 | *cache = new_cache; 286 | diff 287 | } 288 | 289 | #[inline(always)] 290 | fn apply_cache_diff(cache: &mut Self::Cache, diff: &Self::CacheDiff) { 291 | *cache += *diff; 292 | } 293 | 294 | #[inline(always)] 295 | fn merge_cache_diff(diff1: &mut Self::CacheDiff, diff2: &Self::CacheDiff) { 296 | *diff1 += diff2; 297 | } 298 | 299 | #[inline(always)] 300 | fn get_elem_cache(elem: &Self::Elem) -> Self::Cache { 301 | elem.len() as isize 302 | } 303 | 304 | #[inline(always)] 305 | fn new_cache_to_diff(cache: &Self::Cache) -> Self::CacheDiff { 306 | *cache 307 | } 308 | 309 | fn sub_cache(cache_lhs: &Self::Cache, cache_rhs: &Self::Cache) -> Self::CacheDiff { 310 | cache_lhs - cache_rhs 311 | } 312 | } 313 | 314 | #[allow(unused)] 315 | fn test_prev_length(rope: &Rope, q: QueryResult) -> usize { 316 | let mut count = 0; 317 | rope.tree 318 | .visit_previous_caches(q.cursor(), |cache| match cache { 319 | crate::PreviousCache::NodeCache(cache) => { 320 | count += *cache as usize; 321 | } 322 | crate::PreviousCache::PrevSiblingElem(p) => { 323 | count += p.len(); 324 | } 325 | crate::PreviousCache::ThisElemAndOffset { offset, .. } => { 326 | count += offset; 327 | } 328 | }); 329 | count 330 | } 331 | 332 | #[allow(unused)] 333 | fn test_index(rope: &Rope) { 334 | for index in 0..rope.len() { 335 | let q = rope.tree.query::(&index).unwrap(); 336 | let i = test_prev_length(rope, q); 337 | assert_eq!(i, index); 338 | } 339 | } 340 | 341 | #[cfg(test)] 342 | mod test { 343 | 344 | use Action::*; 345 | 346 | use crate::HeapVec; 347 | 348 | use super::*; 349 | 350 | #[test] 351 | fn test() { 352 | let mut rope = Rope::new(); 353 | rope.insert(0, "123"); 354 | assert_eq!(rope.len(), 3); 355 | rope.insert(1, "x"); 356 | test_index(&rope); 357 | assert_eq!(rope.len(), 4); 358 | rope.delete_range(2..4); 359 | assert_eq!(&rope.to_string(), "1x"); 360 | rope.delete_range(..1); 361 | assert_eq!(&rope.to_string(), "x"); 362 | rope.delete_range(..); 363 | assert_eq!(&rope.to_string(), ""); 364 | assert_eq!(rope.len(), 0); 365 | } 366 | 367 | #[test] 368 | fn test_delete_middle() { 369 | let mut rope = Rope::new(); 370 | rope.insert(0, "135"); 371 | rope.delete_range(1..2); 372 | assert_eq!(&rope.to_string(), "15"); 373 | } 374 | 375 | #[test] 376 | fn test_insert_repeatedly() { 377 | let mut rope = Rope::new(); 378 | rope.insert(0, "123"); 379 | rope.insert(1, "x"); 380 | rope.insert(2, "y"); 381 | rope.insert(3, "z"); 382 | test_index(&rope); 383 | assert_eq!(&rope.to_string(), "1xyz23"); 384 | } 385 | 386 | #[test] 387 | #[ignore] 388 | fn test_update() { 389 | let mut rope = Rope::new(); 390 | rope.insert(0, "123"); 391 | rope.insert(3, "xyz"); 392 | rope.update_in_place(1, "kkkk"); 393 | assert_eq!(&rope.to_string(), "1kkkkz"); 394 | } 395 | 396 | #[test] 397 | fn test_clear() { 398 | let mut rope = Rope::new(); 399 | rope.insert(0, "123"); 400 | assert_eq!(rope.len(), 3); 401 | rope.clear(); 402 | assert_eq!(rope.len(), 0); 403 | assert_eq!(&rope.to_string(), ""); 404 | rope.insert(0, "kkk"); 405 | assert_eq!(&rope.to_string(), "kkk"); 406 | } 407 | 408 | #[test] 409 | fn test_insert_many() { 410 | let mut rope = Rope::new(); 411 | let s = "_12345678_".repeat(10); 412 | let mut expected = String::new(); 413 | for i in 0..100 { 414 | expected.insert_str(i, &s); 415 | rope.insert(i, &s); 416 | assert_eq!(&rope.to_string(), &expected) 417 | } 418 | } 419 | 420 | #[test] 421 | fn test_repeat_insert() { 422 | let mut rope = Rope::new(); 423 | rope.insert(0, "123"); 424 | for _ in 0..10000 { 425 | rope.insert(rope.len() / 2, "k"); 426 | } 427 | } 428 | 429 | #[test] 430 | #[ignore] 431 | fn test_update_1() { 432 | let mut rope = Rope::new(); 433 | for i in 0..100 { 434 | rope.insert(i, &(i % 10).to_string()); 435 | } 436 | 437 | rope.update_in_place(15, "kkkkk"); 438 | assert_eq!(&rope.to_string()[10..20], "01234kkkkk"); 439 | test_index(&rope); 440 | } 441 | 442 | #[derive(Debug)] 443 | enum Action { 444 | Insert { pos: u8, content: u8 }, 445 | Delete { pos: u8, len: u8 }, 446 | } 447 | 448 | fn fuzz(data: HeapVec) { 449 | let mut rope = Rope::new(); 450 | let mut truth = String::new(); 451 | for action in data { 452 | match action { 453 | Action::Insert { pos, content } => { 454 | let pos = pos as usize % (truth.len() + 1); 455 | let s = content.to_string(); 456 | dbg!("INS", pos, &s); 457 | dbg!(&rope); 458 | truth.insert_str(pos, &s); 459 | rope.insert(pos, &s); 460 | dbg!(&rope); 461 | rope.check(); 462 | assert_eq!(rope.len(), truth.len()); 463 | assert_eq!(rope.to_string(), truth, "{:#?}", &rope.tree); 464 | } 465 | Action::Delete { pos, len } => { 466 | let pos = pos as usize % (truth.len() + 1); 467 | let mut len = len as usize % 10; 468 | len = len.min(truth.len() - pos); 469 | dbg!("DEL", pos, len); 470 | dbg!(&rope); 471 | rope.delete_range(pos..(pos + len)); 472 | dbg!(&rope); 473 | truth.drain(pos..pos + len); 474 | rope.check(); 475 | assert_eq!(rope.len(), truth.len()); 476 | assert_eq!(rope.to_string(), truth, "{:#?}", &rope.tree); 477 | } 478 | } 479 | } 480 | 481 | assert_eq!(rope.to_string(), truth); 482 | } 483 | 484 | #[test] 485 | fn fuzz_0() { 486 | fuzz(vec![ 487 | Insert { 488 | pos: 0, 489 | content: 128, 490 | }, 491 | Insert { 492 | pos: 0, 493 | content: 249, 494 | }, 495 | Insert { 496 | pos: 108, 497 | content: 108, 498 | }, 499 | Delete { pos: 192, len: 193 }, 500 | Insert { 501 | pos: 106, 502 | content: 108, 503 | }, 504 | Insert { 505 | pos: 108, 506 | content: 108, 507 | }, 508 | Insert { 509 | pos: 100, 510 | content: 108, 511 | }, 512 | Insert { 513 | pos: 108, 514 | content: 108, 515 | }, 516 | Insert { 517 | pos: 108, 518 | content: 108, 519 | }, 520 | Insert { 521 | pos: 108, 522 | content: 108, 523 | }, 524 | Insert { pos: 0, content: 8 }, 525 | Insert { 526 | pos: 108, 527 | content: 108, 528 | }, 529 | Insert { 530 | pos: 108, 531 | content: 108, 532 | }, 533 | Insert { 534 | pos: 111, 535 | content: 127, 536 | }, 537 | Delete { pos: 255, len: 255 }, 538 | Delete { pos: 255, len: 36 }, 539 | Delete { pos: 255, len: 255 }, 540 | Delete { pos: 255, len: 255 }, 541 | Delete { pos: 255, len: 255 }, 542 | Delete { pos: 135, len: 169 }, 543 | Delete { pos: 255, len: 255 }, 544 | Delete { pos: 255, len: 255 }, 545 | Delete { pos: 255, len: 255 }, 546 | Delete { pos: 255, len: 255 }, 547 | ]) 548 | } 549 | 550 | #[test] 551 | fn fuzz_1() { 552 | fuzz(vec![ 553 | Insert { 554 | pos: 157, 555 | content: 108, 556 | }, 557 | Insert { 558 | pos: 255, 559 | content: 255, 560 | }, 561 | Insert { 562 | pos: 108, 563 | content: 108, 564 | }, 565 | Insert { 566 | pos: 108, 567 | content: 108, 568 | }, 569 | Insert { 570 | pos: 8, 571 | content: 101, 572 | }, 573 | Insert { 574 | pos: 111, 575 | content: 127, 576 | }, 577 | Delete { pos: 255, len: 169 }, 578 | ]) 579 | } 580 | 581 | #[test] 582 | fn fuzz_2() { 583 | fuzz(vec![ 584 | Insert { 585 | pos: 0, 586 | content: 128, 587 | }, 588 | Insert { 589 | pos: 0, 590 | content: 249, 591 | }, 592 | Insert { 593 | pos: 108, 594 | content: 108, 595 | }, 596 | Insert { 597 | pos: 108, 598 | content: 108, 599 | }, 600 | Insert { 601 | pos: 108, 602 | content: 108, 603 | }, 604 | Insert { 605 | pos: 108, 606 | content: 108, 607 | }, 608 | Insert { 609 | pos: 108, 610 | content: 108, 611 | }, 612 | Insert { 613 | pos: 108, 614 | content: 108, 615 | }, 616 | Insert { 617 | pos: 108, 618 | content: 0, 619 | }, 620 | Insert { 621 | pos: 108, 622 | content: 108, 623 | }, 624 | Insert { 625 | pos: 108, 626 | content: 249, 627 | }, 628 | Insert { 629 | pos: 135, 630 | content: 255, 631 | }, 632 | Delete { pos: 255, len: 255 }, 633 | Delete { pos: 169, len: 169 }, 634 | ]) 635 | } 636 | 637 | #[test] 638 | fn fuzz_3() { 639 | fuzz(vec![ 640 | Insert { 641 | pos: 111, 642 | content: 140, 643 | }, 644 | Insert { 645 | pos: 111, 646 | content: 107, 647 | }, 648 | Insert { 649 | pos: 35, 650 | content: 102, 651 | }, 652 | Insert { 653 | pos: 102, 654 | content: 102, 655 | }, 656 | Insert { 657 | pos: 102, 658 | content: 102, 659 | }, 660 | Insert { 661 | pos: 102, 662 | content: 102, 663 | }, 664 | Insert { 665 | pos: 64, 666 | content: 64, 667 | }, 668 | Insert { 669 | pos: 64, 670 | content: 64, 671 | }, 672 | Insert { 673 | pos: 64, 674 | content: 64, 675 | }, 676 | Insert { 677 | pos: 64, 678 | content: 0, 679 | }, 680 | Insert { 681 | pos: 64, 682 | content: 64, 683 | }, 684 | Insert { 685 | pos: 93, 686 | content: 93, 687 | }, 688 | Insert { 689 | pos: 93, 690 | content: 93, 691 | }, 692 | Insert { 693 | pos: 93, 694 | content: 93, 695 | }, 696 | Insert { 697 | pos: 93, 698 | content: 93, 699 | }, 700 | Insert { 701 | pos: 93, 702 | content: 93, 703 | }, 704 | Insert { 705 | pos: 93, 706 | content: 93, 707 | }, 708 | Insert { 709 | pos: 93, 710 | content: 93, 711 | }, 712 | Insert { 713 | pos: 93, 714 | content: 93, 715 | }, 716 | Insert { 717 | pos: 93, 718 | content: 93, 719 | }, 720 | Insert { 721 | pos: 93, 722 | content: 93, 723 | }, 724 | Insert { 725 | pos: 93, 726 | content: 93, 727 | }, 728 | Insert { 729 | pos: 93, 730 | content: 93, 731 | }, 732 | Insert { 733 | pos: 93, 734 | content: 93, 735 | }, 736 | Insert { 737 | pos: 93, 738 | content: 93, 739 | }, 740 | Insert { 741 | pos: 93, 742 | content: 93, 743 | }, 744 | Insert { 745 | pos: 64, 746 | content: 64, 747 | }, 748 | Insert { 749 | pos: 64, 750 | content: 64, 751 | }, 752 | Insert { 753 | pos: 64, 754 | content: 64, 755 | }, 756 | Insert { 757 | pos: 102, 758 | content: 119, 759 | }, 760 | Insert { 761 | pos: 119, 762 | content: 119, 763 | }, 764 | Insert { 765 | pos: 119, 766 | content: 119, 767 | }, 768 | Insert { 769 | pos: 119, 770 | content: 119, 771 | }, 772 | Insert { 773 | pos: 119, 774 | content: 119, 775 | }, 776 | Insert { 777 | pos: 119, 778 | content: 111, 779 | }, 780 | Insert { 781 | pos: 102, 782 | content: 102, 783 | }, 784 | Insert { 785 | pos: 102, 786 | content: 101, 787 | }, 788 | Insert { 789 | pos: 36, 790 | content: 146, 791 | }, 792 | Delete { pos: 74, len: 102 }, 793 | Insert { 794 | pos: 119, 795 | content: 119, 796 | }, 797 | Insert { 798 | pos: 119, 799 | content: 119, 800 | }, 801 | Insert { 802 | pos: 17, 803 | content: 17, 804 | }, 805 | Insert { 806 | pos: 17, 807 | content: 17, 808 | }, 809 | Insert { 810 | pos: 64, 811 | content: 64, 812 | }, 813 | Insert { 814 | pos: 64, 815 | content: 64, 816 | }, 817 | Insert { 818 | pos: 64, 819 | content: 64, 820 | }, 821 | Insert { 822 | pos: 64, 823 | content: 64, 824 | }, 825 | Insert { 826 | pos: 64, 827 | content: 64, 828 | }, 829 | Insert { 830 | pos: 64, 831 | content: 64, 832 | }, 833 | Insert { 834 | pos: 64, 835 | content: 64, 836 | }, 837 | Insert { pos: 0, content: 0 }, 838 | Insert { 839 | pos: 102, 840 | content: 119, 841 | }, 842 | Insert { 843 | pos: 119, 844 | content: 119, 845 | }, 846 | Insert { 847 | pos: 119, 848 | content: 119, 849 | }, 850 | Insert { 851 | pos: 119, 852 | content: 119, 853 | }, 854 | Insert { 855 | pos: 119, 856 | content: 119, 857 | }, 858 | Insert { 859 | pos: 119, 860 | content: 111, 861 | }, 862 | Insert { 863 | pos: 102, 864 | content: 102, 865 | }, 866 | Insert { pos: 0, content: 0 }, 867 | Insert { 868 | pos: 3, 869 | content: 73, 870 | }, 871 | Insert { 872 | pos: 146, 873 | content: 74, 874 | }, 875 | Insert { 876 | pos: 119, 877 | content: 119, 878 | }, 879 | Insert { 880 | pos: 119, 881 | content: 119, 882 | }, 883 | Insert { 884 | pos: 119, 885 | content: 119, 886 | }, 887 | Insert { 888 | pos: 119, 889 | content: 119, 890 | }, 891 | Insert { 892 | pos: 21, 893 | content: 119, 894 | }, 895 | Insert { 896 | pos: 119, 897 | content: 119, 898 | }, 899 | Insert { 900 | pos: 119, 901 | content: 119, 902 | }, 903 | Insert { 904 | pos: 111, 905 | content: 111, 906 | }, 907 | Insert { pos: 0, content: 8 }, 908 | Insert { 909 | pos: 102, 910 | content: 102, 911 | }, 912 | Insert { 913 | pos: 102, 914 | content: 102, 915 | }, 916 | Insert { 917 | pos: 102, 918 | content: 3, 919 | }, 920 | Insert { 921 | pos: 36, 922 | content: 146, 923 | }, 924 | Insert { 925 | pos: 119, 926 | content: 119, 927 | }, 928 | Delete { pos: 111, len: 119 }, 929 | Insert { 930 | pos: 119, 931 | content: 119, 932 | }, 933 | Insert { 934 | pos: 102, 935 | content: 102, 936 | }, 937 | Insert { 938 | pos: 102, 939 | content: 102, 940 | }, 941 | Insert { 942 | pos: 73, 943 | content: 36, 944 | }, 945 | Delete { pos: 74, len: 102 }, 946 | Delete { pos: 255, len: 255 }, 947 | Insert { 948 | pos: 42, 949 | content: 64, 950 | }, 951 | Insert { 952 | pos: 64, 953 | content: 64, 954 | }, 955 | Insert { 956 | pos: 64, 957 | content: 64, 958 | }, 959 | Insert { 960 | pos: 64, 961 | content: 64, 962 | }, 963 | Insert { 964 | pos: 102, 965 | content: 102, 966 | }, 967 | Insert { 968 | pos: 119, 969 | content: 119, 970 | }, 971 | Insert { 972 | pos: 42, 973 | content: 42, 974 | }, 975 | Insert { 976 | pos: 42, 977 | content: 42, 978 | }, 979 | Insert { 980 | pos: 42, 981 | content: 42, 982 | }, 983 | Insert { 984 | pos: 0, 985 | content: 15, 986 | }, 987 | Insert { 988 | pos: 42, 989 | content: 42, 990 | }, 991 | Insert { 992 | pos: 42, 993 | content: 42, 994 | }, 995 | Insert { 996 | pos: 42, 997 | content: 42, 998 | }, 999 | Insert { 1000 | pos: 42, 1001 | content: 42, 1002 | }, 1003 | Insert { 1004 | pos: 42, 1005 | content: 42, 1006 | }, 1007 | Insert { 1008 | pos: 42, 1009 | content: 42, 1010 | }, 1011 | Insert { 1012 | pos: 42, 1013 | content: 42, 1014 | }, 1015 | Insert { 1016 | pos: 42, 1017 | content: 42, 1018 | }, 1019 | Insert { 1020 | pos: 42, 1021 | content: 42, 1022 | }, 1023 | Insert { 1024 | pos: 119, 1025 | content: 119, 1026 | }, 1027 | Insert { 1028 | pos: 102, 1029 | content: 102, 1030 | }, 1031 | Insert { 1032 | pos: 102, 1033 | content: 102, 1034 | }, 1035 | Insert { 1036 | pos: 102, 1037 | content: 3, 1038 | }, 1039 | Insert { 1040 | pos: 36, 1041 | content: 146, 1042 | }, 1043 | Insert { 1044 | pos: 255, 1045 | content: 255, 1046 | }, 1047 | Insert { 1048 | pos: 42, 1049 | content: 42, 1050 | }, 1051 | Insert { 1052 | pos: 64, 1053 | content: 64, 1054 | }, 1055 | Insert { 1056 | pos: 64, 1057 | content: 64, 1058 | }, 1059 | Insert { 1060 | pos: 64, 1061 | content: 64, 1062 | }, 1063 | Insert { 1064 | pos: 64, 1065 | content: 64, 1066 | }, 1067 | Insert { 1068 | pos: 119, 1069 | content: 119, 1070 | }, 1071 | Insert { 1072 | pos: 119, 1073 | content: 119, 1074 | }, 1075 | Insert { 1076 | pos: 42, 1077 | content: 42, 1078 | }, 1079 | Insert { 1080 | pos: 42, 1081 | content: 38, 1082 | }, 1083 | Insert { pos: 0, content: 0 }, 1084 | Insert { 1085 | pos: 89, 1086 | content: 89, 1087 | }, 1088 | Insert { 1089 | pos: 89, 1090 | content: 89, 1091 | }, 1092 | Insert { 1093 | pos: 89, 1094 | content: 89, 1095 | }, 1096 | Insert { 1097 | pos: 89, 1098 | content: 89, 1099 | }, 1100 | Insert { 1101 | pos: 89, 1102 | content: 89, 1103 | }, 1104 | Insert { 1105 | pos: 89, 1106 | content: 89, 1107 | }, 1108 | Insert { 1109 | pos: 89, 1110 | content: 89, 1111 | }, 1112 | Insert { 1113 | pos: 89, 1114 | content: 89, 1115 | }, 1116 | Insert { 1117 | pos: 89, 1118 | content: 89, 1119 | }, 1120 | Insert { 1121 | pos: 89, 1122 | content: 89, 1123 | }, 1124 | Insert { 1125 | pos: 89, 1126 | content: 89, 1127 | }, 1128 | Insert { 1129 | pos: 89, 1130 | content: 89, 1131 | }, 1132 | Insert { 1133 | pos: 89, 1134 | content: 89, 1135 | }, 1136 | Insert { 1137 | pos: 89, 1138 | content: 89, 1139 | }, 1140 | Insert { 1141 | pos: 89, 1142 | content: 89, 1143 | }, 1144 | Insert { 1145 | pos: 89, 1146 | content: 89, 1147 | }, 1148 | Insert { 1149 | pos: 42, 1150 | content: 42, 1151 | }, 1152 | Insert { 1153 | pos: 42, 1154 | content: 42, 1155 | }, 1156 | Insert { 1157 | pos: 42, 1158 | content: 42, 1159 | }, 1160 | Insert { 1161 | pos: 42, 1162 | content: 42, 1163 | }, 1164 | Insert { 1165 | pos: 42, 1166 | content: 42, 1167 | }, 1168 | Insert { 1169 | pos: 119, 1170 | content: 119, 1171 | }, 1172 | Insert { 1173 | pos: 119, 1174 | content: 37, 1175 | }, 1176 | Insert { 1177 | pos: 101, 1178 | content: 102, 1179 | }, 1180 | Insert { pos: 0, content: 0 }, 1181 | Delete { pos: 193, len: 63 }, 1182 | Insert { 1183 | pos: 108, 1184 | content: 108, 1185 | }, 1186 | Insert { 1187 | pos: 108, 1188 | content: 0, 1189 | }, 1190 | Insert { 1191 | pos: 108, 1192 | content: 108, 1193 | }, 1194 | Insert { 1195 | pos: 108, 1196 | content: 108, 1197 | }, 1198 | Insert { 1199 | pos: 108, 1200 | content: 108, 1201 | }, 1202 | Insert { pos: 0, content: 8 }, 1203 | Insert { 1204 | pos: 108, 1205 | content: 108, 1206 | }, 1207 | Insert { 1208 | pos: 102, 1209 | content: 102, 1210 | }, 1211 | Insert { 1212 | pos: 119, 1213 | content: 119, 1214 | }, 1215 | Insert { 1216 | pos: 119, 1217 | content: 119, 1218 | }, 1219 | Insert { 1220 | pos: 119, 1221 | content: 119, 1222 | }, 1223 | Insert { 1224 | pos: 119, 1225 | content: 119, 1226 | }, 1227 | Delete { pos: 199, len: 199 }, 1228 | Delete { pos: 199, len: 199 }, 1229 | Delete { pos: 199, len: 199 }, 1230 | Delete { pos: 199, len: 199 }, 1231 | Delete { pos: 199, len: 199 }, 1232 | Delete { pos: 199, len: 187 }, 1233 | Delete { pos: 187, len: 187 }, 1234 | Delete { pos: 187, len: 187 }, 1235 | Delete { pos: 187, len: 187 }, 1236 | Delete { pos: 187, len: 187 }, 1237 | Delete { pos: 187, len: 187 }, 1238 | Delete { pos: 187, len: 187 }, 1239 | Delete { pos: 187, len: 187 }, 1240 | Delete { pos: 187, len: 187 }, 1241 | Insert { 1242 | pos: 3, 1243 | content: 119, 1244 | }, 1245 | Insert { 1246 | pos: 102, 1247 | content: 102, 1248 | }, 1249 | Delete { pos: 163, len: 163 }, 1250 | Delete { pos: 163, len: 163 }, 1251 | Delete { pos: 163, len: 102 }, 1252 | Insert { 1253 | pos: 102, 1254 | content: 102, 1255 | }, 1256 | Insert { 1257 | pos: 108, 1258 | content: 249, 1259 | }, 1260 | Insert { 1261 | pos: 135, 1262 | content: 169, 1263 | }, 1264 | Delete { pos: 255, len: 255 }, 1265 | Delete { pos: 255, len: 255 }, 1266 | Delete { pos: 111, len: 255 }, 1267 | Insert { 1268 | pos: 111, 1269 | content: 111, 1270 | }, 1271 | Insert { 1272 | pos: 255, 1273 | content: 255, 1274 | }, 1275 | ]) 1276 | } 1277 | 1278 | #[test] 1279 | fn fuzz_4() { 1280 | fuzz(vec![ 1281 | Insert { 1282 | pos: 0, 1283 | content: 128, 1284 | }, 1285 | Insert { 1286 | pos: 0, 1287 | content: 249, 1288 | }, 1289 | Insert { pos: 8, content: 0 }, 1290 | Insert { 1291 | pos: 108, 1292 | content: 108, 1293 | }, 1294 | Insert { 1295 | pos: 108, 1296 | content: 108, 1297 | }, 1298 | Insert { 1299 | pos: 108, 1300 | content: 108, 1301 | }, 1302 | Insert { 1303 | pos: 108, 1304 | content: 108, 1305 | }, 1306 | Insert { 1307 | pos: 108, 1308 | content: 108, 1309 | }, 1310 | Insert { 1311 | pos: 108, 1312 | content: 0, 1313 | }, 1314 | Insert { 1315 | pos: 108, 1316 | content: 108, 1317 | }, 1318 | ]) 1319 | } 1320 | 1321 | #[test] 1322 | fn fuzz_5() { 1323 | fuzz(vec![ 1324 | Insert { 1325 | pos: 123, 1326 | content: 123, 1327 | }, 1328 | Insert { 1329 | pos: 123, 1330 | content: 123, 1331 | }, 1332 | Insert { 1333 | pos: 123, 1334 | content: 123, 1335 | }, 1336 | Insert { 1337 | pos: 0, 1338 | content: 123, 1339 | }, 1340 | Delete { pos: 108, len: 108 }, 1341 | Insert { 1342 | pos: 108, 1343 | content: 108, 1344 | }, 1345 | Insert { 1346 | pos: 108, 1347 | content: 108, 1348 | }, 1349 | Insert { 1350 | pos: 108, 1351 | content: 108, 1352 | }, 1353 | Insert { 1354 | pos: 108, 1355 | content: 108, 1356 | }, 1357 | Insert { 1358 | pos: 12, 1359 | content: 0, 1360 | }, 1361 | Insert { pos: 0, content: 0 }, 1362 | Insert { 1363 | pos: 127, 1364 | content: 135, 1365 | }, 1366 | Delete { pos: 255, len: 246 }, 1367 | Delete { pos: 246, len: 246 }, 1368 | Delete { pos: 246, len: 246 }, 1369 | Delete { pos: 246, len: 246 }, 1370 | Insert { 1371 | pos: 101, 1372 | content: 101, 1373 | }, 1374 | Insert { 1375 | pos: 101, 1376 | content: 101, 1377 | }, 1378 | Delete { pos: 255, len: 255 }, 1379 | Delete { pos: 169, len: 169 }, 1380 | ]) 1381 | } 1382 | 1383 | #[test] 1384 | fn fuzz_6() { 1385 | fuzz(vec![ 1386 | Insert { 1387 | pos: 0, 1388 | content: 128, 1389 | }, 1390 | Insert { pos: 0, content: 0 }, 1391 | Insert { 1392 | pos: 108, 1393 | content: 108, 1394 | }, 1395 | Insert { 1396 | pos: 108, 1397 | content: 108, 1398 | }, 1399 | Insert { 1400 | pos: 108, 1401 | content: 108, 1402 | }, 1403 | Insert { 1404 | pos: 108, 1405 | content: 108, 1406 | }, 1407 | Insert { 1408 | pos: 108, 1409 | content: 108, 1410 | }, 1411 | Insert { 1412 | pos: 0, 1413 | content: 249, 1414 | }, 1415 | Insert { 1416 | pos: 108, 1417 | content: 108, 1418 | }, 1419 | Insert { 1420 | pos: 108, 1421 | content: 108, 1422 | }, 1423 | Insert { 1424 | pos: 108, 1425 | content: 108, 1426 | }, 1427 | Insert { 1428 | pos: 108, 1429 | content: 108, 1430 | }, 1431 | Insert { 1432 | pos: 171, 1433 | content: 171, 1434 | }, 1435 | Delete { pos: 171, len: 0 }, 1436 | Insert { 1437 | pos: 108, 1438 | content: 108, 1439 | }, 1440 | Insert { 1441 | pos: 108, 1442 | content: 108, 1443 | }, 1444 | Insert { 1445 | pos: 108, 1446 | content: 108, 1447 | }, 1448 | Insert { 1449 | pos: 108, 1450 | content: 108, 1451 | }, 1452 | Insert { 1453 | pos: 108, 1454 | content: 171, 1455 | }, 1456 | Delete { pos: 187, len: 171 }, 1457 | Delete { pos: 171, len: 171 }, 1458 | Delete { pos: 171, len: 171 }, 1459 | Delete { pos: 171, len: 171 }, 1460 | Delete { pos: 171, len: 171 }, 1461 | Insert { 1462 | pos: 108, 1463 | content: 108, 1464 | }, 1465 | Insert { 1466 | pos: 108, 1467 | content: 108, 1468 | }, 1469 | Insert { 1470 | pos: 108, 1471 | content: 108, 1472 | }, 1473 | Insert { 1474 | pos: 108, 1475 | content: 108, 1476 | }, 1477 | Insert { 1478 | pos: 171, 1479 | content: 171, 1480 | }, 1481 | Insert { pos: 0, content: 0 }, 1482 | Insert { 1483 | pos: 108, 1484 | content: 108, 1485 | }, 1486 | Insert { 1487 | pos: 108, 1488 | content: 108, 1489 | }, 1490 | Insert { 1491 | pos: 110, 1492 | content: 108, 1493 | }, 1494 | Insert { 1495 | pos: 108, 1496 | content: 108, 1497 | }, 1498 | Insert { 1499 | pos: 108, 1500 | content: 171, 1501 | }, 1502 | Delete { pos: 187, len: 171 }, 1503 | Delete { pos: 171, len: 171 }, 1504 | Delete { pos: 171, len: 171 }, 1505 | Delete { pos: 171, len: 171 }, 1506 | Delete { pos: 171, len: 171 }, 1507 | Delete { pos: 171, len: 171 }, 1508 | Delete { pos: 171, len: 171 }, 1509 | Delete { pos: 171, len: 171 }, 1510 | Insert { 1511 | pos: 8, 1512 | content: 108, 1513 | }, 1514 | Insert { 1515 | pos: 108, 1516 | content: 108, 1517 | }, 1518 | Insert { 1519 | pos: 50, 1520 | content: 108, 1521 | }, 1522 | Delete { pos: 108, len: 108 }, 1523 | Insert { 1524 | pos: 108, 1525 | content: 87, 1526 | }, 1527 | Insert { 1528 | pos: 249, 1529 | content: 1, 1530 | }, 1531 | Delete { pos: 169, len: 235 }, 1532 | Delete { pos: 171, len: 171 }, 1533 | Delete { pos: 171, len: 171 }, 1534 | Delete { pos: 163, len: 171 }, 1535 | Delete { pos: 171, len: 171 }, 1536 | Insert { pos: 8, content: 0 }, 1537 | Insert { pos: 0, content: 0 }, 1538 | Delete { pos: 171, len: 171 }, 1539 | Delete { pos: 171, len: 171 }, 1540 | Delete { pos: 41, len: 164 }, 1541 | Delete { pos: 171, len: 171 }, 1542 | Delete { pos: 171, len: 171 }, 1543 | Delete { pos: 171, len: 171 }, 1544 | Delete { pos: 171, len: 171 }, 1545 | Delete { pos: 171, len: 171 }, 1546 | Delete { pos: 171, len: 171 }, 1547 | Delete { pos: 171, len: 171 }, 1548 | Delete { pos: 171, len: 171 }, 1549 | Insert { pos: 0, content: 0 }, 1550 | Insert { 1551 | pos: 108, 1552 | content: 108, 1553 | }, 1554 | Insert { 1555 | pos: 108, 1556 | content: 108, 1557 | }, 1558 | Delete { pos: 171, len: 171 }, 1559 | Delete { pos: 171, len: 171 }, 1560 | Insert { 1561 | pos: 123, 1562 | content: 123, 1563 | }, 1564 | Insert { 1565 | pos: 123, 1566 | content: 123, 1567 | }, 1568 | Insert { 1569 | pos: 123, 1570 | content: 2, 1571 | }, 1572 | Insert { 1573 | pos: 254, 1574 | content: 123, 1575 | }, 1576 | Insert { 1577 | pos: 123, 1578 | content: 123, 1579 | }, 1580 | Insert { 1581 | pos: 123, 1582 | content: 123, 1583 | }, 1584 | Insert { 1585 | pos: 123, 1586 | content: 123, 1587 | }, 1588 | Insert { 1589 | pos: 0, 1590 | content: 123, 1591 | }, 1592 | Delete { pos: 238, len: 238 }, 1593 | Delete { pos: 238, len: 238 }, 1594 | Delete { pos: 238, len: 238 }, 1595 | Delete { pos: 238, len: 238 }, 1596 | Delete { pos: 238, len: 238 }, 1597 | Delete { pos: 238, len: 238 }, 1598 | Delete { pos: 238, len: 238 }, 1599 | Delete { pos: 238, len: 238 }, 1600 | Insert { 1601 | pos: 238, 1602 | content: 238, 1603 | }, 1604 | Delete { pos: 238, len: 238 }, 1605 | Delete { pos: 238, len: 238 }, 1606 | Insert { pos: 0, content: 0 }, 1607 | Insert { 1608 | pos: 238, 1609 | content: 238, 1610 | }, 1611 | Delete { pos: 238, len: 238 }, 1612 | Delete { pos: 238, len: 238 }, 1613 | Delete { pos: 238, len: 238 }, 1614 | Delete { pos: 238, len: 238 }, 1615 | Delete { pos: 238, len: 238 }, 1616 | Insert { 1617 | pos: 123, 1618 | content: 123, 1619 | }, 1620 | Insert { 1621 | pos: 86, 1622 | content: 86, 1623 | }, 1624 | Insert { 1625 | pos: 123, 1626 | content: 2, 1627 | }, 1628 | Insert { 1629 | pos: 254, 1630 | content: 123, 1631 | }, 1632 | Insert { 1633 | pos: 123, 1634 | content: 123, 1635 | }, 1636 | Insert { 1637 | pos: 123, 1638 | content: 123, 1639 | }, 1640 | Insert { 1641 | pos: 123, 1642 | content: 123, 1643 | }, 1644 | Insert { 1645 | pos: 0, 1646 | content: 238, 1647 | }, 1648 | Delete { pos: 238, len: 238 }, 1649 | Delete { pos: 238, len: 238 }, 1650 | Delete { pos: 238, len: 238 }, 1651 | Delete { pos: 238, len: 238 }, 1652 | Insert { 1653 | pos: 238, 1654 | content: 123, 1655 | }, 1656 | Delete { pos: 123, len: 123 }, 1657 | Insert { 1658 | pos: 86, 1659 | content: 254, 1660 | }, 1661 | Insert { 1662 | pos: 33, 1663 | content: 238, 1664 | }, 1665 | Delete { pos: 238, len: 238 }, 1666 | Delete { pos: 238, len: 238 }, 1667 | Insert { 1668 | pos: 123, 1669 | content: 2, 1670 | }, 1671 | Insert { pos: 0, content: 0 }, 1672 | Delete { pos: 238, len: 238 }, 1673 | Delete { pos: 123, len: 123 }, 1674 | Insert { 1675 | pos: 0, 1676 | content: 121, 1677 | }, 1678 | Insert { 1679 | pos: 26, 1680 | content: 0, 1681 | }, 1682 | Insert { pos: 0, content: 0 }, 1683 | Insert { 1684 | pos: 123, 1685 | content: 123, 1686 | }, 1687 | Delete { pos: 238, len: 254 }, 1688 | Insert { 1689 | pos: 144, 1690 | content: 238, 1691 | }, 1692 | Delete { pos: 91, len: 238 }, 1693 | Delete { pos: 238, len: 238 }, 1694 | Insert { 1695 | pos: 123, 1696 | content: 238, 1697 | }, 1698 | Delete { pos: 238, len: 238 }, 1699 | Delete { pos: 0, len: 51 }, 1700 | Insert { 1701 | pos: 123, 1702 | content: 123, 1703 | }, 1704 | Insert { 1705 | pos: 102, 1706 | content: 102, 1707 | }, 1708 | Insert { 1709 | pos: 102, 1710 | content: 102, 1711 | }, 1712 | Insert { 1713 | pos: 123, 1714 | content: 123, 1715 | }, 1716 | Delete { pos: 238, len: 238 }, 1717 | Delete { pos: 238, len: 123 }, 1718 | Insert { 1719 | pos: 123, 1720 | content: 123, 1721 | }, 1722 | Insert { 1723 | pos: 123, 1724 | content: 123, 1725 | }, 1726 | Insert { 1727 | pos: 123, 1728 | content: 123, 1729 | }, 1730 | Insert { 1731 | pos: 123, 1732 | content: 86, 1733 | }, 1734 | Delete { pos: 101, len: 144 }, 1735 | Delete { pos: 238, len: 91 }, 1736 | Delete { pos: 238, len: 238 }, 1737 | Insert { pos: 0, content: 0 }, 1738 | Insert { 1739 | pos: 108, 1740 | content: 108, 1741 | }, 1742 | Insert { pos: 3, content: 0 }, 1743 | Insert { pos: 0, content: 0 }, 1744 | Insert { 1745 | pos: 171, 1746 | content: 63, 1747 | }, 1748 | Delete { pos: 171, len: 171 }, 1749 | Delete { pos: 171, len: 171 }, 1750 | Delete { pos: 171, len: 171 }, 1751 | Delete { pos: 171, len: 171 }, 1752 | Delete { pos: 171, len: 171 }, 1753 | Delete { pos: 171, len: 171 }, 1754 | Insert { pos: 0, content: 0 }, 1755 | Insert { 1756 | pos: 108, 1757 | content: 108, 1758 | }, 1759 | Insert { pos: 0, content: 0 }, 1760 | Delete { pos: 235, len: 235 }, 1761 | Insert { 1762 | pos: 108, 1763 | content: 108, 1764 | }, 1765 | Insert { pos: 8, content: 0 }, 1766 | Insert { 1767 | pos: 127, 1768 | content: 135, 1769 | }, 1770 | Delete { pos: 171, len: 171 }, 1771 | Delete { pos: 0, len: 171 }, 1772 | Delete { pos: 171, len: 171 }, 1773 | Delete { pos: 171, len: 171 }, 1774 | Insert { 1775 | pos: 0, 1776 | content: 171, 1777 | }, 1778 | Delete { pos: 1, len: 126 }, 1779 | Delete { pos: 235, len: 154 }, 1780 | Delete { pos: 171, len: 171 }, 1781 | Delete { pos: 171, len: 171 }, 1782 | Insert { 1783 | pos: 84, 1784 | content: 84, 1785 | }, 1786 | Delete { pos: 171, len: 171 }, 1787 | Delete { pos: 171, len: 171 }, 1788 | Delete { pos: 171, len: 171 }, 1789 | Delete { pos: 171, len: 171 }, 1790 | Delete { pos: 238, len: 238 }, 1791 | Delete { pos: 238, len: 238 }, 1792 | Insert { pos: 0, content: 0 }, 1793 | Delete { pos: 91, len: 238 }, 1794 | Delete { pos: 238, len: 238 }, 1795 | Delete { pos: 238, len: 238 }, 1796 | Delete { pos: 238, len: 238 }, 1797 | Delete { pos: 238, len: 238 }, 1798 | Delete { pos: 171, len: 171 }, 1799 | Insert { 1800 | pos: 249, 1801 | content: 1, 1802 | }, 1803 | Insert { 1804 | pos: 108, 1805 | content: 108, 1806 | }, 1807 | Insert { pos: 0, content: 0 }, 1808 | Insert { 1809 | pos: 108, 1810 | content: 108, 1811 | }, 1812 | Delete { pos: 171, len: 171 }, 1813 | Delete { pos: 171, len: 171 }, 1814 | Delete { pos: 171, len: 171 }, 1815 | Delete { pos: 171, len: 171 }, 1816 | Delete { pos: 171, len: 171 }, 1817 | Delete { pos: 171, len: 171 }, 1818 | Delete { pos: 171, len: 171 }, 1819 | Insert { pos: 0, content: 8 }, 1820 | Insert { 1821 | pos: 108, 1822 | content: 32, 1823 | }, 1824 | Insert { pos: 0, content: 0 }, 1825 | Delete { pos: 235, len: 108 }, 1826 | Insert { 1827 | pos: 108, 1828 | content: 108, 1829 | }, 1830 | Delete { pos: 255, len: 6 }, 1831 | Insert { 1832 | pos: 135, 1833 | content: 169, 1834 | }, 1835 | Delete { pos: 171, len: 171 }, 1836 | Insert { 1837 | pos: 171, 1838 | content: 171, 1839 | }, 1840 | Delete { pos: 171, len: 171 }, 1841 | Delete { pos: 171, len: 171 }, 1842 | Insert { 1843 | pos: 171, 1844 | content: 171, 1845 | }, 1846 | Insert { 1847 | pos: 126, 1848 | content: 111, 1849 | }, 1850 | Delete { pos: 154, len: 171 }, 1851 | Delete { pos: 171, len: 171 }, 1852 | Delete { pos: 171, len: 171 }, 1853 | Insert { 1854 | pos: 84, 1855 | content: 171, 1856 | }, 1857 | Delete { pos: 171, len: 171 }, 1858 | Delete { pos: 171, len: 171 }, 1859 | Delete { pos: 171, len: 171 }, 1860 | Delete { pos: 171, len: 171 }, 1861 | Delete { pos: 171, len: 171 }, 1862 | Insert { 1863 | pos: 108, 1864 | content: 108, 1865 | }, 1866 | Insert { 1867 | pos: 108, 1868 | content: 108, 1869 | }, 1870 | Insert { 1871 | pos: 108, 1872 | content: 235, 1873 | }, 1874 | Insert { 1875 | pos: 108, 1876 | content: 108, 1877 | }, 1878 | Insert { 1879 | pos: 87, 1880 | content: 0, 1881 | }, 1882 | Delete { pos: 1, len: 111 }, 1883 | Delete { pos: 238, len: 238 }, 1884 | Insert { 1885 | pos: 123, 1886 | content: 123, 1887 | }, 1888 | Insert { 1889 | pos: 121, 1890 | content: 86, 1891 | }, 1892 | Insert { 1893 | pos: 123, 1894 | content: 123, 1895 | }, 1896 | Insert { 1897 | pos: 86, 1898 | content: 254, 1899 | }, 1900 | Insert { 1901 | pos: 123, 1902 | content: 123, 1903 | }, 1904 | Insert { 1905 | pos: 123, 1906 | content: 123, 1907 | }, 1908 | Insert { 1909 | pos: 123, 1910 | content: 123, 1911 | }, 1912 | Insert { 1913 | pos: 86, 1914 | content: 0, 1915 | }, 1916 | Delete { pos: 238, len: 238 }, 1917 | Delete { pos: 238, len: 238 }, 1918 | Delete { pos: 254, len: 193 }, 1919 | Delete { pos: 63, len: 64 }, 1920 | Insert { pos: 0, content: 0 }, 1921 | Delete { pos: 235, len: 235 }, 1922 | Insert { 1923 | pos: 108, 1924 | content: 108, 1925 | }, 1926 | Insert { pos: 0, content: 8 }, 1927 | Insert { 1928 | pos: 111, 1929 | content: 127, 1930 | }, 1931 | Delete { pos: 171, len: 171 }, 1932 | Delete { pos: 171, len: 0 }, 1933 | Delete { pos: 171, len: 171 }, 1934 | Delete { pos: 171, len: 171 }, 1935 | Delete { pos: 8, len: 0 }, 1936 | Delete { pos: 249, len: 1 }, 1937 | Delete { pos: 169, len: 235 }, 1938 | Delete { pos: 171, len: 171 }, 1939 | Delete { pos: 171, len: 171 }, 1940 | Delete { pos: 171, len: 171 }, 1941 | Delete { pos: 171, len: 171 }, 1942 | Insert { 1943 | pos: 8, 1944 | content: 108, 1945 | }, 1946 | Insert { 1947 | pos: 108, 1948 | content: 108, 1949 | }, 1950 | Insert { 1951 | pos: 50, 1952 | content: 108, 1953 | }, 1954 | Delete { pos: 108, len: 108 }, 1955 | Insert { 1956 | pos: 108, 1957 | content: 8, 1958 | }, 1959 | Insert { pos: 0, content: 0 }, 1960 | Delete { pos: 169, len: 235 }, 1961 | Delete { pos: 171, len: 171 }, 1962 | Delete { pos: 171, len: 171 }, 1963 | Delete { pos: 171, len: 171 }, 1964 | Delete { pos: 171, len: 171 }, 1965 | Insert { pos: 8, content: 0 }, 1966 | Insert { pos: 0, content: 0 }, 1967 | Delete { pos: 171, len: 171 }, 1968 | Delete { pos: 171, len: 171 }, 1969 | Delete { pos: 41, len: 164 }, 1970 | Delete { pos: 171, len: 171 }, 1971 | Delete { pos: 171, len: 171 }, 1972 | Delete { pos: 171, len: 171 }, 1973 | Delete { pos: 171, len: 171 }, 1974 | Delete { pos: 171, len: 171 }, 1975 | Delete { pos: 171, len: 171 }, 1976 | Delete { pos: 171, len: 171 }, 1977 | Delete { pos: 171, len: 171 }, 1978 | Insert { pos: 0, content: 0 }, 1979 | Insert { 1980 | pos: 108, 1981 | content: 108, 1982 | }, 1983 | Insert { 1984 | pos: 108, 1985 | content: 108, 1986 | }, 1987 | Delete { pos: 235, len: 235 }, 1988 | Insert { 1989 | pos: 108, 1990 | content: 108, 1991 | }, 1992 | Insert { pos: 8, content: 0 }, 1993 | Insert { 1994 | pos: 171, 1995 | content: 171, 1996 | }, 1997 | Insert { pos: 8, content: 0 }, 1998 | Insert { 1999 | pos: 127, 2000 | content: 135, 2001 | }, 2002 | Delete { pos: 171, len: 171 }, 2003 | Delete { pos: 171, len: 171 }, 2004 | Delete { pos: 41, len: 171 }, 2005 | Delete { pos: 171, len: 171 }, 2006 | Delete { pos: 171, len: 171 }, 2007 | Delete { pos: 171, len: 41 }, 2008 | Insert { 2009 | pos: 171, 2010 | content: 171, 2011 | }, 2012 | Delete { pos: 171, len: 171 }, 2013 | Delete { pos: 165, len: 171 }, 2014 | Delete { pos: 171, len: 171 }, 2015 | Delete { pos: 171, len: 171 }, 2016 | Delete { pos: 171, len: 171 }, 2017 | Delete { pos: 171, len: 170 }, 2018 | Delete { pos: 171, len: 171 }, 2019 | Delete { pos: 235, len: 235 }, 2020 | Insert { 2021 | pos: 108, 2022 | content: 108, 2023 | }, 2024 | Insert { 2025 | pos: 108, 2026 | content: 108, 2027 | }, 2028 | Insert { 2029 | pos: 108, 2030 | content: 108, 2031 | }, 2032 | Insert { 2033 | pos: 0, 2034 | content: 108, 2035 | }, 2036 | Delete { pos: 171, len: 171 }, 2037 | Delete { pos: 171, len: 171 }, 2038 | Insert { 2039 | pos: 171, 2040 | content: 171, 2041 | }, 2042 | Insert { pos: 0, content: 0 }, 2043 | Insert { 2044 | pos: 108, 2045 | content: 108, 2046 | }, 2047 | Insert { 2048 | pos: 108, 2049 | content: 108, 2050 | }, 2051 | Delete { pos: 235, len: 235 }, 2052 | Insert { 2053 | pos: 108, 2054 | content: 108, 2055 | }, 2056 | Insert { pos: 8, content: 0 }, 2057 | Insert { 2058 | pos: 127, 2059 | content: 135, 2060 | }, 2061 | Delete { pos: 171, len: 171 }, 2062 | Delete { pos: 171, len: 171 }, 2063 | Delete { pos: 171, len: 171 }, 2064 | Insert { 2065 | pos: 123, 2066 | content: 2, 2067 | }, 2068 | Insert { 2069 | pos: 254, 2070 | content: 123, 2071 | }, 2072 | Insert { 2073 | pos: 123, 2074 | content: 123, 2075 | }, 2076 | Insert { 2077 | pos: 123, 2078 | content: 123, 2079 | }, 2080 | Delete { pos: 238, len: 238 }, 2081 | Delete { pos: 238, len: 238 }, 2082 | Insert { 2083 | pos: 123, 2084 | content: 123, 2085 | }, 2086 | Insert { 2087 | pos: 123, 2088 | content: 123, 2089 | }, 2090 | Insert { 2091 | pos: 123, 2092 | content: 123, 2093 | }, 2094 | Insert { 2095 | pos: 123, 2096 | content: 123, 2097 | }, 2098 | Delete { pos: 255, len: 255 }, 2099 | Delete { pos: 238, len: 238 }, 2100 | Delete { pos: 238, len: 238 }, 2101 | Delete { pos: 238, len: 238 }, 2102 | Insert { 2103 | pos: 123, 2104 | content: 123, 2105 | }, 2106 | Insert { 2107 | pos: 121, 2108 | content: 86, 2109 | }, 2110 | Insert { pos: 0, content: 0 }, 2111 | Delete { pos: 238, len: 238 }, 2112 | Insert { 2113 | pos: 123, 2114 | content: 123, 2115 | }, 2116 | Delete { pos: 255, len: 255 }, 2117 | Delete { pos: 8, len: 238 }, 2118 | Delete { pos: 238, len: 238 }, 2119 | Insert { 2120 | pos: 123, 2121 | content: 123, 2122 | }, 2123 | Insert { 2124 | pos: 123, 2125 | content: 123, 2126 | }, 2127 | Insert { 2128 | pos: 123, 2129 | content: 123, 2130 | }, 2131 | Insert { 2132 | pos: 123, 2133 | content: 123, 2134 | }, 2135 | Delete { pos: 255, len: 255 }, 2136 | Delete { pos: 238, len: 238 }, 2137 | Delete { pos: 238, len: 238 }, 2138 | Delete { pos: 238, len: 238 }, 2139 | Delete { pos: 238, len: 238 }, 2140 | Delete { pos: 238, len: 238 }, 2141 | Insert { 2142 | pos: 238, 2143 | content: 238, 2144 | }, 2145 | Insert { pos: 0, content: 0 }, 2146 | Delete { pos: 91, len: 238 }, 2147 | Delete { pos: 238, len: 238 }, 2148 | Delete { pos: 238, len: 238 }, 2149 | Delete { pos: 238, len: 18 }, 2150 | Delete { pos: 238, len: 238 }, 2151 | Delete { pos: 238, len: 238 }, 2152 | Insert { 2153 | pos: 123, 2154 | content: 123, 2155 | }, 2156 | Insert { 2157 | pos: 121, 2158 | content: 86, 2159 | }, 2160 | Insert { 2161 | pos: 123, 2162 | content: 123, 2163 | }, 2164 | Insert { 2165 | pos: 86, 2166 | content: 254, 2167 | }, 2168 | Insert { 2169 | pos: 123, 2170 | content: 123, 2171 | }, 2172 | Insert { 2173 | pos: 123, 2174 | content: 123, 2175 | }, 2176 | Insert { 2177 | pos: 123, 2178 | content: 123, 2179 | }, 2180 | Insert { 2181 | pos: 0, 2182 | content: 123, 2183 | }, 2184 | Delete { pos: 238, len: 238 }, 2185 | Delete { pos: 238, len: 238 }, 2186 | Delete { pos: 91, len: 238 }, 2187 | Delete { pos: 238, len: 238 }, 2188 | Delete { pos: 238, len: 238 }, 2189 | Delete { pos: 238, len: 238 }, 2190 | Delete { pos: 238, len: 123 }, 2191 | Delete { pos: 238, len: 238 }, 2192 | Insert { 2193 | pos: 121, 2194 | content: 86, 2195 | }, 2196 | Insert { 2197 | pos: 123, 2198 | content: 123, 2199 | }, 2200 | Delete { pos: 238, len: 238 }, 2201 | Delete { pos: 238, len: 238 }, 2202 | Insert { 2203 | pos: 123, 2204 | content: 123, 2205 | }, 2206 | Insert { 2207 | pos: 86, 2208 | content: 86, 2209 | }, 2210 | Insert { 2211 | pos: 202, 2212 | content: 238, 2213 | }, 2214 | Delete { pos: 238, len: 238 }, 2215 | Insert { 2216 | pos: 123, 2217 | content: 2, 2218 | }, 2219 | Insert { 2220 | pos: 254, 2221 | content: 123, 2222 | }, 2223 | Insert { pos: 0, content: 0 }, 2224 | Insert { 2225 | pos: 123, 2226 | content: 123, 2227 | }, 2228 | Delete { pos: 238, len: 238 }, 2229 | Delete { pos: 255, len: 101 }, 2230 | Delete { pos: 238, len: 238 }, 2231 | Delete { pos: 238, len: 238 }, 2232 | Insert { 2233 | pos: 238, 2234 | content: 123, 2235 | }, 2236 | Delete { pos: 123, len: 238 }, 2237 | Delete { pos: 238, len: 238 }, 2238 | Insert { 2239 | pos: 123, 2240 | content: 123, 2241 | }, 2242 | Insert { 2243 | pos: 102, 2244 | content: 102, 2245 | }, 2246 | Insert { 2247 | pos: 102, 2248 | content: 102, 2249 | }, 2250 | Insert { 2251 | pos: 102, 2252 | content: 123, 2253 | }, 2254 | Insert { 2255 | pos: 238, 2256 | content: 238, 2257 | }, 2258 | Delete { pos: 238, len: 238 }, 2259 | Insert { 2260 | pos: 123, 2261 | content: 123, 2262 | }, 2263 | Insert { 2264 | pos: 123, 2265 | content: 123, 2266 | }, 2267 | Insert { 2268 | pos: 123, 2269 | content: 123, 2270 | }, 2271 | Insert { 2272 | pos: 123, 2273 | content: 123, 2274 | }, 2275 | Delete { pos: 255, len: 255 }, 2276 | Delete { pos: 238, len: 238 }, 2277 | Delete { pos: 238, len: 238 }, 2278 | Delete { pos: 1, len: 0 }, 2279 | Insert { pos: 0, content: 7 }, 2280 | Insert { 2281 | pos: 108, 2282 | content: 108, 2283 | }, 2284 | Insert { pos: 0, content: 0 }, 2285 | Insert { 2286 | pos: 108, 2287 | content: 108, 2288 | }, 2289 | Delete { pos: 171, len: 171 }, 2290 | Delete { pos: 171, len: 171 }, 2291 | Delete { pos: 171, len: 171 }, 2292 | Delete { pos: 171, len: 171 }, 2293 | Delete { pos: 171, len: 171 }, 2294 | Delete { pos: 171, len: 171 }, 2295 | Delete { pos: 171, len: 108 }, 2296 | Insert { 2297 | pos: 108, 2298 | content: 108, 2299 | }, 2300 | Insert { pos: 0, content: 0 }, 2301 | Insert { 2302 | pos: 235, 2303 | content: 235, 2304 | }, 2305 | Insert { 2306 | pos: 108, 2307 | content: 108, 2308 | }, 2309 | Insert { pos: 0, content: 0 }, 2310 | Insert { 2311 | pos: 111, 2312 | content: 111, 2313 | }, 2314 | Delete { pos: 154, len: 171 }, 2315 | Delete { pos: 171, len: 171 }, 2316 | Delete { pos: 171, len: 171 }, 2317 | Delete { pos: 171, len: 171 }, 2318 | Insert { 2319 | pos: 171, 2320 | content: 8, 2321 | }, 2322 | Delete { pos: 171, len: 249 }, 2323 | Insert { 2324 | pos: 135, 2325 | content: 169, 2326 | }, 2327 | Delete { pos: 171, len: 171 }, 2328 | Delete { pos: 171, len: 171 }, 2329 | Insert { 2330 | pos: 87, 2331 | content: 84, 2332 | }, 2333 | Delete { pos: 171, len: 171 }, 2334 | Delete { pos: 171, len: 171 }, 2335 | Delete { pos: 171, len: 171 }, 2336 | Delete { pos: 171, len: 171 }, 2337 | Delete { pos: 238, len: 238 }, 2338 | Delete { pos: 11, len: 238 }, 2339 | Insert { pos: 0, content: 0 }, 2340 | Delete { pos: 41, len: 238 }, 2341 | Delete { pos: 238, len: 238 }, 2342 | Delete { pos: 238, len: 238 }, 2343 | Delete { pos: 238, len: 238 }, 2344 | Delete { pos: 238, len: 238 }, 2345 | Delete { pos: 238, len: 238 }, 2346 | Delete { pos: 171, len: 0 }, 2347 | Insert { 2348 | pos: 108, 2349 | content: 108, 2350 | }, 2351 | Insert { pos: 0, content: 0 }, 2352 | Insert { 2353 | pos: 0, 2354 | content: 108, 2355 | }, 2356 | Delete { pos: 63, len: 171 }, 2357 | Delete { pos: 171, len: 171 }, 2358 | Delete { pos: 171, len: 171 }, 2359 | Delete { pos: 171, len: 171 }, 2360 | Delete { pos: 157, len: 157 }, 2361 | Delete { pos: 171, len: 171 }, 2362 | Delete { pos: 171, len: 171 }, 2363 | Delete { pos: 108, len: 0 }, 2364 | Insert { 2365 | pos: 108, 2366 | content: 108, 2367 | }, 2368 | Insert { pos: 0, content: 0 }, 2369 | Delete { pos: 235, len: 235 }, 2370 | Insert { 2371 | pos: 108, 2372 | content: 108, 2373 | }, 2374 | Insert { 2375 | pos: 0, 2376 | content: 248, 2377 | }, 2378 | Delete { pos: 154, len: 127 }, 2379 | Delete { pos: 171, len: 171 }, 2380 | Delete { pos: 171, len: 0 }, 2381 | Delete { pos: 171, len: 171 }, 2382 | Delete { pos: 171, len: 171 }, 2383 | Delete { pos: 8, len: 0 }, 2384 | Delete { pos: 249, len: 1 }, 2385 | Delete { pos: 169, len: 235 }, 2386 | Delete { pos: 171, len: 171 }, 2387 | Delete { pos: 171, len: 171 }, 2388 | Insert { 2389 | pos: 84, 2390 | content: 84, 2391 | }, 2392 | Delete { pos: 171, len: 171 }, 2393 | Delete { pos: 171, len: 171 }, 2394 | Delete { pos: 171, len: 171 }, 2395 | Delete { pos: 171, len: 171 }, 2396 | Delete { pos: 171, len: 171 }, 2397 | Insert { pos: 0, content: 8 }, 2398 | Insert { 2399 | pos: 108, 2400 | content: 108, 2401 | }, 2402 | Insert { 2403 | pos: 108, 2404 | content: 49, 2405 | }, 2406 | Delete { pos: 235, len: 108 }, 2407 | Insert { 2408 | pos: 108, 2409 | content: 108, 2410 | }, 2411 | Insert { 2412 | pos: 0, 2413 | content: 249, 2414 | }, 2415 | Insert { 2416 | pos: 135, 2417 | content: 169, 2418 | }, 2419 | Delete { pos: 238, len: 123 }, 2420 | Insert { pos: 2, content: 0 }, 2421 | Insert { pos: 0, content: 0 }, 2422 | Insert { 2423 | pos: 121, 2424 | content: 86, 2425 | }, 2426 | Insert { 2427 | pos: 123, 2428 | content: 123, 2429 | }, 2430 | Insert { 2431 | pos: 123, 2432 | content: 123, 2433 | }, 2434 | Insert { 2435 | pos: 123, 2436 | content: 123, 2437 | }, 2438 | Insert { 2439 | pos: 123, 2440 | content: 1, 2441 | }, 2442 | Delete { pos: 238, len: 238 }, 2443 | Insert { 2444 | pos: 238, 2445 | content: 238, 2446 | }, 2447 | Delete { pos: 238, len: 238 }, 2448 | Insert { 2449 | pos: 193, 2450 | content: 192, 2451 | }, 2452 | Delete { pos: 63, len: 127 }, 2453 | Insert { 2454 | pos: 0, 2455 | content: 235, 2456 | }, 2457 | Insert { 2458 | pos: 108, 2459 | content: 108, 2460 | }, 2461 | Insert { 2462 | pos: 87, 2463 | content: 0, 2464 | }, 2465 | Delete { pos: 1, len: 111 }, 2466 | Delete { pos: 235, len: 154 }, 2467 | Delete { pos: 171, len: 171 }, 2468 | Delete { pos: 171, len: 171 }, 2469 | Delete { pos: 171, len: 171 }, 2470 | Delete { pos: 0, len: 171 }, 2471 | Delete { pos: 171, len: 171 }, 2472 | Insert { 2473 | pos: 127, 2474 | content: 135, 2475 | }, 2476 | Delete { pos: 171, len: 171 }, 2477 | Delete { pos: 171, len: 171 }, 2478 | Delete { pos: 171, len: 171 }, 2479 | Delete { pos: 171, len: 171 }, 2480 | Insert { pos: 0, content: 0 }, 2481 | Insert { 2482 | pos: 108, 2483 | content: 108, 2484 | }, 2485 | Insert { 2486 | pos: 108, 2487 | content: 108, 2488 | }, 2489 | Delete { pos: 235, len: 235 }, 2490 | Insert { 2491 | pos: 108, 2492 | content: 108, 2493 | }, 2494 | Insert { pos: 0, content: 0 }, 2495 | Insert { 2496 | pos: 127, 2497 | content: 135, 2498 | }, 2499 | Delete { pos: 171, len: 171 }, 2500 | Delete { pos: 171, len: 172 }, 2501 | Delete { pos: 171, len: 171 }, 2502 | Delete { pos: 171, len: 171 }, 2503 | Delete { pos: 171, len: 0 }, 2504 | Insert { pos: 0, content: 0 }, 2505 | Insert { 2506 | pos: 0, 2507 | content: 171, 2508 | }, 2509 | Delete { pos: 171, len: 171 }, 2510 | Delete { pos: 171, len: 171 }, 2511 | Delete { pos: 171, len: 171 }, 2512 | Delete { pos: 171, len: 171 }, 2513 | Delete { pos: 171, len: 171 }, 2514 | Delete { pos: 171, len: 171 }, 2515 | Delete { pos: 171, len: 171 }, 2516 | Delete { pos: 171, len: 171 }, 2517 | Delete { pos: 171, len: 171 }, 2518 | Delete { pos: 171, len: 171 }, 2519 | Delete { pos: 171, len: 108 }, 2520 | Insert { 2521 | pos: 108, 2522 | content: 108, 2523 | }, 2524 | Insert { 2525 | pos: 108, 2526 | content: 108, 2527 | }, 2528 | Insert { 2529 | pos: 235, 2530 | content: 235, 2531 | }, 2532 | Insert { 2533 | pos: 108, 2534 | content: 108, 2535 | }, 2536 | Insert { pos: 0, content: 0 }, 2537 | Insert { 2538 | pos: 111, 2539 | content: 111, 2540 | }, 2541 | Delete { pos: 171, len: 0 }, 2542 | Insert { 2543 | pos: 48, 2544 | content: 111, 2545 | }, 2546 | Delete { pos: 154, len: 171 }, 2547 | Delete { pos: 171, len: 171 }, 2548 | Delete { pos: 171, len: 171 }, 2549 | Delete { pos: 171, len: 171 }, 2550 | Delete { pos: 171, len: 171 }, 2551 | Delete { pos: 171, len: 171 }, 2552 | Insert { 2553 | pos: 84, 2554 | content: 84, 2555 | }, 2556 | Delete { pos: 171, len: 171 }, 2557 | Delete { pos: 171, len: 171 }, 2558 | Delete { pos: 171, len: 171 }, 2559 | Delete { pos: 171, len: 171 }, 2560 | Delete { pos: 171, len: 171 }, 2561 | Delete { pos: 171, len: 171 }, 2562 | Delete { pos: 171, len: 171 }, 2563 | Delete { pos: 171, len: 235 }, 2564 | Delete { pos: 254, len: 86 }, 2565 | Insert { 2566 | pos: 108, 2567 | content: 108, 2568 | }, 2569 | Insert { 2570 | pos: 108, 2571 | content: 108, 2572 | }, 2573 | Insert { pos: 0, content: 8 }, 2574 | Insert { 2575 | pos: 108, 2576 | content: 171, 2577 | }, 2578 | Delete { pos: 171, len: 171 }, 2579 | Delete { pos: 171, len: 20 }, 2580 | Delete { pos: 171, len: 108 }, 2581 | Insert { 2582 | pos: 108, 2583 | content: 108, 2584 | }, 2585 | Insert { 2586 | pos: 108, 2587 | content: 108, 2588 | }, 2589 | Insert { 2590 | pos: 235, 2591 | content: 235, 2592 | }, 2593 | Insert { 2594 | pos: 108, 2595 | content: 108, 2596 | }, 2597 | Insert { pos: 0, content: 0 }, 2598 | Insert { 2599 | pos: 111, 2600 | content: 111, 2601 | }, 2602 | Delete { pos: 154, len: 171 }, 2603 | Delete { pos: 171, len: 171 }, 2604 | Delete { pos: 171, len: 171 }, 2605 | Delete { pos: 123, len: 123 }, 2606 | Insert { 2607 | pos: 86, 2608 | content: 86, 2609 | }, 2610 | Insert { 2611 | pos: 123, 2612 | content: 123, 2613 | }, 2614 | Insert { 2615 | pos: 123, 2616 | content: 123, 2617 | }, 2618 | Insert { 2619 | pos: 123, 2620 | content: 238, 2621 | }, 2622 | Delete { pos: 238, len: 238 }, 2623 | Insert { 2624 | pos: 123, 2625 | content: 36, 2626 | }, 2627 | Insert { 2628 | pos: 123, 2629 | content: 123, 2630 | }, 2631 | Insert { 2632 | pos: 123, 2633 | content: 123, 2634 | }, 2635 | Insert { 2636 | pos: 123, 2637 | content: 123, 2638 | }, 2639 | Insert { 2640 | pos: 254, 2641 | content: 255, 2642 | }, 2643 | Delete { pos: 238, len: 238 }, 2644 | Delete { pos: 238, len: 238 }, 2645 | Delete { pos: 238, len: 238 }, 2646 | Delete { pos: 238, len: 123 }, 2647 | Insert { pos: 0, content: 0 }, 2648 | Insert { pos: 0, content: 0 }, 2649 | Delete { pos: 238, len: 238 }, 2650 | Delete { pos: 238, len: 238 }, 2651 | Delete { pos: 238, len: 238 }, 2652 | Delete { pos: 123, len: 123 }, 2653 | Insert { 2654 | pos: 238, 2655 | content: 238, 2656 | }, 2657 | Delete { pos: 238, len: 238 }, 2658 | Delete { pos: 238, len: 238 }, 2659 | Insert { 2660 | pos: 238, 2661 | content: 238, 2662 | }, 2663 | Insert { pos: 0, content: 0 }, 2664 | Delete { pos: 91, len: 238 }, 2665 | Delete { pos: 238, len: 238 }, 2666 | Delete { pos: 238, len: 238 }, 2667 | Delete { pos: 238, len: 238 }, 2668 | Insert { pos: 0, content: 0 }, 2669 | Delete { pos: 238, len: 238 }, 2670 | Delete { pos: 238, len: 238 }, 2671 | Insert { pos: 0, content: 0 }, 2672 | Insert { 2673 | pos: 238, 2674 | content: 238, 2675 | }, 2676 | Insert { 2677 | pos: 108, 2678 | content: 108, 2679 | }, 2680 | Delete { pos: 238, len: 238 }, 2681 | Delete { pos: 238, len: 238 }, 2682 | Insert { 2683 | pos: 123, 2684 | content: 2, 2685 | }, 2686 | Insert { pos: 0, content: 0 }, 2687 | Insert { 2688 | pos: 238, 2689 | content: 238, 2690 | }, 2691 | Insert { 2692 | pos: 0, 2693 | content: 238, 2694 | }, 2695 | Delete { pos: 238, len: 238 }, 2696 | Delete { pos: 0, len: 249 }, 2697 | Insert { 2698 | pos: 135, 2699 | content: 255, 2700 | }, 2701 | Delete { pos: 255, len: 255 }, 2702 | Delete { pos: 144, len: 255 }, 2703 | Delete { pos: 169, len: 169 }, 2704 | ]) 2705 | } 2706 | 2707 | #[test] 2708 | fn ben() { 2709 | use arbitrary::Arbitrary; 2710 | #[derive(Arbitrary, Debug, Clone, Copy)] 2711 | enum Action { 2712 | Insert { pos: u8, content: u8 }, 2713 | Delete { pos: u8, len: u8 }, 2714 | } 2715 | 2716 | use rand::{Rng, SeedableRng}; 2717 | let mut rng = rand::rngs::StdRng::seed_from_u64(123); 2718 | let mut expected = String::new(); 2719 | let unstructured: Vec = (0..10_000).map(|_| rng.gen()).collect(); 2720 | let mut gen = arbitrary::Unstructured::new(&unstructured); 2721 | let actions: [Action; 1_000] = gen.arbitrary().unwrap(); 2722 | let mut rope = Rope::new(); 2723 | for action in actions.iter() { 2724 | match *action { 2725 | Action::Insert { pos, content } => { 2726 | let pos = pos as usize % (rope.len() + 1); 2727 | let s = content.to_string(); 2728 | expected.insert_str(pos, &s); 2729 | rope.insert(pos, &s); 2730 | assert_eq!(expected.len(), rope.len()); 2731 | } 2732 | Action::Delete { pos, len } => { 2733 | let pos = pos as usize % (rope.len() + 1); 2734 | let mut len = len as usize % 10; 2735 | len = len.min(rope.len() - pos); 2736 | expected.drain(pos..pos + len); 2737 | rope.delete_range(pos..(pos + len)); 2738 | assert_eq!(expected.len(), rope.len()); 2739 | } 2740 | } 2741 | } 2742 | assert_eq!(rope.to_string(), expected); 2743 | } 2744 | 2745 | #[test] 2746 | fn fuzz_7() { 2747 | fuzz(vec![ 2748 | Insert { 2749 | pos: 111, 2750 | content: 111, 2751 | }, 2752 | Insert { pos: 0, content: 0 }, 2753 | Insert { pos: 0, content: 0 }, 2754 | Insert { pos: 0, content: 0 }, 2755 | Insert { pos: 0, content: 0 }, 2756 | Insert { pos: 0, content: 0 }, 2757 | Insert { 2758 | pos: 108, 2759 | content: 108, 2760 | }, 2761 | Insert { 2762 | pos: 108, 2763 | content: 108, 2764 | }, 2765 | Insert { 2766 | pos: 108, 2767 | content: 255, 2768 | }, 2769 | Delete { pos: 255, len: 0 }, 2770 | Insert { 2771 | pos: 140, 2772 | content: 140, 2773 | }, 2774 | Insert { 2775 | pos: 102, 2776 | content: 101, 2777 | }, 2778 | Insert { 2779 | pos: 36, 2780 | content: 146, 2781 | }, 2782 | Insert { 2783 | pos: 102, 2784 | content: 119, 2785 | }, 2786 | Insert { 2787 | pos: 118, 2788 | content: 119, 2789 | }, 2790 | Insert { 2791 | pos: 119, 2792 | content: 119, 2793 | }, 2794 | Insert { 2795 | pos: 21, 2796 | content: 0, 2797 | }, 2798 | Insert { 2799 | pos: 140, 2800 | content: 140, 2801 | }, 2802 | Insert { 2803 | pos: 107, 2804 | content: 19, 2805 | }, 2806 | Insert { 2807 | pos: 102, 2808 | content: 47, 2809 | }, 2810 | Insert { pos: 0, content: 0 }, 2811 | Insert { 2812 | pos: 0, 2813 | content: 102, 2814 | }, 2815 | Insert { pos: 0, content: 0 }, 2816 | Insert { 2817 | pos: 0, 2818 | content: 102, 2819 | }, 2820 | Insert { 2821 | pos: 102, 2822 | content: 64, 2823 | }, 2824 | Insert { 2825 | pos: 64, 2826 | content: 64, 2827 | }, 2828 | Insert { 2829 | pos: 64, 2830 | content: 64, 2831 | }, 2832 | Insert { 2833 | pos: 64, 2834 | content: 64, 2835 | }, 2836 | Insert { 2837 | pos: 64, 2838 | content: 64, 2839 | }, 2840 | Insert { 2841 | pos: 64, 2842 | content: 64, 2843 | }, 2844 | Insert { 2845 | pos: 64, 2846 | content: 64, 2847 | }, 2848 | Insert { 2849 | pos: 123, 2850 | content: 123, 2851 | }, 2852 | Delete { pos: 255, len: 136 }, 2853 | Delete { pos: 119, len: 111 }, 2854 | Insert { 2855 | pos: 102, 2856 | content: 102, 2857 | }, 2858 | Insert { 2859 | pos: 3, 2860 | content: 73, 2861 | }, 2862 | Insert { 2863 | pos: 146, 2864 | content: 74, 2865 | }, 2866 | Delete { pos: 255, len: 255 }, 2867 | Delete { pos: 0, len: 102 }, 2868 | Insert { 2869 | pos: 102, 2870 | content: 102, 2871 | }, 2872 | Insert { 2873 | pos: 102, 2874 | content: 102, 2875 | }, 2876 | Insert { 2877 | pos: 119, 2878 | content: 119, 2879 | }, 2880 | Insert { 2881 | pos: 119, 2882 | content: 119, 2883 | }, 2884 | Insert { pos: 0, content: 0 }, 2885 | Delete { pos: 255, len: 255 }, 2886 | Insert { pos: 0, content: 0 }, 2887 | Insert { 2888 | pos: 0, 2889 | content: 255, 2890 | }, 2891 | Delete { pos: 111, len: 108 }, 2892 | Insert { 2893 | pos: 119, 2894 | content: 119, 2895 | }, 2896 | Insert { 2897 | pos: 119, 2898 | content: 119, 2899 | }, 2900 | Insert { 2901 | pos: 119, 2902 | content: 119, 2903 | }, 2904 | Insert { 2905 | pos: 102, 2906 | content: 102, 2907 | }, 2908 | Insert { 2909 | pos: 83, 2910 | content: 108, 2911 | }, 2912 | Insert { 2913 | pos: 111, 2914 | content: 111, 2915 | }, 2916 | Insert { 2917 | pos: 119, 2918 | content: 21, 2919 | }, 2920 | Insert { 2921 | pos: 119, 2922 | content: 119, 2923 | }, 2924 | Insert { 2925 | pos: 64, 2926 | content: 64, 2927 | }, 2928 | Insert { 2929 | pos: 64, 2930 | content: 64, 2931 | }, 2932 | Insert { 2933 | pos: 64, 2934 | content: 64, 2935 | }, 2936 | Insert { 2937 | pos: 55, 2938 | content: 119, 2939 | }, 2940 | Insert { 2941 | pos: 119, 2942 | content: 119, 2943 | }, 2944 | Insert { pos: 0, content: 0 }, 2945 | Insert { 2946 | pos: 119, 2947 | content: 119, 2948 | }, 2949 | Insert { 2950 | pos: 123, 2951 | content: 123, 2952 | }, 2953 | Insert { 2954 | pos: 121, 2955 | content: 86, 2956 | }, 2957 | Insert { 2958 | pos: 123, 2959 | content: 123, 2960 | }, 2961 | Insert { 2962 | pos: 125, 2963 | content: 125, 2964 | }, 2965 | Insert { 2966 | pos: 125, 2967 | content: 125, 2968 | }, 2969 | Insert { 2970 | pos: 125, 2971 | content: 125, 2972 | }, 2973 | Insert { 2974 | pos: 125, 2975 | content: 125, 2976 | }, 2977 | Insert { 2978 | pos: 125, 2979 | content: 125, 2980 | }, 2981 | Insert { 2982 | pos: 125, 2983 | content: 125, 2984 | }, 2985 | Insert { 2986 | pos: 125, 2987 | content: 125, 2988 | }, 2989 | Insert { 2990 | pos: 125, 2991 | content: 125, 2992 | }, 2993 | Insert { 2994 | pos: 125, 2995 | content: 125, 2996 | }, 2997 | Insert { 2998 | pos: 125, 2999 | content: 125, 3000 | }, 3001 | Insert { 3002 | pos: 125, 3003 | content: 125, 3004 | }, 3005 | Insert { 3006 | pos: 125, 3007 | content: 125, 3008 | }, 3009 | Insert { 3010 | pos: 125, 3011 | content: 125, 3012 | }, 3013 | Insert { 3014 | pos: 125, 3015 | content: 125, 3016 | }, 3017 | Insert { 3018 | pos: 125, 3019 | content: 125, 3020 | }, 3021 | Delete { pos: 130, len: 130 }, 3022 | Insert { 3023 | pos: 125, 3024 | content: 125, 3025 | }, 3026 | Insert { 3027 | pos: 125, 3028 | content: 125, 3029 | }, 3030 | Insert { 3031 | pos: 125, 3032 | content: 125, 3033 | }, 3034 | Insert { 3035 | pos: 123, 3036 | content: 123, 3037 | }, 3038 | Insert { 3039 | pos: 123, 3040 | content: 123, 3041 | }, 3042 | Insert { 3043 | pos: 119, 3044 | content: 119, 3045 | }, 3046 | Insert { 3047 | pos: 96, 3048 | content: 102, 3049 | }, 3050 | Insert { 3051 | pos: 119, 3052 | content: 119, 3053 | }, 3054 | Insert { 3055 | pos: 156, 3056 | content: 111, 3057 | }, 3058 | Insert { 3059 | pos: 123, 3060 | content: 37, 3061 | }, 3062 | Insert { 3063 | pos: 123, 3064 | content: 123, 3065 | }, 3066 | Insert { 3067 | pos: 123, 3068 | content: 123, 3069 | }, 3070 | Insert { 3071 | pos: 37, 3072 | content: 121, 3073 | }, 3074 | Insert { 3075 | pos: 123, 3076 | content: 123, 3077 | }, 3078 | Insert { 3079 | pos: 125, 3080 | content: 125, 3081 | }, 3082 | Insert { 3083 | pos: 125, 3084 | content: 125, 3085 | }, 3086 | Insert { 3087 | pos: 125, 3088 | content: 125, 3089 | }, 3090 | Insert { 3091 | pos: 125, 3092 | content: 125, 3093 | }, 3094 | Insert { 3095 | pos: 125, 3096 | content: 125, 3097 | }, 3098 | Insert { 3099 | pos: 125, 3100 | content: 125, 3101 | }, 3102 | Insert { 3103 | pos: 125, 3104 | content: 125, 3105 | }, 3106 | Insert { 3107 | pos: 125, 3108 | content: 125, 3109 | }, 3110 | Insert { 3111 | pos: 125, 3112 | content: 125, 3113 | }, 3114 | Insert { 3115 | pos: 125, 3116 | content: 125, 3117 | }, 3118 | Insert { 3119 | pos: 123, 3120 | content: 123, 3121 | }, 3122 | Insert { 3123 | pos: 121, 3124 | content: 86, 3125 | }, 3126 | Insert { 3127 | pos: 123, 3128 | content: 123, 3129 | }, 3130 | Insert { 3131 | pos: 125, 3132 | content: 125, 3133 | }, 3134 | Insert { 3135 | pos: 125, 3136 | content: 125, 3137 | }, 3138 | Insert { 3139 | pos: 125, 3140 | content: 125, 3141 | }, 3142 | Insert { 3143 | pos: 125, 3144 | content: 125, 3145 | }, 3146 | Insert { 3147 | pos: 125, 3148 | content: 125, 3149 | }, 3150 | Insert { 3151 | pos: 125, 3152 | content: 125, 3153 | }, 3154 | Insert { 3155 | pos: 125, 3156 | content: 125, 3157 | }, 3158 | Insert { 3159 | pos: 125, 3160 | content: 125, 3161 | }, 3162 | Insert { 3163 | pos: 125, 3164 | content: 125, 3165 | }, 3166 | Insert { 3167 | pos: 125, 3168 | content: 125, 3169 | }, 3170 | Insert { 3171 | pos: 125, 3172 | content: 125, 3173 | }, 3174 | Insert { 3175 | pos: 125, 3176 | content: 125, 3177 | }, 3178 | Insert { 3179 | pos: 125, 3180 | content: 125, 3181 | }, 3182 | Insert { 3183 | pos: 125, 3184 | content: 125, 3185 | }, 3186 | Insert { 3187 | pos: 125, 3188 | content: 125, 3189 | }, 3190 | Insert { 3191 | pos: 125, 3192 | content: 125, 3193 | }, 3194 | Insert { 3195 | pos: 125, 3196 | content: 125, 3197 | }, 3198 | Insert { 3199 | pos: 125, 3200 | content: 125, 3201 | }, 3202 | Insert { 3203 | pos: 125, 3204 | content: 125, 3205 | }, 3206 | Insert { 3207 | pos: 125, 3208 | content: 125, 3209 | }, 3210 | Insert { 3211 | pos: 125, 3212 | content: 125, 3213 | }, 3214 | Insert { 3215 | pos: 125, 3216 | content: 125, 3217 | }, 3218 | Insert { 3219 | pos: 125, 3220 | content: 125, 3221 | }, 3222 | Insert { 3223 | pos: 125, 3224 | content: 125, 3225 | }, 3226 | Insert { 3227 | pos: 125, 3228 | content: 125, 3229 | }, 3230 | Insert { 3231 | pos: 125, 3232 | content: 123, 3233 | }, 3234 | Insert { 3235 | pos: 125, 3236 | content: 125, 3237 | }, 3238 | Insert { 3239 | pos: 125, 3240 | content: 125, 3241 | }, 3242 | Insert { 3243 | pos: 125, 3244 | content: 125, 3245 | }, 3246 | Insert { 3247 | pos: 125, 3248 | content: 125, 3249 | }, 3250 | Insert { 3251 | pos: 125, 3252 | content: 125, 3253 | }, 3254 | Insert { 3255 | pos: 125, 3256 | content: 125, 3257 | }, 3258 | Insert { 3259 | pos: 125, 3260 | content: 125, 3261 | }, 3262 | Insert { 3263 | pos: 125, 3264 | content: 125, 3265 | }, 3266 | Delete { pos: 239, len: 239 }, 3267 | Insert { 3268 | pos: 125, 3269 | content: 125, 3270 | }, 3271 | Insert { 3272 | pos: 125, 3273 | content: 125, 3274 | }, 3275 | Insert { 3276 | pos: 125, 3277 | content: 125, 3278 | }, 3279 | Insert { 3280 | pos: 125, 3281 | content: 125, 3282 | }, 3283 | Insert { 3284 | pos: 125, 3285 | content: 125, 3286 | }, 3287 | Insert { 3288 | pos: 125, 3289 | content: 125, 3290 | }, 3291 | Insert { 3292 | pos: 125, 3293 | content: 125, 3294 | }, 3295 | Insert { 3296 | pos: 125, 3297 | content: 125, 3298 | }, 3299 | Insert { 3300 | pos: 125, 3301 | content: 125, 3302 | }, 3303 | Insert { 3304 | pos: 125, 3305 | content: 125, 3306 | }, 3307 | Insert { 3308 | pos: 125, 3309 | content: 125, 3310 | }, 3311 | Insert { 3312 | pos: 125, 3313 | content: 125, 3314 | }, 3315 | Insert { 3316 | pos: 125, 3317 | content: 125, 3318 | }, 3319 | Insert { 3320 | pos: 125, 3321 | content: 125, 3322 | }, 3323 | Insert { 3324 | pos: 125, 3325 | content: 125, 3326 | }, 3327 | Insert { 3328 | pos: 125, 3329 | content: 125, 3330 | }, 3331 | Insert { 3332 | pos: 125, 3333 | content: 123, 3334 | }, 3335 | Insert { 3336 | pos: 123, 3337 | content: 123, 3338 | }, 3339 | Insert { 3340 | pos: 123, 3341 | content: 0, 3342 | }, 3343 | Delete { pos: 255, len: 255 }, 3344 | Delete { pos: 255, len: 255 }, 3345 | Delete { pos: 255, len: 255 }, 3346 | Delete { pos: 255, len: 255 }, 3347 | Delete { pos: 255, len: 255 }, 3348 | Delete { pos: 255, len: 255 }, 3349 | Delete { pos: 255, len: 255 }, 3350 | Delete { pos: 125, len: 125 }, 3351 | Insert { 3352 | pos: 125, 3353 | content: 125, 3354 | }, 3355 | Insert { 3356 | pos: 125, 3357 | content: 125, 3358 | }, 3359 | Insert { 3360 | pos: 125, 3361 | content: 125, 3362 | }, 3363 | Insert { 3364 | pos: 125, 3365 | content: 125, 3366 | }, 3367 | Insert { 3368 | pos: 123, 3369 | content: 123, 3370 | }, 3371 | Insert { 3372 | pos: 118, 3373 | content: 118, 3374 | }, 3375 | Insert { 3376 | pos: 255, 3377 | content: 255, 3378 | }, 3379 | Insert { 3380 | pos: 119, 3381 | content: 119, 3382 | }, 3383 | Insert { 3384 | pos: 102, 3385 | content: 102, 3386 | }, 3387 | Delete { pos: 209, len: 255 }, 3388 | Delete { pos: 255, len: 255 }, 3389 | ]) 3390 | } 3391 | 3392 | #[test] 3393 | fn from_str() { 3394 | for i in 0..100000 { 3395 | let s = i.to_string(); 3396 | let mut g = GapBuffer::from_str(&s); 3397 | assert_eq!(s.len(), g.next().unwrap().len()); 3398 | } 3399 | } 3400 | 3401 | #[test] 3402 | fn from_iter() { 3403 | let mut v = vec![]; 3404 | for i in 0..100000 { 3405 | v.push(i.to_string()); 3406 | } 3407 | 3408 | let rope = Rope { 3409 | tree: v 3410 | .iter() 3411 | .flat_map(|x| GapBuffer::from_str(x.as_str())) 3412 | .collect(), 3413 | cursor: None, 3414 | }; 3415 | 3416 | let s = v.join(""); 3417 | assert_eq!(rope.to_string(), s); 3418 | assert_eq!(rope.len(), s.len()); 3419 | rope.tree.check(); 3420 | } 3421 | 3422 | #[test] 3423 | fn drain() { 3424 | let mut rope = Rope::new(); 3425 | for i in 0..100000 { 3426 | rope.insert(0, &i.to_string()); 3427 | } 3428 | 3429 | while !rope.is_empty() { 3430 | let leaf = rope.tree.first_leaf(); 3431 | rope.tree.update_leaf(leaf.unwrap(), |elem| { 3432 | elem.slice_(1..1); 3433 | (true, None, None) 3434 | }); 3435 | } 3436 | } 3437 | 3438 | #[test] 3439 | fn fuzz_empty() { 3440 | fuzz(vec![]) 3441 | } 3442 | } 3443 | --------------------------------------------------------------------------------