├── .editorconfig ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── benches ├── automerge-paper.json.gz ├── automerge.rs ├── bench_ord.rs ├── bench_rope.rs └── utils.rs ├── clippy.toml ├── examples └── rope.rs ├── fuzz ├── .gitignore ├── Cargo.lock ├── Cargo.toml └── fuzz_targets │ ├── ord.rs │ └── rope.rs ├── src ├── generic_impl │ ├── gap_buffer.rs │ ├── len_finder.rs │ ├── mod.rs │ ├── ord.rs │ └── rope.rs ├── iter.rs ├── lib.rs └── rle.rs └── tests ├── integration.rs └── range_num_map └── mod.rs /.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 | -------------------------------------------------------------------------------- /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 = "addr2line" 7 | version = "0.19.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 | dependencies = [ 26 | "cfg-if", 27 | "getrandom", 28 | "once_cell", 29 | "version_check", 30 | "zerocopy", 31 | ] 32 | 33 | [[package]] 34 | name = "anes" 35 | version = "0.1.6" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 38 | 39 | [[package]] 40 | name = "arbitrary" 41 | version = "1.2.3" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad" 44 | dependencies = [ 45 | "derive_arbitrary", 46 | ] 47 | 48 | [[package]] 49 | name = "arrayvec" 50 | version = "0.7.2" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 53 | 54 | [[package]] 55 | name = "arref" 56 | version = "0.1.0" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "2ccd462b64c3c72f1be8305905a85d85403d768e8690c9b8bd3b9009a5761679" 59 | 60 | [[package]] 61 | name = "atomic-polyfill" 62 | version = "0.1.11" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" 65 | dependencies = [ 66 | "critical-section", 67 | ] 68 | 69 | [[package]] 70 | name = "atty" 71 | version = "0.2.14" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 74 | dependencies = [ 75 | "hermit-abi 0.1.19", 76 | "libc", 77 | "winapi", 78 | ] 79 | 80 | [[package]] 81 | name = "autocfg" 82 | version = "1.1.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 85 | 86 | [[package]] 87 | name = "backtrace" 88 | version = "0.3.67" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" 91 | dependencies = [ 92 | "addr2line", 93 | "cc", 94 | "cfg-if", 95 | "libc", 96 | "miniz_oxide", 97 | "object", 98 | "rustc-demangle", 99 | ] 100 | 101 | [[package]] 102 | name = "bitflags" 103 | version = "1.3.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 106 | 107 | [[package]] 108 | name = "bumpalo" 109 | version = "3.12.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" 112 | 113 | [[package]] 114 | name = "bytemuck" 115 | version = "1.13.1" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" 118 | 119 | [[package]] 120 | name = "byteorder" 121 | version = "1.4.3" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 124 | 125 | [[package]] 126 | name = "cast" 127 | version = "0.3.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 130 | 131 | [[package]] 132 | name = "cc" 133 | version = "1.0.79" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 136 | 137 | [[package]] 138 | name = "cfg-if" 139 | version = "1.0.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 142 | 143 | [[package]] 144 | name = "ciborium" 145 | version = "0.2.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" 148 | dependencies = [ 149 | "ciborium-io", 150 | "ciborium-ll", 151 | "serde", 152 | ] 153 | 154 | [[package]] 155 | name = "ciborium-io" 156 | version = "0.2.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" 159 | 160 | [[package]] 161 | name = "ciborium-ll" 162 | version = "0.2.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" 165 | dependencies = [ 166 | "ciborium-io", 167 | "half", 168 | ] 169 | 170 | [[package]] 171 | name = "clap" 172 | version = "3.2.23" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" 175 | dependencies = [ 176 | "bitflags", 177 | "clap_lex", 178 | "indexmap", 179 | "textwrap", 180 | ] 181 | 182 | [[package]] 183 | name = "clap_lex" 184 | version = "0.2.4" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 187 | dependencies = [ 188 | "os_str_bytes", 189 | ] 190 | 191 | [[package]] 192 | name = "color-backtrace" 193 | version = "0.5.1" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "cd6c04463c99389fff045d2b90ce84f5131332712c7ffbede020f5e9ad1ed685" 196 | dependencies = [ 197 | "atty", 198 | "backtrace", 199 | "termcolor", 200 | ] 201 | 202 | [[package]] 203 | name = "cpp_demangle" 204 | version = "0.4.0" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442" 207 | dependencies = [ 208 | "cfg-if", 209 | ] 210 | 211 | [[package]] 212 | name = "crc32fast" 213 | version = "1.3.2" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 216 | dependencies = [ 217 | "cfg-if", 218 | ] 219 | 220 | [[package]] 221 | name = "criterion" 222 | version = "0.4.0" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" 225 | dependencies = [ 226 | "anes", 227 | "atty", 228 | "cast", 229 | "ciborium", 230 | "clap", 231 | "criterion-plot", 232 | "itertools 0.10.5", 233 | "lazy_static", 234 | "num-traits", 235 | "oorandom", 236 | "plotters", 237 | "rayon", 238 | "regex", 239 | "serde", 240 | "serde_derive", 241 | "serde_json", 242 | "tinytemplate", 243 | "walkdir", 244 | ] 245 | 246 | [[package]] 247 | name = "criterion-plot" 248 | version = "0.5.0" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" 251 | dependencies = [ 252 | "cast", 253 | "itertools 0.10.5", 254 | ] 255 | 256 | [[package]] 257 | name = "critical-section" 258 | version = "1.1.2" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 261 | 262 | [[package]] 263 | name = "crossbeam-channel" 264 | version = "0.5.6" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 267 | dependencies = [ 268 | "cfg-if", 269 | "crossbeam-utils", 270 | ] 271 | 272 | [[package]] 273 | name = "crossbeam-deque" 274 | version = "0.8.2" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" 277 | dependencies = [ 278 | "cfg-if", 279 | "crossbeam-epoch", 280 | "crossbeam-utils", 281 | ] 282 | 283 | [[package]] 284 | name = "crossbeam-epoch" 285 | version = "0.9.13" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" 288 | dependencies = [ 289 | "autocfg", 290 | "cfg-if", 291 | "crossbeam-utils", 292 | "memoffset", 293 | "scopeguard", 294 | ] 295 | 296 | [[package]] 297 | name = "crossbeam-utils" 298 | version = "0.8.14" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 301 | dependencies = [ 302 | "cfg-if", 303 | ] 304 | 305 | [[package]] 306 | name = "ctor" 307 | version = "0.1.26" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" 310 | dependencies = [ 311 | "quote", 312 | "syn 1.0.107", 313 | ] 314 | 315 | [[package]] 316 | name = "debugid" 317 | version = "0.8.0" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" 320 | dependencies = [ 321 | "uuid", 322 | ] 323 | 324 | [[package]] 325 | name = "derive_arbitrary" 326 | version = "1.2.3" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "8beee4701e2e229e8098bbdecdca12449bc3e322f137d269182fa1291e20bd00" 329 | dependencies = [ 330 | "proc-macro2", 331 | "quote", 332 | "syn 1.0.107", 333 | ] 334 | 335 | [[package]] 336 | name = "either" 337 | version = "1.8.1" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" 340 | 341 | [[package]] 342 | name = "errno" 343 | version = "0.2.8" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 346 | dependencies = [ 347 | "errno-dragonfly", 348 | "libc", 349 | "winapi", 350 | ] 351 | 352 | [[package]] 353 | name = "errno-dragonfly" 354 | version = "0.1.2" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 357 | dependencies = [ 358 | "cc", 359 | "libc", 360 | ] 361 | 362 | [[package]] 363 | name = "fastrand" 364 | version = "1.9.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 367 | dependencies = [ 368 | "instant", 369 | ] 370 | 371 | [[package]] 372 | name = "findshlibs" 373 | version = "0.10.2" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" 376 | dependencies = [ 377 | "cc", 378 | "lazy_static", 379 | "libc", 380 | "winapi", 381 | ] 382 | 383 | [[package]] 384 | name = "flate2" 385 | version = "1.0.25" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" 388 | dependencies = [ 389 | "crc32fast", 390 | "miniz_oxide", 391 | ] 392 | 393 | [[package]] 394 | name = "fxhash" 395 | version = "0.2.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 398 | dependencies = [ 399 | "byteorder", 400 | ] 401 | 402 | [[package]] 403 | name = "generic-btree" 404 | version = "0.10.5" 405 | dependencies = [ 406 | "ahash", 407 | "arbitrary", 408 | "arref", 409 | "color-backtrace", 410 | "criterion", 411 | "ctor", 412 | "flate2", 413 | "fxhash", 414 | "heapless", 415 | "itertools 0.11.0", 416 | "jumprope", 417 | "loro-thunderdome", 418 | "pprof", 419 | "proc-macro2", 420 | "rand", 421 | "serde_json", 422 | ] 423 | 424 | [[package]] 425 | name = "getrandom" 426 | version = "0.2.8" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 429 | dependencies = [ 430 | "cfg-if", 431 | "libc", 432 | "wasi", 433 | ] 434 | 435 | [[package]] 436 | name = "gimli" 437 | version = "0.27.2" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" 440 | 441 | [[package]] 442 | name = "half" 443 | version = "1.8.2" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" 446 | 447 | [[package]] 448 | name = "hash32" 449 | version = "0.2.1" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" 452 | dependencies = [ 453 | "byteorder", 454 | ] 455 | 456 | [[package]] 457 | name = "hashbrown" 458 | version = "0.12.3" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 461 | 462 | [[package]] 463 | name = "heapless" 464 | version = "0.7.16" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" 467 | dependencies = [ 468 | "atomic-polyfill", 469 | "hash32", 470 | "rustc_version", 471 | "spin", 472 | "stable_deref_trait", 473 | ] 474 | 475 | [[package]] 476 | name = "hermit-abi" 477 | version = "0.1.19" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 480 | dependencies = [ 481 | "libc", 482 | ] 483 | 484 | [[package]] 485 | name = "hermit-abi" 486 | version = "0.2.6" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 489 | dependencies = [ 490 | "libc", 491 | ] 492 | 493 | [[package]] 494 | name = "hermit-abi" 495 | version = "0.3.1" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 498 | 499 | [[package]] 500 | name = "indexmap" 501 | version = "1.9.2" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 504 | dependencies = [ 505 | "autocfg", 506 | "hashbrown", 507 | ] 508 | 509 | [[package]] 510 | name = "inferno" 511 | version = "0.11.15" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "2fb7c1b80a1dfa604bb4a649a5c5aeef3d913f7c520cb42b40e534e8a61bcdfc" 514 | dependencies = [ 515 | "ahash", 516 | "indexmap", 517 | "is-terminal", 518 | "itoa", 519 | "log", 520 | "num-format", 521 | "once_cell", 522 | "quick-xml", 523 | "rgb", 524 | "str_stack", 525 | ] 526 | 527 | [[package]] 528 | name = "instant" 529 | version = "0.1.12" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 532 | dependencies = [ 533 | "cfg-if", 534 | ] 535 | 536 | [[package]] 537 | name = "io-lifetimes" 538 | version = "1.0.5" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" 541 | dependencies = [ 542 | "libc", 543 | "windows-sys 0.45.0", 544 | ] 545 | 546 | [[package]] 547 | name = "is-terminal" 548 | version = "0.4.4" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" 551 | dependencies = [ 552 | "hermit-abi 0.3.1", 553 | "io-lifetimes", 554 | "rustix", 555 | "windows-sys 0.45.0", 556 | ] 557 | 558 | [[package]] 559 | name = "itertools" 560 | version = "0.10.5" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 563 | dependencies = [ 564 | "either", 565 | ] 566 | 567 | [[package]] 568 | name = "itertools" 569 | version = "0.11.0" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 572 | dependencies = [ 573 | "either", 574 | ] 575 | 576 | [[package]] 577 | name = "itoa" 578 | version = "1.0.5" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 581 | 582 | [[package]] 583 | name = "js-sys" 584 | version = "0.3.61" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" 587 | dependencies = [ 588 | "wasm-bindgen", 589 | ] 590 | 591 | [[package]] 592 | name = "jumprope" 593 | version = "1.1.1" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "76ff13229092ab69baa5e45e49e3ebf75637ca61061b5c233b7d2eb3e91855a2" 596 | dependencies = [ 597 | "rand", 598 | "str_indices", 599 | ] 600 | 601 | [[package]] 602 | name = "lazy_static" 603 | version = "1.4.0" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 606 | 607 | [[package]] 608 | name = "libc" 609 | version = "0.2.139" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 612 | 613 | [[package]] 614 | name = "linux-raw-sys" 615 | version = "0.1.4" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 618 | 619 | [[package]] 620 | name = "lock_api" 621 | version = "0.4.9" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 624 | dependencies = [ 625 | "autocfg", 626 | "scopeguard", 627 | ] 628 | 629 | [[package]] 630 | name = "log" 631 | version = "0.4.17" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 634 | dependencies = [ 635 | "cfg-if", 636 | ] 637 | 638 | [[package]] 639 | name = "loro-thunderdome" 640 | version = "0.6.2" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" 643 | 644 | [[package]] 645 | name = "memchr" 646 | version = "2.5.0" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 649 | 650 | [[package]] 651 | name = "memmap2" 652 | version = "0.5.10" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" 655 | dependencies = [ 656 | "libc", 657 | ] 658 | 659 | [[package]] 660 | name = "memoffset" 661 | version = "0.7.1" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" 664 | dependencies = [ 665 | "autocfg", 666 | ] 667 | 668 | [[package]] 669 | name = "miniz_oxide" 670 | version = "0.6.2" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 673 | dependencies = [ 674 | "adler", 675 | ] 676 | 677 | [[package]] 678 | name = "nix" 679 | version = "0.26.2" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" 682 | dependencies = [ 683 | "bitflags", 684 | "cfg-if", 685 | "libc", 686 | "static_assertions", 687 | ] 688 | 689 | [[package]] 690 | name = "num-format" 691 | version = "0.4.4" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" 694 | dependencies = [ 695 | "arrayvec", 696 | "itoa", 697 | ] 698 | 699 | [[package]] 700 | name = "num-traits" 701 | version = "0.2.15" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 704 | dependencies = [ 705 | "autocfg", 706 | ] 707 | 708 | [[package]] 709 | name = "num_cpus" 710 | version = "1.15.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 713 | dependencies = [ 714 | "hermit-abi 0.2.6", 715 | "libc", 716 | ] 717 | 718 | [[package]] 719 | name = "object" 720 | version = "0.30.3" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" 723 | dependencies = [ 724 | "memchr", 725 | ] 726 | 727 | [[package]] 728 | name = "once_cell" 729 | version = "1.19.0" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 732 | 733 | [[package]] 734 | name = "oorandom" 735 | version = "11.1.3" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" 738 | 739 | [[package]] 740 | name = "os_str_bytes" 741 | version = "6.4.1" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 744 | 745 | [[package]] 746 | name = "parking_lot" 747 | version = "0.12.1" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 750 | dependencies = [ 751 | "lock_api", 752 | "parking_lot_core", 753 | ] 754 | 755 | [[package]] 756 | name = "parking_lot_core" 757 | version = "0.9.7" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 760 | dependencies = [ 761 | "cfg-if", 762 | "libc", 763 | "redox_syscall", 764 | "smallvec", 765 | "windows-sys 0.45.0", 766 | ] 767 | 768 | [[package]] 769 | name = "plotters" 770 | version = "0.3.4" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" 773 | dependencies = [ 774 | "num-traits", 775 | "plotters-backend", 776 | "plotters-svg", 777 | "wasm-bindgen", 778 | "web-sys", 779 | ] 780 | 781 | [[package]] 782 | name = "plotters-backend" 783 | version = "0.3.4" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" 786 | 787 | [[package]] 788 | name = "plotters-svg" 789 | version = "0.3.3" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" 792 | dependencies = [ 793 | "plotters-backend", 794 | ] 795 | 796 | [[package]] 797 | name = "pprof" 798 | version = "0.11.1" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "196ded5d4be535690899a4631cc9f18cdc41b7ebf24a79400f46f48e49a11059" 801 | dependencies = [ 802 | "backtrace", 803 | "cfg-if", 804 | "criterion", 805 | "findshlibs", 806 | "inferno", 807 | "libc", 808 | "log", 809 | "nix", 810 | "once_cell", 811 | "parking_lot", 812 | "smallvec", 813 | "symbolic-demangle", 814 | "tempfile", 815 | "thiserror", 816 | ] 817 | 818 | [[package]] 819 | name = "ppv-lite86" 820 | version = "0.2.17" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 823 | 824 | [[package]] 825 | name = "proc-macro2" 826 | version = "1.0.67" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" 829 | dependencies = [ 830 | "unicode-ident", 831 | ] 832 | 833 | [[package]] 834 | name = "quick-xml" 835 | version = "0.26.0" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" 838 | dependencies = [ 839 | "memchr", 840 | ] 841 | 842 | [[package]] 843 | name = "quote" 844 | version = "1.0.33" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 847 | dependencies = [ 848 | "proc-macro2", 849 | ] 850 | 851 | [[package]] 852 | name = "rand" 853 | version = "0.8.5" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 856 | dependencies = [ 857 | "libc", 858 | "rand_chacha", 859 | "rand_core", 860 | ] 861 | 862 | [[package]] 863 | name = "rand_chacha" 864 | version = "0.3.1" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 867 | dependencies = [ 868 | "ppv-lite86", 869 | "rand_core", 870 | ] 871 | 872 | [[package]] 873 | name = "rand_core" 874 | version = "0.6.4" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 877 | dependencies = [ 878 | "getrandom", 879 | ] 880 | 881 | [[package]] 882 | name = "rayon" 883 | version = "1.6.1" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" 886 | dependencies = [ 887 | "either", 888 | "rayon-core", 889 | ] 890 | 891 | [[package]] 892 | name = "rayon-core" 893 | version = "1.10.2" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" 896 | dependencies = [ 897 | "crossbeam-channel", 898 | "crossbeam-deque", 899 | "crossbeam-utils", 900 | "num_cpus", 901 | ] 902 | 903 | [[package]] 904 | name = "redox_syscall" 905 | version = "0.2.16" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 908 | dependencies = [ 909 | "bitflags", 910 | ] 911 | 912 | [[package]] 913 | name = "regex" 914 | version = "1.7.1" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 917 | dependencies = [ 918 | "regex-syntax", 919 | ] 920 | 921 | [[package]] 922 | name = "regex-syntax" 923 | version = "0.6.28" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 926 | 927 | [[package]] 928 | name = "rgb" 929 | version = "0.8.36" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" 932 | dependencies = [ 933 | "bytemuck", 934 | ] 935 | 936 | [[package]] 937 | name = "rustc-demangle" 938 | version = "0.1.21" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 941 | 942 | [[package]] 943 | name = "rustc_version" 944 | version = "0.4.0" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 947 | dependencies = [ 948 | "semver", 949 | ] 950 | 951 | [[package]] 952 | name = "rustix" 953 | version = "0.36.8" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" 956 | dependencies = [ 957 | "bitflags", 958 | "errno", 959 | "io-lifetimes", 960 | "libc", 961 | "linux-raw-sys", 962 | "windows-sys 0.45.0", 963 | ] 964 | 965 | [[package]] 966 | name = "ryu" 967 | version = "1.0.12" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 970 | 971 | [[package]] 972 | name = "same-file" 973 | version = "1.0.6" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 976 | dependencies = [ 977 | "winapi-util", 978 | ] 979 | 980 | [[package]] 981 | name = "scopeguard" 982 | version = "1.1.0" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 985 | 986 | [[package]] 987 | name = "semver" 988 | version = "1.0.19" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" 991 | 992 | [[package]] 993 | name = "serde" 994 | version = "1.0.152" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 997 | dependencies = [ 998 | "serde_derive", 999 | ] 1000 | 1001 | [[package]] 1002 | name = "serde_derive" 1003 | version = "1.0.152" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 1006 | dependencies = [ 1007 | "proc-macro2", 1008 | "quote", 1009 | "syn 1.0.107", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "serde_json" 1014 | version = "1.0.93" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" 1017 | dependencies = [ 1018 | "itoa", 1019 | "ryu", 1020 | "serde", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "smallvec" 1025 | version = "1.10.0" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1028 | 1029 | [[package]] 1030 | name = "spin" 1031 | version = "0.9.8" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1034 | dependencies = [ 1035 | "lock_api", 1036 | ] 1037 | 1038 | [[package]] 1039 | name = "stable_deref_trait" 1040 | version = "1.2.0" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1043 | 1044 | [[package]] 1045 | name = "static_assertions" 1046 | version = "1.1.0" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1049 | 1050 | [[package]] 1051 | name = "str_indices" 1052 | version = "0.4.1" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd" 1055 | 1056 | [[package]] 1057 | name = "str_stack" 1058 | version = "0.1.0" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" 1061 | 1062 | [[package]] 1063 | name = "symbolic-common" 1064 | version = "10.2.1" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "1b55cdc318ede251d0957f07afe5fed912119b8c1bc5a7804151826db999e737" 1067 | dependencies = [ 1068 | "debugid", 1069 | "memmap2", 1070 | "stable_deref_trait", 1071 | "uuid", 1072 | ] 1073 | 1074 | [[package]] 1075 | name = "symbolic-demangle" 1076 | version = "10.2.1" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "79be897be8a483a81fff6a3a4e195b4ac838ef73ca42d348b3f722da9902e489" 1079 | dependencies = [ 1080 | "cpp_demangle", 1081 | "rustc-demangle", 1082 | "symbolic-common", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "syn" 1087 | version = "1.0.107" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 1090 | dependencies = [ 1091 | "proc-macro2", 1092 | "quote", 1093 | "unicode-ident", 1094 | ] 1095 | 1096 | [[package]] 1097 | name = "syn" 1098 | version = "2.0.43" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" 1101 | dependencies = [ 1102 | "proc-macro2", 1103 | "quote", 1104 | "unicode-ident", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "tempfile" 1109 | version = "3.4.0" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" 1112 | dependencies = [ 1113 | "cfg-if", 1114 | "fastrand", 1115 | "redox_syscall", 1116 | "rustix", 1117 | "windows-sys 0.42.0", 1118 | ] 1119 | 1120 | [[package]] 1121 | name = "termcolor" 1122 | version = "1.2.0" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 1125 | dependencies = [ 1126 | "winapi-util", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "textwrap" 1131 | version = "0.16.0" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" 1134 | 1135 | [[package]] 1136 | name = "thiserror" 1137 | version = "1.0.38" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 1140 | dependencies = [ 1141 | "thiserror-impl", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "thiserror-impl" 1146 | version = "1.0.38" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 1149 | dependencies = [ 1150 | "proc-macro2", 1151 | "quote", 1152 | "syn 1.0.107", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "tinytemplate" 1157 | version = "1.2.1" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 1160 | dependencies = [ 1161 | "serde", 1162 | "serde_json", 1163 | ] 1164 | 1165 | [[package]] 1166 | name = "unicode-ident" 1167 | version = "1.0.6" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1170 | 1171 | [[package]] 1172 | name = "uuid" 1173 | version = "1.3.0" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" 1176 | 1177 | [[package]] 1178 | name = "version_check" 1179 | version = "0.9.4" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1182 | 1183 | [[package]] 1184 | name = "walkdir" 1185 | version = "2.3.2" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" 1188 | dependencies = [ 1189 | "same-file", 1190 | "winapi", 1191 | "winapi-util", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "wasi" 1196 | version = "0.11.0+wasi-snapshot-preview1" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1199 | 1200 | [[package]] 1201 | name = "wasm-bindgen" 1202 | version = "0.2.84" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" 1205 | dependencies = [ 1206 | "cfg-if", 1207 | "wasm-bindgen-macro", 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "wasm-bindgen-backend" 1212 | version = "0.2.84" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" 1215 | dependencies = [ 1216 | "bumpalo", 1217 | "log", 1218 | "once_cell", 1219 | "proc-macro2", 1220 | "quote", 1221 | "syn 1.0.107", 1222 | "wasm-bindgen-shared", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "wasm-bindgen-macro" 1227 | version = "0.2.84" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" 1230 | dependencies = [ 1231 | "quote", 1232 | "wasm-bindgen-macro-support", 1233 | ] 1234 | 1235 | [[package]] 1236 | name = "wasm-bindgen-macro-support" 1237 | version = "0.2.84" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" 1240 | dependencies = [ 1241 | "proc-macro2", 1242 | "quote", 1243 | "syn 1.0.107", 1244 | "wasm-bindgen-backend", 1245 | "wasm-bindgen-shared", 1246 | ] 1247 | 1248 | [[package]] 1249 | name = "wasm-bindgen-shared" 1250 | version = "0.2.84" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" 1253 | 1254 | [[package]] 1255 | name = "web-sys" 1256 | version = "0.3.61" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" 1259 | dependencies = [ 1260 | "js-sys", 1261 | "wasm-bindgen", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "winapi" 1266 | version = "0.3.9" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1269 | dependencies = [ 1270 | "winapi-i686-pc-windows-gnu", 1271 | "winapi-x86_64-pc-windows-gnu", 1272 | ] 1273 | 1274 | [[package]] 1275 | name = "winapi-i686-pc-windows-gnu" 1276 | version = "0.4.0" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1279 | 1280 | [[package]] 1281 | name = "winapi-util" 1282 | version = "0.1.5" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1285 | dependencies = [ 1286 | "winapi", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "winapi-x86_64-pc-windows-gnu" 1291 | version = "0.4.0" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1294 | 1295 | [[package]] 1296 | name = "windows-sys" 1297 | version = "0.42.0" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1300 | dependencies = [ 1301 | "windows_aarch64_gnullvm", 1302 | "windows_aarch64_msvc", 1303 | "windows_i686_gnu", 1304 | "windows_i686_msvc", 1305 | "windows_x86_64_gnu", 1306 | "windows_x86_64_gnullvm", 1307 | "windows_x86_64_msvc", 1308 | ] 1309 | 1310 | [[package]] 1311 | name = "windows-sys" 1312 | version = "0.45.0" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1315 | dependencies = [ 1316 | "windows-targets", 1317 | ] 1318 | 1319 | [[package]] 1320 | name = "windows-targets" 1321 | version = "0.42.1" 1322 | source = "registry+https://github.com/rust-lang/crates.io-index" 1323 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 1324 | dependencies = [ 1325 | "windows_aarch64_gnullvm", 1326 | "windows_aarch64_msvc", 1327 | "windows_i686_gnu", 1328 | "windows_i686_msvc", 1329 | "windows_x86_64_gnu", 1330 | "windows_x86_64_gnullvm", 1331 | "windows_x86_64_msvc", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "windows_aarch64_gnullvm" 1336 | version = "0.42.1" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 1339 | 1340 | [[package]] 1341 | name = "windows_aarch64_msvc" 1342 | version = "0.42.1" 1343 | source = "registry+https://github.com/rust-lang/crates.io-index" 1344 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 1345 | 1346 | [[package]] 1347 | name = "windows_i686_gnu" 1348 | version = "0.42.1" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 1351 | 1352 | [[package]] 1353 | name = "windows_i686_msvc" 1354 | version = "0.42.1" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 1357 | 1358 | [[package]] 1359 | name = "windows_x86_64_gnu" 1360 | version = "0.42.1" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 1363 | 1364 | [[package]] 1365 | name = "windows_x86_64_gnullvm" 1366 | version = "0.42.1" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 1369 | 1370 | [[package]] 1371 | name = "windows_x86_64_msvc" 1372 | version = "0.42.1" 1373 | source = "registry+https://github.com/rust-lang/crates.io-index" 1374 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 1375 | 1376 | [[package]] 1377 | name = "zerocopy" 1378 | version = "0.7.32" 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" 1380 | checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" 1381 | dependencies = [ 1382 | "zerocopy-derive", 1383 | ] 1384 | 1385 | [[package]] 1386 | name = "zerocopy-derive" 1387 | version = "0.7.32" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" 1390 | dependencies = [ 1391 | "proc-macro2", 1392 | "quote", 1393 | "syn 2.0.43", 1394 | ] 1395 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generic-btree" 3 | author = "Zixuan Chen" 4 | version = "0.10.5" 5 | edition = "2021" 6 | description = "Generic BTree for versatile purposes" 7 | readme = "README.md" 8 | license = "MIT" 9 | homepage = "https://github.com/loro-dev/generic-btree" 10 | repository = "https://github.com/loro-dev/generic-btree" 11 | authors = ["zxch3n "] 12 | keywords = ["btree", "data-structure"] 13 | include = ["Cargo.toml", "/src/**/*.rs", "/benches/**/*.rs"] 14 | documentation = "https://docs.rs/generic-btree" 15 | 16 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 17 | 18 | [dependencies] 19 | arref = "0.1.0" 20 | fxhash = "0.2.1" 21 | heapless = "0.7.16" 22 | itertools = "0.11.0" 23 | proc-macro2 = "1.0.67" 24 | thunderdome = { version = "0.6.2", package = "loro-thunderdome" } 25 | 26 | 27 | [dev-dependencies] 28 | arbitrary = { version = "1.2.3", features = ["derive"] } 29 | criterion = "0.4.0" 30 | jumprope = "1.0.0" 31 | ahash = "0.8.11" 32 | rand = "0.8.5" 33 | color-backtrace = "0.5.1" 34 | ctor = "0.1.26" 35 | pprof = { version = "0.11.1", features = [ 36 | "flamegraph", 37 | "criterion", 38 | "frame-pointer", 39 | ] } 40 | serde_json = "1.0.93" 41 | flate2 = "1.0.25" 42 | 43 | 44 | [[bench]] 45 | name = "bench_ord" 46 | harness = false 47 | 48 | [[bench]] 49 | name = "bench_rope" 50 | harness = false 51 | 52 | [profile.release] 53 | debug = true 54 | 55 | [features] 56 | test = [] 57 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /benches/automerge-paper.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loro-dev/generic-btree/870b8e39a089a4e269f5de1738642e5c0848dd42/benches/automerge-paper.json.gz -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | disallowed-types = [] 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | artifacts 4 | coverage 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------