My personal-knowledge-system, with deeply integrated task tracking and long term goal planning capabilities.
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: added sakura

+2752 -28
+252 -10
Cargo.lock
··· 113 113 checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 114 114 115 115 [[package]] 116 + name = "automerge" 117 + version = "0.7.4" 118 + source = "registry+https://github.com/rust-lang/crates.io-index" 119 + checksum = "3f4f9b5e81602f033fac828dafb4fef91742f6f01adfdb8ee5b8bc804cfac7bb" 120 + dependencies = [ 121 + "cfg-if", 122 + "flate2", 123 + "getrandom 0.3.4", 124 + "hex", 125 + "hexane", 126 + "itertools", 127 + "leb128", 128 + "rand 0.9.2", 129 + "rustc-hash", 130 + "serde", 131 + "sha2 0.11.0-rc.5", 132 + "smol_str", 133 + "thiserror 2.0.18", 134 + "tinyvec", 135 + "tracing", 136 + "unicode-segmentation", 137 + ] 138 + 139 + [[package]] 140 + name = "autosurgeon" 141 + version = "0.10.1" 142 + source = "registry+https://github.com/rust-lang/crates.io-index" 143 + checksum = "87b6547a9a35fbf5e5b1305a56c42196ae2cfb456897f1cab97d4829f1096550" 144 + dependencies = [ 145 + "automerge", 146 + "autosurgeon-derive", 147 + "similar", 148 + "thiserror 1.0.69", 149 + ] 150 + 151 + [[package]] 152 + name = "autosurgeon-derive" 153 + version = "0.10.1" 154 + source = "registry+https://github.com/rust-lang/crates.io-index" 155 + checksum = "f99b54090e5aca6915313efcf065f9873c9ca9d39c875cfc956f30523075d49f" 156 + dependencies = [ 157 + "proc-macro2", 158 + "quote", 159 + "syn 2.0.117", 160 + "thiserror 1.0.69", 161 + ] 162 + 163 + [[package]] 116 164 name = "backtrace" 117 165 version = "0.3.76" 118 166 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 177 225 checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 178 226 dependencies = [ 179 227 "generic-array", 228 + ] 229 + 230 + [[package]] 231 + name = "block-buffer" 232 + version = "0.12.0" 233 + source = "registry+https://github.com/rust-lang/crates.io-index" 234 + checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" 235 + dependencies = [ 236 + "hybrid-array", 237 + ] 238 + 239 + [[package]] 240 + name = "borsh" 241 + version = "1.6.0" 242 + source = "registry+https://github.com/rust-lang/crates.io-index" 243 + checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" 244 + dependencies = [ 245 + "cfg_aliases", 180 246 ] 181 247 182 248 [[package]] ··· 380 446 ] 381 447 382 448 [[package]] 449 + name = "const-oid" 450 + version = "0.10.2" 451 + source = "registry+https://github.com/rust-lang/crates.io-index" 452 + checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" 453 + 454 + [[package]] 383 455 name = "convert_case" 384 456 version = "0.10.0" 385 457 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 451 523 ] 452 524 453 525 [[package]] 526 + name = "crypto-common" 527 + version = "0.2.1" 528 + source = "registry+https://github.com/rust-lang/crates.io-index" 529 + checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" 530 + dependencies = [ 531 + "hybrid-array", 532 + ] 533 + 534 + [[package]] 454 535 name = "csscolorparser" 455 536 version = "0.6.2" 456 537 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 544 625 ] 545 626 546 627 [[package]] 628 + name = "db" 629 + version = "0.1.0" 630 + 631 + [[package]] 547 632 name = "deltae" 548 633 version = "0.3.2" 549 634 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 617 702 source = "registry+https://github.com/rust-lang/crates.io-index" 618 703 checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 619 704 dependencies = [ 620 - "block-buffer", 621 - "crypto-common", 705 + "block-buffer 0.10.4", 706 + "crypto-common 0.1.7", 707 + ] 708 + 709 + [[package]] 710 + name = "digest" 711 + version = "0.11.2" 712 + source = "registry+https://github.com/rust-lang/crates.io-index" 713 + checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" 714 + dependencies = [ 715 + "block-buffer 0.12.0", 716 + "const-oid", 717 + "crypto-common 0.2.1", 622 718 ] 623 719 624 720 [[package]] ··· 797 893 version = "0.4.2" 798 894 source = "registry+https://github.com/rust-lang/crates.io-index" 799 895 checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 896 + 897 + [[package]] 898 + name = "flate2" 899 + version = "1.1.9" 900 + source = "registry+https://github.com/rust-lang/crates.io-index" 901 + checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" 902 + dependencies = [ 903 + "crc32fast", 904 + "miniz_oxide", 905 + ] 800 906 801 907 [[package]] 802 908 name = "fnv" ··· 1753 1859 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1754 1860 1755 1861 [[package]] 1862 + name = "hexane" 1863 + version = "0.1.7" 1864 + source = "registry+https://github.com/rust-lang/crates.io-index" 1865 + checksum = "8ab946df174dbf65fc07610c1f936b3e40b9ca7cfd09c0f827f9509a62e93a39" 1866 + dependencies = [ 1867 + "leb128", 1868 + "thiserror 2.0.18", 1869 + ] 1870 + 1871 + [[package]] 1756 1872 name = "human-panic" 1757 1873 version = "2.0.6" 1758 1874 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1766 1882 "sysinfo", 1767 1883 "toml", 1768 1884 "uuid", 1885 + ] 1886 + 1887 + [[package]] 1888 + name = "hybrid-array" 1889 + version = "0.4.8" 1890 + source = "registry+https://github.com/rust-lang/crates.io-index" 1891 + checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" 1892 + dependencies = [ 1893 + "typenum", 1769 1894 ] 1770 1895 1771 1896 [[package]] ··· 1945 2070 checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1946 2071 1947 2072 [[package]] 2073 + name = "leb128" 2074 + version = "0.2.5" 2075 + source = "registry+https://github.com/rust-lang/crates.io-index" 2076 + checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" 2077 + 2078 + [[package]] 1948 2079 name = "leb128fmt" 1949 2080 version = "0.1.0" 1950 2081 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2096 2227 checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 2097 2228 dependencies = [ 2098 2229 "adler2", 2230 + "simd-adler32", 2099 2231 ] 2100 2232 2101 2233 [[package]] ··· 2380 2512 checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" 2381 2513 dependencies = [ 2382 2514 "pest", 2383 - "sha2", 2515 + "sha2 0.10.9", 2384 2516 ] 2385 2517 2386 2518 [[package]] ··· 2410 2542 checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" 2411 2543 dependencies = [ 2412 2544 "phf_shared", 2413 - "rand", 2545 + "rand 0.8.5", 2414 2546 ] 2415 2547 2416 2548 [[package]] ··· 2469 2601 checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 2470 2602 2471 2603 [[package]] 2604 + name = "ppv-lite86" 2605 + version = "0.2.21" 2606 + source = "registry+https://github.com/rust-lang/crates.io-index" 2607 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 2608 + dependencies = [ 2609 + "zerocopy", 2610 + ] 2611 + 2612 + [[package]] 2472 2613 name = "prettyplease" 2473 2614 version = "0.2.37" 2474 2615 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2523 2664 source = "registry+https://github.com/rust-lang/crates.io-index" 2524 2665 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2525 2666 dependencies = [ 2526 - "rand_core", 2667 + "rand_core 0.6.4", 2668 + ] 2669 + 2670 + [[package]] 2671 + name = "rand" 2672 + version = "0.9.2" 2673 + source = "registry+https://github.com/rust-lang/crates.io-index" 2674 + checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" 2675 + dependencies = [ 2676 + "rand_chacha", 2677 + "rand_core 0.9.5", 2678 + ] 2679 + 2680 + [[package]] 2681 + name = "rand_chacha" 2682 + version = "0.9.0" 2683 + source = "registry+https://github.com/rust-lang/crates.io-index" 2684 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 2685 + dependencies = [ 2686 + "ppv-lite86", 2687 + "rand_core 0.9.5", 2527 2688 ] 2528 2689 2529 2690 [[package]] ··· 2531 2692 version = "0.6.4" 2532 2693 source = "registry+https://github.com/rust-lang/crates.io-index" 2533 2694 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2695 + 2696 + [[package]] 2697 + name = "rand_core" 2698 + version = "0.9.5" 2699 + source = "registry+https://github.com/rust-lang/crates.io-index" 2700 + checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" 2701 + dependencies = [ 2702 + "getrandom 0.3.4", 2703 + ] 2534 2704 2535 2705 [[package]] 2536 2706 name = "ratatui" ··· 2682 2852 checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" 2683 2853 2684 2854 [[package]] 2855 + name = "rustc-hash" 2856 + version = "2.1.1" 2857 + source = "registry+https://github.com/rust-lang/crates.io-index" 2858 + checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 2859 + 2860 + [[package]] 2685 2861 name = "rustc_version" 2686 2862 version = "0.4.1" 2687 2863 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2714 2890 version = "1.0.23" 2715 2891 source = "registry+https://github.com/rust-lang/crates.io-index" 2716 2892 checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" 2893 + 2894 + [[package]] 2895 + name = "sakura" 2896 + version = "0.1.0" 2897 + dependencies = [ 2898 + "automerge", 2899 + "autosurgeon", 2900 + "serde", 2901 + ] 2717 2902 2718 2903 [[package]] 2719 2904 name = "same-file" ··· 2800 2985 dependencies = [ 2801 2986 "cfg-if", 2802 2987 "cpufeatures", 2803 - "digest", 2988 + "digest 0.10.7", 2804 2989 ] 2805 2990 2806 2991 [[package]] ··· 2809 2994 source = "registry+https://github.com/rust-lang/crates.io-index" 2810 2995 checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" 2811 2996 dependencies = [ 2812 - "digest", 2997 + "digest 0.10.7", 2813 2998 "sha1", 2814 2999 ] 2815 3000 ··· 2821 3006 dependencies = [ 2822 3007 "cfg-if", 2823 3008 "cpufeatures", 2824 - "digest", 3009 + "digest 0.10.7", 3010 + ] 3011 + 3012 + [[package]] 3013 + name = "sha2" 3014 + version = "0.11.0-rc.5" 3015 + source = "registry+https://github.com/rust-lang/crates.io-index" 3016 + checksum = "7c5f3b1e2dc8aad28310d8410bd4d7e180eca65fca176c52ab00d364475d0024" 3017 + dependencies = [ 3018 + "cfg-if", 3019 + "cpufeatures", 3020 + "digest 0.11.2", 2825 3021 ] 2826 3022 2827 3023 [[package]] ··· 2881 3077 ] 2882 3078 2883 3079 [[package]] 3080 + name = "simd-adler32" 3081 + version = "0.3.8" 3082 + source = "registry+https://github.com/rust-lang/crates.io-index" 3083 + checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" 3084 + 3085 + [[package]] 3086 + name = "similar" 3087 + version = "2.7.0" 3088 + source = "registry+https://github.com/rust-lang/crates.io-index" 3089 + checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" 3090 + dependencies = [ 3091 + "bstr", 3092 + "unicode-segmentation", 3093 + ] 3094 + 3095 + [[package]] 2884 3096 name = "siphasher" 2885 3097 version = "1.0.2" 2886 3098 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2899 3111 checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 2900 3112 2901 3113 [[package]] 3114 + name = "smol_str" 3115 + version = "0.3.6" 3116 + source = "registry+https://github.com/rust-lang/crates.io-index" 3117 + checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" 3118 + dependencies = [ 3119 + "borsh", 3120 + "serde_core", 3121 + ] 3122 + 3123 + [[package]] 2902 3124 name = "socket2" 2903 3125 version = "0.6.2" 2904 3126 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3073 3295 "pest", 3074 3296 "pest_derive", 3075 3297 "phf", 3076 - "sha2", 3298 + "sha2 0.10.9", 3077 3299 "signal-hook 0.3.18", 3078 3300 "siphasher", 3079 3301 "terminfo", ··· 3611 3833 dependencies = [ 3612 3834 "getrandom 0.3.4", 3613 3835 "mac_address", 3614 - "sha2", 3836 + "sha2 0.10.9", 3615 3837 "thiserror 1.0.69", 3616 3838 "uuid", 3617 3839 ] ··· 4073 4295 "serde_json", 4074 4296 "unicode-xid", 4075 4297 "wasmparser", 4298 + ] 4299 + 4300 + [[package]] 4301 + name = "zerocopy" 4302 + version = "0.8.42" 4303 + source = "registry+https://github.com/rust-lang/crates.io-index" 4304 + checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" 4305 + dependencies = [ 4306 + "zerocopy-derive", 4307 + ] 4308 + 4309 + [[package]] 4310 + name = "zerocopy-derive" 4311 + version = "0.8.42" 4312 + source = "registry+https://github.com/rust-lang/crates.io-index" 4313 + checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" 4314 + dependencies = [ 4315 + "proc-macro2", 4316 + "quote", 4317 + "syn 2.0.117", 4076 4318 ] 4077 4319 4078 4320 [[package]]
+2 -1
Cargo.toml
··· 1 1 [workspace] 2 - members = ["crates/db"] 2 + members = ["crates/db", "crates/sakura"] 3 3 4 4 5 5 [workspace.package] ··· 26 26 27 27 [workspace.dependencies] 28 28 snafu = "0.9.0" 29 + serde = "1.0.228" 29 30 tracing = "0.1.44" 30 31 31 32 [package]
+18
crates/sakura/Cargo.toml
··· 1 + [package] 2 + name = "sakura" 3 + version = "0.1.0" 4 + authors.workspace = true 5 + edition.workspace = true 6 + rust-version.workspace = true 7 + repository.workspace = true 8 + license.workspace = true 9 + 10 + [dependencies] 11 + automerge = "0.7.3" 12 + autosurgeon = "0.10.1" 13 + serde.workspace = true 14 + 15 + 16 + [lints.clippy] 17 + pedantic = "deny" 18 + nursery = "deny"
+188
crates/sakura/src/behaviors.rs
··· 1 + use super::NodeId; 2 + 3 + /// Describes the possible behaviors of the `Tree::insert` method. 4 + pub enum InsertBehavior<'a> { 5 + /// Insert the `Node` as the root of the tree. 6 + /// 7 + /// If there is already a root `Node` in the tree, then that `Node` will 8 + /// be set as the first child as the new root `Node`. 9 + /// 10 + /// ``` 11 + /// use sakura::*; 12 + /// use sakura::InsertBehavior::*; 13 + /// 14 + /// let mut tree: Tree<i32> = Tree::new(); 15 + /// let root_node = Node::new(1); 16 + /// 17 + /// tree.insert(root_node, AsRoot).unwrap(); 18 + /// 19 + /// ``` 20 + AsRoot, 21 + 22 + /// Inserts the `Node` under the `Node` that has the provided `NodeId`. 23 + /// 24 + /// Note: Adds the new `Node` to the end of its children. 25 + /// 26 + /// # Returns 27 + /// `Result` containing the `NodeId` of the child that was added or a `NodeIdError` 28 + /// 29 + /// ``` 30 + /// use sakura::*; 31 + /// use sakura::InsertBehavior::*; 32 + /// 33 + /// let root_node = Node::new(1); 34 + /// let child_node = Node::new(2); 35 + /// 36 + /// let mut tree: Tree<i32> = Tree::new(); 37 + /// let mut root_id = tree.insert(root_node, AsRoot).unwrap(); 38 + /// 39 + /// tree.insert(child_node, UnderNode(&root_id)).unwrap(); 40 + /// 41 + /// ``` 42 + UnderNode(&'a NodeId), 43 + } 44 + 45 + pub enum RemoveBehavior { 46 + /// The entire subtree of the `Node` being removed will be 47 + /// dropped from the tree, effectively meaning that all children 48 + /// will be dropped recursively. 49 + /// 50 + /// Those `Node`'s will no longer exist and cannot be accessed even 51 + /// if you hold a `NodeId` for them, so use this behavior with caution. 52 + /// 53 + /// 54 + /// ``` 55 + /// use sakura::*; 56 + /// use sakura::InsertBehavior::*; 57 + /// use sakura::RemoveBehavior::*; 58 + /// 59 + /// let mut tree: Tree<i32> = Tree::new(); 60 + /// 61 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 62 + /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 63 + /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap(); 64 + /// 65 + /// let child = tree.remove_node(child_id, DropChildren).ok().unwrap(); 66 + /// 67 + /// assert!(tree.get(&grandchild_id).is_err()); 68 + /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0); 69 + /// assert_eq!(child.children().len(), 0); 70 + /// assert_eq!(child.parent(), None); 71 + /// ``` 72 + /// 73 + DropChildren, 74 + 75 + /// 76 + /// 77 + /// If the removed `Node` (say `A`) has a parent `A'`, then `A'` will 78 + /// become the parent of `A`'s children. 79 + /// 80 + /// If `A` doesn't have a parent, then this behaves exactly like 81 + /// `RemoveBehavior::OrphanChildren`. 82 + /// ``` 83 + /// use sakura::*; 84 + /// use sakura::InsertBehavior::*; 85 + /// use sakura::RemoveBehavior::*; 86 + /// 87 + /// let mut tree: Tree<i32> = Tree::new(); 88 + /// 89 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 90 + /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 91 + /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap(); 92 + /// 93 + /// let child = tree.remove_node(child_id, LiftChildren).ok().unwrap(); 94 + /// 95 + /// assert!(tree.get(&grandchild_id).is_ok()); 96 + /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id)); 97 + /// assert_eq!(child.children().len(), 0); 98 + /// assert_eq!(child.parent(), None); 99 + /// ``` 100 + /// 101 + LiftChildren, 102 + 103 + /// All children will have their parent references cleared. Nothing 104 + /// will point to them, but they will still exist in the tree. 105 + /// Those `Node`s can still be accessed if you still have their 106 + /// `NodeId`'s. 107 + /// 108 + /// ``` 109 + /// use sakura::*; 110 + /// use sakura::InsertBehavior::*; 111 + /// use sakura::RemoveBehavior::*; 112 + /// 113 + /// let mut tree: Tree<i32> = Tree::new(); 114 + /// 115 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 116 + /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 117 + /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap(); 118 + /// 119 + /// let child = tree.remove_node(child_id, OrphanChildren).ok().unwrap(); 120 + /// 121 + /// assert!(tree.get(&grandchild_id).is_ok()); 122 + /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0); 123 + /// assert_eq!(child.children().len(), 0); 124 + /// assert_eq!(child.parent(), None); 125 + /// ``` 126 + /// 127 + OrphanChildren, 128 + } 129 + 130 + pub enum MoveBehavior<'a> { 131 + /// Sets the `Node` as the new root `Node`, while having all their children 132 + /// travel with them. 133 + /// 134 + /// If there is already a root `Node` in place, it will be attached as the 135 + /// last child of the new root `Node`. 136 + /// 137 + /// ``` 138 + /// use sakura::*; 139 + /// use sakura::InsertBehavior::*; 140 + /// use sakura::MoveBehavior::*; 141 + /// 142 + /// let mut tree: Tree<i32> = Tree::new(); 143 + /// 144 + /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap(); 145 + /// let child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 146 + /// let grandchild_id = tree.insert(Node::new(3), UnderNode(&child_id)).unwrap(); 147 + /// 148 + /// tree.move_node(&grandchild_id, ToRoot).unwrap(); 149 + /// 150 + /// assert_eq!(tree.root_node_id(), Some(&grandchild_id)); 151 + /// assert!(tree.get(&grandchild_id).unwrap().children().contains(&root_id)); 152 + /// assert!(!tree.get(&child_id).unwrap().children().contains(&grandchild_id)); 153 + /// ``` 154 + /// 155 + ToRoot, 156 + 157 + /// 158 + /// Moves a `Node` in the `Tree` to a new parent, while leaving 159 + /// all children in their place. 160 + /// 161 + /// If the new parent (lets say `A'`) is a descendant of the `Node` being 162 + /// moved (`A`), then the direct child of `A` on the path from `A` to 163 + /// `A'` will be shifted upwards to take the place of its parent (`A`). 164 + /// All other children of `A` will be left alone, so they will travel 165 + /// with `A`. 166 + /// 167 + /// NOTE: During the shift-up part of the above scenario, the `Node` being 168 + /// shifted up will always be added as the last child of its new parent. 169 + /// ``` 170 + /// use sakura::*; 171 + /// use sakura::InsertBehavior::*; 172 + /// use sakura::MoveBehavior::*; 173 + /// 174 + /// let mut tree: Tree<i32> = Tree::new(); 175 + /// 176 + /// let root_id = tree.insert(Node::new(1), AsRoot).ok().unwrap(); 177 + /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 178 + /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap(); 179 + /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&first_child_id)).unwrap(); 180 + /// 181 + /// tree.move_node(&grandchild_id, ToParent(&second_child_id)).unwrap(); 182 + /// 183 + /// assert!(!tree.get(&first_child_id).unwrap().children().contains(&grandchild_id)); 184 + /// assert!(tree.get(&second_child_id).unwrap().children().contains(&grandchild_id)); 185 + /// ``` 186 + /// 187 + ToParent(&'a NodeId), 188 + }
+27
crates/sakura/src/error.rs
··· 1 + use std::{error::Error, fmt::Display}; 2 + 3 + /// Enum for all possible `NodeId` errors that could happen. 4 + #[derive(Debug, PartialEq, Eq)] 5 + pub enum NodeIdError { 6 + /// Occurs when a `NodeId` is used on a `Tree` after the corresponding 7 + /// `Node` has been removed. 8 + NodeIdNoLongerValid, 9 + } 10 + 11 + impl NodeIdError { 12 + const fn to_string(&self) -> &str { 13 + match *self { 14 + Self::NodeIdNoLongerValid => { 15 + "The given NodeId is no longer valid. The Node in question has been removed." 16 + } 17 + } 18 + } 19 + } 20 + 21 + impl Display for NodeIdError { 22 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 23 + write!(f, "NodeIdError: {}", self.to_string()) 24 + } 25 + } 26 + 27 + impl Error for NodeIdError {}
+261
crates/sakura/src/iterators.rs
··· 1 + use std::{collections::VecDeque, slice::Iter}; 2 + 3 + use crate::{Node, NodeId, Tree}; 4 + 5 + /// An `Iterator` over the children of a `Node`. 6 + /// 7 + /// Iterates over the child `Node`s of a given `Node` in the `Tree`. 8 + /// Each call to `next` will return an immutable 9 + /// reference to the next child `Node`. 10 + pub struct Children<'a, T: 'a> { 11 + tree: &'a Tree<T>, 12 + child_ids: Iter<'a, NodeId>, 13 + } 14 + 15 + impl<'a, T> Children<'a, T> { 16 + // we actually want to 17 + #[allow(clippy::use_self)] 18 + pub(crate) fn new(tree: &'a Tree<T>, node_id: &NodeId) -> Children<'a, T> { 19 + Children { 20 + tree, 21 + child_ids: tree 22 + .get(node_id) 23 + .expect( 24 + "Function is crate specific, expecting to only be used 25 + with a valid node_id", 26 + ) 27 + .children() 28 + .as_slice() 29 + .iter(), 30 + } 31 + } 32 + } 33 + 34 + impl<'a, T> Iterator for Children<'a, T> { 35 + type Item = &'a Node<T>; 36 + 37 + fn next(&mut self) -> Option<Self::Item> { 38 + self.child_ids 39 + .next() 40 + .and_then(|child_id| self.tree.get(child_id).ok()) 41 + } 42 + } 43 + 44 + impl<T> Clone for Children<'_, T> { 45 + fn clone(&self) -> Self { 46 + Children { 47 + tree: self.tree, 48 + child_ids: self.child_ids.clone(), 49 + } 50 + } 51 + } 52 + 53 + /// An `Iterator` over the children of a `Node`. 54 + /// 55 + /// Iterates over the child `NodeId`s of a given `NodeId` in the `Tree`. 56 + /// Each call to `next` will return an immutable 57 + /// reference to the next child `NodeId`. 58 + pub struct ChildrenIds<'a> { 59 + child_ids: Iter<'a, NodeId>, 60 + } 61 + 62 + impl<'a> ChildrenIds<'a> { 63 + #[allow(clippy::use_self)] 64 + pub(crate) fn new<T>(tree: &'a Tree<T>, node_id: &NodeId) -> ChildrenIds<'a> { 65 + ChildrenIds { 66 + child_ids: tree 67 + .get(node_id) 68 + .expect( 69 + "Function is crate specific, expecting to only be used 70 + with a valid node_id", 71 + ) 72 + .children() 73 + .as_slice() 74 + .iter(), 75 + } 76 + } 77 + } 78 + 79 + impl<'a> Iterator for ChildrenIds<'a> { 80 + type Item = &'a NodeId; 81 + 82 + fn next(&mut self) -> Option<Self::Item> { 83 + self.child_ids.next() 84 + } 85 + } 86 + 87 + /// An `Iterator` over the ancestors of a `Node`. 88 + /// 89 + /// Iterates over the ancestor `Node`s of given `Node` in the `Tree`. 90 + /// Each call to `next` will return an immutable reference to the next 91 + /// `Node` up the `Tree`. 92 + pub struct Ancestors<'a, T: 'a> { 93 + tree: &'a Tree<T>, 94 + node_id: Option<NodeId>, 95 + } 96 + 97 + impl<'a, T> Ancestors<'a, T> { 98 + #[allow(clippy::use_self)] 99 + pub(crate) const fn new(tree: &'a Tree<T>, node_id: NodeId) -> Ancestors<'a, T> { 100 + Ancestors { 101 + tree, 102 + node_id: Some(node_id), 103 + } 104 + } 105 + } 106 + 107 + impl<'a, T> Iterator for Ancestors<'a, T> { 108 + type Item = &'a Node<T>; 109 + 110 + fn next(&mut self) -> Option<&'a Node<T>> { 111 + self.node_id 112 + .take() 113 + .and_then(|current_id| self.tree.get(&current_id).ok()) 114 + .and_then(|node_ref| node_ref.parent()) 115 + .and_then(|parent_id| { 116 + self.node_id = Some(parent_id.clone()); 117 + self.tree.get(parent_id).ok() 118 + }) 119 + } 120 + } 121 + 122 + impl<T> Clone for Ancestors<'_, T> { 123 + fn clone(&self) -> Self { 124 + Ancestors { 125 + tree: self.tree, 126 + node_id: self.node_id.clone(), 127 + } 128 + } 129 + } 130 + 131 + /// An `Iterator` over the ancestors of a `Node`. 132 + /// 133 + /// Iterates over `NodeId`s instead of over `Node`s themselves. 134 + pub struct AncestorsIds<'a, T: 'a> { 135 + tree: &'a Tree<T>, 136 + node_id: Option<NodeId>, 137 + } 138 + 139 + impl<'a, T> AncestorsIds<'a, T> { 140 + #[allow(clippy::use_self)] 141 + pub(crate) const fn new(tree: &'a Tree<T>, node_id: NodeId) -> AncestorsIds<'a, T> { 142 + AncestorsIds { 143 + tree, 144 + node_id: Some(node_id), 145 + } 146 + } 147 + } 148 + 149 + impl<'a, T> Iterator for AncestorsIds<'a, T> { 150 + type Item = &'a NodeId; 151 + 152 + fn next(&mut self) -> Option<&'a NodeId> { 153 + self.node_id 154 + .take() 155 + .and_then(|current_id| self.tree.get(&current_id).ok()) 156 + .and_then(|node_ref| node_ref.parent()) 157 + .inspect(|parent_id| { 158 + self.node_id = Some((*parent_id).clone()); 159 + }) 160 + } 161 + } 162 + 163 + impl<T> Clone for AncestorsIds<'_, T> { 164 + fn clone(&self) -> Self { 165 + AncestorsIds { 166 + tree: self.tree, 167 + node_id: self.node_id.clone(), 168 + } 169 + } 170 + } 171 + 172 + /// An iterator over the subtree relative to a given `Node`. 173 + /// 174 + /// Each call to `next` will return an immutable reference to the 175 + /// next `Node` in Pre-Order Traversal order. 176 + pub struct PreOrderTraversal<'a, T: 'a> { 177 + tree: &'a Tree<T>, 178 + data: VecDeque<NodeId>, 179 + } 180 + 181 + impl<'a, T> PreOrderTraversal<'a, T> { 182 + #[allow(clippy::use_self)] 183 + pub(crate) fn new(tree: &'a Tree<T>, node_id: NodeId) -> PreOrderTraversal<'a, T> { 184 + let mut data = VecDeque::with_capacity(tree.capacity()); 185 + data.push_front(node_id); 186 + 187 + PreOrderTraversal { tree, data } 188 + } 189 + } 190 + 191 + impl<'a, T> Iterator for PreOrderTraversal<'a, T> { 192 + type Item = &'a Node<T>; 193 + 194 + fn next(&mut self) -> Option<Self::Item> { 195 + self.data 196 + .pop_front() 197 + .and_then(|node_id| self.tree.get(&node_id).ok()) 198 + .inspect(|node_ref| { 199 + for child_id in node_ref.children().iter().rev() { 200 + self.data.push_front(child_id.clone()); 201 + } 202 + }) 203 + } 204 + } 205 + 206 + impl<T> Clone for PreOrderTraversal<'_, T> { 207 + fn clone(&self) -> Self { 208 + PreOrderTraversal { 209 + tree: self.tree, 210 + data: self.data.clone(), 211 + } 212 + } 213 + } 214 + 215 + /// An Iterator over the subtree relative to a given `Node`. 216 + /// 217 + /// Each call to `next` will return an immutable reference to the 218 + /// next `NodeId` in Pre-Order Traversal order. 219 + /// 220 + pub struct PreOrderTraversalIds<'a, T: 'a> { 221 + tree: &'a Tree<T>, 222 + data: VecDeque<NodeId>, 223 + } 224 + 225 + impl<'a, T> PreOrderTraversalIds<'a, T> { 226 + #[allow(clippy::use_self)] 227 + pub(crate) fn new(tree: &'a Tree<T>, node_id: NodeId) -> PreOrderTraversalIds<'a, T> { 228 + // Over allocating, but all at once instead of resizing and reallocating as we go. 229 + let mut data = VecDeque::with_capacity(tree.capacity()); 230 + 231 + data.push_front(node_id); 232 + 233 + PreOrderTraversalIds { tree, data } 234 + } 235 + } 236 + 237 + impl<T> Iterator for PreOrderTraversalIds<'_, T> { 238 + type Item = NodeId; 239 + 240 + fn next(&mut self) -> Option<NodeId> { 241 + self.data.pop_front().and_then(|node_id| { 242 + self.tree.get(&node_id).ok().map(|node_ref| { 243 + // prepend child_ids 244 + for child_id in node_ref.children().iter().rev() { 245 + self.data.push_front(child_id.clone()); 246 + } 247 + 248 + node_id 249 + }) 250 + }) 251 + } 252 + } 253 + 254 + impl<T> Clone for PreOrderTraversalIds<'_, T> { 255 + fn clone(&self) -> Self { 256 + PreOrderTraversalIds { 257 + tree: self.tree, 258 + data: self.data.clone(), 259 + } 260 + } 261 + }
+50
crates/sakura/src/lib.rs
··· 1 + #![forbid(unsafe_code)] 2 + //! A purpose-built library for CASE, to hold the internal tree-like 3 + //! data structure that holds tasks and groups. Additionally, this 4 + //! data structure is compatible with `AutoMerge`, via `AutoSurgeon` 5 + //! 6 + //! TODO: add example usage 7 + 8 + use autosurgeon::{Hydrate, Reconcile}; 9 + use serde::{Deserialize, Serialize}; 10 + 11 + mod behaviors; 12 + mod error; 13 + mod iterators; 14 + mod node; 15 + mod tree; 16 + 17 + pub use node::Node; 18 + 19 + pub use tree::Tree; 20 + pub use tree::TreeBuilder; 21 + 22 + pub use behaviors::InsertBehavior; 23 + pub use behaviors::MoveBehavior; 24 + pub use behaviors::RemoveBehavior; 25 + 26 + pub use iterators::Ancestors; 27 + pub use iterators::Children; 28 + pub use iterators::ChildrenIds; 29 + pub use iterators::PreOrderTraversal; 30 + pub use iterators::PreOrderTraversalIds; 31 + 32 + pub use error::NodeIdError; 33 + 34 + /// A Node Id 35 + #[derive( 36 + Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Reconcile, Hydrate, 37 + )] 38 + pub struct NodeId { 39 + index: u32, 40 + } 41 + 42 + impl NodeId { 43 + // This is okay since we are practically never reaching 2^32. 44 + #[allow(clippy::cast_possible_truncation)] 45 + pub(crate) const fn new(index: usize) -> Self { 46 + Self { 47 + index: index as u32, 48 + } 49 + } 50 + }
+204
crates/sakura/src/node.rs
··· 1 + use autosurgeon::{Hydrate, Reconcile}; 2 + use serde::{Deserialize, Serialize}; 3 + 4 + use crate::NodeId; 5 + 6 + #[derive(Debug, Serialize, Deserialize, Reconcile, Hydrate, Ord, Eq, PartialOrd)] 7 + pub struct Node<T> { 8 + pub(crate) data: T, 9 + pub(crate) parent: Option<NodeId>, 10 + pub(crate) children: Vec<NodeId>, 11 + } 12 + 13 + impl<T> PartialEq for Node<T> 14 + where 15 + T: PartialEq, 16 + { 17 + // We only care if node data is equivalent. 18 + fn eq(&self, other: &Self) -> bool { 19 + self.data == other.data 20 + } 21 + } 22 + 23 + impl<T> Node<T> { 24 + /// Creates a new `Node` with the provided data 25 + /// 26 + /// ``` 27 + /// use sakura::Node; 28 + /// 29 + /// let _one: Node<i32> = Node::new(1); 30 + /// ``` 31 + /// 32 + #[allow(clippy::use_self)] 33 + pub const fn new(data: T) -> Node<T> { 34 + Self { 35 + parent: None, 36 + data, 37 + children: vec![], 38 + } 39 + } 40 + 41 + /// Returns a reference to the data inside the `Node` 42 + /// 43 + /// ``` 44 + /// use sakura::Node; 45 + /// 46 + /// let x = 10; 47 + /// let node: Node<i32> = Node::new(x); 48 + /// # assert_eq!(node.data(), &10); 49 + /// ``` 50 + pub const fn data(&self) -> &T { 51 + &self.data 52 + } 53 + 54 + /// Returns a mutable reference to the data inside the `Node` 55 + /// 56 + /// ``` 57 + /// use sakura::Node; 58 + /// 59 + /// let x = 10; 60 + /// let mut node: Node<i32> = Node::new(x); 61 + /// # assert_eq!(node.data_mut(), &mut 10); 62 + /// ``` 63 + pub const fn data_mut(&mut self) -> &mut T { 64 + &mut self.data 65 + } 66 + 67 + /// Replaces this `Node`s data with the provided data 68 + /// 69 + /// Returns the data previously in the node 70 + /// 71 + /// ``` 72 + /// use sakura::Node; 73 + /// 74 + /// let x = 10; 75 + /// let mut y = 15; 76 + /// 77 + /// let mut node_x: Node<i32> = Node::new(x); 78 + /// let replaced_x = node_x.replace_data(y); 79 + /// let new_x = node_x.data(); 80 + /// 81 + /// # assert_eq!(*new_x, y); 82 + /// # assert_eq!(replaced_x, x); 83 + /// ``` 84 + pub const fn replace_data(&mut self, mut data: T) -> T { 85 + ::std::mem::swap(&mut data, self.data_mut()); 86 + data 87 + } 88 + 89 + /// Returns the parent of this `Node`, if it has one. 90 + /// 91 + /// ``` 92 + /// use sakura::Node; 93 + /// 94 + /// let node: Node<i32> = Node::new(1); 95 + /// # assert_eq!(node.parent(), None); 96 + /// ``` 97 + pub const fn parent(&self) -> Option<&NodeId> { 98 + self.parent.as_ref() 99 + } 100 + 101 + /// Returns the children of this `Node` 102 + /// 103 + /// ``` 104 + /// use sakura::Node; 105 + /// 106 + /// let node: Node<i32> = Node::new(0); 107 + /// # assert_eq!(node.children().len(), 0); 108 + /// ``` 109 + pub const fn children(&self) -> &Vec<NodeId> { 110 + &self.children 111 + } 112 + 113 + pub(crate) const fn children_mut(&mut self) -> &mut Vec<NodeId> { 114 + &mut self.children 115 + } 116 + 117 + pub(crate) const fn set_parent(&mut self, parent: Option<NodeId>) { 118 + self.parent = parent; 119 + } 120 + 121 + pub(crate) fn add_child(&mut self, child: NodeId) { 122 + self.children.push(child); 123 + } 124 + 125 + pub(crate) fn set_children(&mut self, children: Vec<NodeId>) { 126 + self.children = children; 127 + } 128 + 129 + pub(crate) fn take_children(&mut self) -> Vec<NodeId> { 130 + use std::mem; 131 + 132 + let mut empty = Vec::with_capacity(0); 133 + mem::swap(&mut self.children, &mut empty); 134 + // post-swap this holds children 135 + empty 136 + } 137 + } 138 + 139 + #[cfg(test)] 140 + mod node_tests { 141 + 142 + use super::super::NodeId; 143 + use super::Node; 144 + 145 + #[test] 146 + fn test_new() { 147 + let node = Node::new(10); 148 + assert_eq!(node.children.capacity(), 0); 149 + } 150 + 151 + #[test] 152 + fn test_data() { 153 + let data = 0; 154 + let node = Node::new(data); 155 + 156 + assert_eq!(node.data(), &data); 157 + } 158 + 159 + #[test] 160 + fn test_data_mut() { 161 + let mut data = 0; 162 + let mut node = Node::new(data); 163 + 164 + assert_eq!(node.data_mut(), &mut data); 165 + } 166 + 167 + #[test] 168 + fn test_parent() { 169 + let mut node = Node::new(0); 170 + 171 + assert!(node.parent().is_none()); 172 + 173 + let parent_id: NodeId = NodeId { index: 100 }; 174 + 175 + node.set_parent(Some(parent_id.clone())); 176 + 177 + assert_eq!(node.parent, Some(parent_id)); 178 + } 179 + 180 + #[test] 181 + fn test_children() { 182 + let mut node = Node::new(0); 183 + assert!(node.children.is_empty()); 184 + 185 + let child_id: NodeId = NodeId { index: 1 }; 186 + 187 + node.add_child(child_id.clone()); 188 + 189 + assert_eq!(node.children.len(), 1); 190 + assert_eq!(node.children.first().unwrap(), &child_id); 191 + } 192 + 193 + #[test] 194 + fn test_partial_eq() { 195 + let node1 = Node::new(32); 196 + let node2 = Node::new(32); 197 + let node3 = Node::new(64); 198 + 199 + assert_eq!(node1, node2); 200 + 201 + assert_ne!(node1, node3); 202 + assert_ne!(node2, node3); 203 + } 204 + }
+1732
crates/sakura/src/tree.rs
··· 1 + use std::cmp::Ordering; 2 + 3 + use autosurgeon::{Hydrate, Reconcile}; 4 + use serde::{Deserialize, Serialize}; 5 + 6 + use crate::{ 7 + Ancestors, Children, ChildrenIds, InsertBehavior, MoveBehavior, Node, NodeId, 8 + PreOrderTraversal, PreOrderTraversalIds, RemoveBehavior, error::NodeIdError, 9 + iterators::AncestorsIds, 10 + }; 11 + 12 + /// A `Tree` builder to assist with building a `Tree`, with more control. 13 + pub struct TreeBuilder<T> { 14 + root: Option<Node<T>>, 15 + node_capacity: usize, 16 + swap_capacity: usize, 17 + } 18 + 19 + impl<T> Default for TreeBuilder<T> { 20 + fn default() -> Self { 21 + Self::new() 22 + } 23 + } 24 + 25 + impl<T> TreeBuilder<T> { 26 + /// Creates a new `TreeBuilder` with default settings. 27 + /// 28 + /// ``` 29 + /// use sakura::TreeBuilder; 30 + /// 31 + /// let _tree_builder: TreeBuilder<i32> = TreeBuilder::new(); 32 + /// 33 + /// ``` 34 + #[allow(clippy::use_self)] 35 + #[must_use] 36 + pub const fn new() -> TreeBuilder<T> { 37 + TreeBuilder { 38 + root: None, 39 + node_capacity: 0, 40 + swap_capacity: 0, 41 + } 42 + } 43 + 44 + /// Sets the root `Node` for the resulting `Tree` from this `TreeBuilder`. 45 + /// 46 + /// ``` 47 + /// use sakura::TreeBuilder; 48 + /// use sakura::Node; 49 + /// 50 + /// let _tree_builder: TreeBuilder<i32> = TreeBuilder::new().with_root(Node::new(1)); 51 + /// ``` 52 + #[must_use] 53 + #[allow(clippy::use_self)] 54 + pub fn with_root(mut self, root: Node<T>) -> TreeBuilder<T> { 55 + self.root = Some(root); 56 + self 57 + } 58 + 59 + /// Sets the `node_capacity` for `TreeBuilder`. 60 + /// 61 + /// Since `Tree`'s own their `Node`'s, they must allocate 62 + /// storage for `Node`'s ahead of time, so that the 63 + /// space allocations don't happen as the `Node`'s are inserted. 64 + /// 65 + /// _Configure this variable if you know the **maximum** number of `Node`'s 66 + /// that your `Tree` will **contain** at **any given time**._ 67 + /// 68 + /// ``` 69 + /// use sakura::TreeBuilder; 70 + /// 71 + /// let _tree_builder: TreeBuilder<i32> = TreeBuilder::new().with_node_capacity(1); 72 + /// 73 + /// ``` 74 + #[must_use] 75 + #[allow(clippy::use_self)] 76 + pub const fn with_node_capacity(mut self, node_capacity: usize) -> TreeBuilder<T> { 77 + self.node_capacity = node_capacity; 78 + self 79 + } 80 + 81 + /// Sets the `swap_capacity` for `TreeBuilder`. 82 + /// 83 + /// `Tree`'s attempt to save time by reusing storage space 84 + /// when `Node`'s are removed (instead of shuffling `Node`'s around internally). 85 + /// To do this, the `Tree` must store information about the space left behind when a `Node` 86 + /// is removed. Using this setting allows the `Tree` to pre-allocate this storage 87 + /// space instead of doing so as `Node`'s are removed from the `Tree`. 88 + /// 89 + /// _Use of this setting is recommended if you know the **maximum "net number 90 + /// of removals"** that have occurred at **any given time**._ 91 + /// 92 + /// 93 + /// For example: 94 + /// --- 95 + /// In **Scenario 1**: 96 + /// 97 + /// * Add 3 `Node`s, Remove 2 `Node`s, Add 1 `Node`. 98 + /// 99 + /// The maximum amount of nodes that have been removed at any given time is **2**. 100 + /// 101 + /// But in **Scenario 2**: 102 + /// 103 + /// * Add 3 `Node`s, Remove 2 `Node`s, Add 1 `Node`, Remove 2 `Node`s. 104 + /// 105 + /// The maximum amount of nodes that have been removed at any given time is **3**. 106 + /// 107 + /// ``` 108 + /// use sakura::TreeBuilder; 109 + /// 110 + /// let _tree_builder: TreeBuilder<i32> = TreeBuilder::new().with_node_capacity(1); 111 + /// 112 + /// ``` 113 + #[must_use] 114 + #[allow(clippy::use_self)] 115 + pub const fn with_swap_capacity(mut self, swap_capacity: usize) -> TreeBuilder<T> { 116 + self.swap_capacity = swap_capacity; 117 + self 118 + } 119 + 120 + /// 121 + /// Build a `Tree` based upon the current settings in the `TreeBuilder`. 122 + /// 123 + /// ``` 124 + /// use sakura::TreeBuilder; 125 + /// use sakura::Tree; 126 + /// use sakura::Node; 127 + /// 128 + /// let _tree: Tree<i32> = TreeBuilder::new() 129 + /// .with_root(Node::new(5)) 130 + /// .with_node_capacity(3) 131 + /// .with_swap_capacity(2) 132 + /// .build(); 133 + /// ``` 134 + pub fn build(mut self) -> Tree<T> { 135 + let mut tree = Tree { 136 + root: None, 137 + nodes: Vec::with_capacity(self.node_capacity), 138 + free_ids: Vec::with_capacity(self.swap_capacity), 139 + }; 140 + 141 + if self.root.is_some() { 142 + let node_id = NodeId { index: 0 }; 143 + 144 + tree.nodes.push(self.root.take()); 145 + 146 + tree.root = Some(node_id); 147 + } 148 + 149 + tree 150 + } 151 + } 152 + 153 + /// A tree structure made up of `Node`'s. 154 + /// 155 + /// # Panics 156 + /// Any function that takes a `NodeId` can `panic`, but this should 157 + /// only happen with improper `NodeId` management within `Sakura`, and 158 + /// should have nothing to do with library user's code. 159 + #[derive(Debug, Serialize, Deserialize, Reconcile, Hydrate)] 160 + pub struct Tree<T> { 161 + root: Option<NodeId>, 162 + pub(crate) nodes: Vec<Option<Node<T>>>, 163 + free_ids: Vec<NodeId>, 164 + } 165 + 166 + impl<T> Default for Tree<T> { 167 + fn default() -> Self { 168 + Self::new() 169 + } 170 + } 171 + 172 + impl<T> PartialEq for Tree<T> 173 + where 174 + T: PartialEq, 175 + { 176 + fn eq(&self, other: &Self) -> bool { 177 + if self.nodes.iter().filter(|x| x.is_some()).count() 178 + != other.nodes.iter().filter(|x| x.is_some()).count() 179 + { 180 + return false; 181 + } 182 + 183 + for ((i, node1), (j, node2)) in self 184 + .nodes 185 + .iter() 186 + .enumerate() 187 + .filter_map(|(i, x)| (*x).as_ref().map(|x| (i, x))) 188 + .zip( 189 + other 190 + .nodes 191 + .iter() 192 + .enumerate() 193 + .filter_map(|(i, x)| (*x).as_ref().map(|x| (i, x))), 194 + ) 195 + { 196 + let parent1_node = node1.parent.as_ref().and_then(|x| self.get(x).ok()); 197 + let parent2_node = node2.parent.as_ref().and_then(|x| other.get(x).ok()); 198 + 199 + if i != j || node1 != node2 || parent1_node != parent2_node { 200 + return false; 201 + } 202 + } 203 + 204 + true 205 + } 206 + } 207 + 208 + impl<T> Tree<T> { 209 + /// Creates a new `Tree` with default settings (no root `Node` and no space pre-allocation) 210 + /// 211 + /// ``` 212 + /// use sakura::Tree; 213 + /// 214 + /// let _tree: Tree<i32> = Tree::new(); 215 + /// ``` 216 + #[must_use] 217 + #[allow(clippy::use_self)] 218 + pub fn new() -> Tree<T> { 219 + TreeBuilder::new().build() 220 + } 221 + 222 + /// 223 + /// Returns the number of elements the tree can hold without reallocating. 224 + /// 225 + #[must_use] 226 + pub const fn capacity(&self) -> usize { 227 + self.nodes.capacity() 228 + } 229 + 230 + /// Returns a `Some` value containing the `NodeId` of the root `Node` if 231 + /// it exists. Otherwise, a `None` is returned. 232 + /// 233 + /// ``` 234 + /// use sakura::*; 235 + /// use sakura::InsertBehavior::*; 236 + /// 237 + /// let mut tree: Tree<i32> = Tree::new(); 238 + /// let root_id = tree.insert(Node::new(5), AsRoot).unwrap(); 239 + /// 240 + /// # assert_eq!(&root_id, tree.root_node_id().unwrap()); 241 + /// ``` 242 + /// 243 + #[must_use] 244 + pub const fn root_node_id(&self) -> Option<&NodeId> { 245 + self.root.as_ref() 246 + } 247 + 248 + /// Returns the maximum height of the `Tree`. 249 + /// 250 + /// ``` 251 + /// use sakura::*; 252 + /// use sakura::InsertBehavior::*; 253 + /// 254 + /// let mut tree: Tree<i32> = Tree::new(); 255 + /// # assert_eq!(0, tree.height()); 256 + /// 257 + /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap(); 258 + /// # assert_eq!(1, tree.height()); 259 + /// 260 + /// tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 261 + /// # assert_eq!(2, tree.height()); 262 + /// ``` 263 + #[must_use] 264 + pub fn height(&self) -> usize { 265 + self.root 266 + .as_ref() 267 + .map_or_else(|| 0, |id| self.height_of_node(id)) 268 + } 269 + 270 + fn height_of_node(&self, node: &NodeId) -> usize { 271 + let mut h = 0; 272 + for n in self.children_ids(node).unwrap() { 273 + h = std::cmp::max(h, self.height_of_node(n)); 274 + } 275 + 276 + h + 1 277 + } 278 + 279 + /// Gets a reference `Node` from the `Tree` 280 + /// 281 + /// # Errors 282 + /// 283 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 284 + /// 285 + /// # Panics 286 + /// 287 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 288 + /// be a bug in `Sakura` 289 + /// 290 + /// ``` 291 + /// use sakura::*; 292 + /// use sakura::InsertBehavior::*; 293 + /// 294 + /// let mut tree: Tree<i32> = Tree::new(); 295 + /// let root_id = tree.insert(Node::new(5), AsRoot).unwrap(); 296 + /// 297 + /// let root_node: &Node<i32> = tree.get(&root_id).unwrap(); 298 + /// 299 + /// # assert_eq!(root_node.data(), &5); 300 + /// ``` 301 + /// 302 + pub fn get(&self, node_id: &NodeId) -> Result<&Node<T>, NodeIdError> { 303 + // Returns if node id isn't valid. 304 + let () = self.is_valid_node_id(node_id)?; 305 + 306 + self.nodes 307 + .get(node_id.index as usize) 308 + .expect( 309 + "index must 310 + exist in tree", 311 + ) 312 + .as_ref() 313 + // Since we are given a node id, and that entry in the nodes 314 + // vec isn't an actual node, the node_id is no longer valid. 315 + .ok_or(NodeIdError::NodeIdNoLongerValid) 316 + } 317 + 318 + /// Gets a mutable reference to a `Node` from the `Tree` 319 + /// 320 + /// # Errors 321 + /// 322 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 323 + /// 324 + /// # Panics 325 + /// 326 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 327 + /// be a bug in `Sakura` 328 + /// 329 + /// ``` 330 + /// use sakura::*; 331 + /// use sakura::InsertBehavior::*; 332 + /// 333 + /// let mut tree: Tree<i32> = Tree::new(); 334 + /// let root_id = tree.insert(Node::new(5), AsRoot).unwrap(); 335 + /// 336 + /// let root_node: &mut Node<i32> = tree.get_mut(&root_id).unwrap(); 337 + /// 338 + /// # assert_eq!(root_node.data(), &5); 339 + /// ``` 340 + /// 341 + pub fn get_mut(&mut self, node_id: &NodeId) -> Result<&mut Node<T>, NodeIdError> { 342 + // Returns if node id isn't valid. 343 + let () = self.is_valid_node_id(node_id)?; 344 + 345 + self.nodes 346 + .get_mut(node_id.index as usize) 347 + .expect( 348 + "index must 349 + exist in tree", 350 + ) 351 + .as_mut() 352 + // Since we are given a node id, and that entry in the nodes 353 + // vec isn't an actual node, the node_id is no longer valid. 354 + .ok_or(NodeIdError::NodeIdNoLongerValid) 355 + } 356 + 357 + /// Inserts a `Node` into the `Tree`, via the provided `InsertBehavior` 358 + /// 359 + /// # Errors 360 + /// 361 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 362 + /// 363 + /// # Panics 364 + /// 365 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 366 + /// be a bug in `Sakura` 367 + /// 368 + /// ``` 369 + /// use sakura::*; 370 + /// use sakura::InsertBehavior::*; 371 + /// 372 + /// let root_node = Node::new(1); 373 + /// let child_node = Node::new(2); 374 + /// 375 + /// let mut tree: Tree<i32> = Tree::new(); 376 + /// let root_id = tree.insert(root_node, AsRoot).unwrap(); 377 + /// 378 + /// tree.insert(child_node, UnderNode(&root_id)).unwrap(); 379 + /// ``` 380 + #[allow(clippy::needless_pass_by_value)] 381 + pub fn insert( 382 + &mut self, 383 + node: Node<T>, 384 + behavior: InsertBehavior, 385 + ) -> Result<NodeId, NodeIdError> { 386 + match behavior { 387 + InsertBehavior::AsRoot => Ok(self.set_root(node)), 388 + InsertBehavior::UnderNode(parent_id) => { 389 + self.is_valid_node_id(parent_id)?; 390 + Ok(self.insert_with_parent(node, parent_id)) 391 + } 392 + } 393 + } 394 + 395 + /// Removes a `Node` from the `Tree`, via the provided `RemoveBehavior` 396 + /// 397 + /// # Errors 398 + /// 399 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 400 + /// 401 + /// # Panics 402 + /// 403 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 404 + /// be a bug in `Sakura` 405 + /// 406 + /// 407 + /// ``` 408 + /// use sakura::*; 409 + /// use sakura::InsertBehavior::*; 410 + /// use sakura::RemoveBehavior::*; 411 + /// 412 + /// let mut tree: Tree<i32> = Tree::new(); 413 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 414 + /// 415 + /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 416 + /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap(); 417 + /// 418 + /// let child = tree.remove_node(child_id, DropChildren).unwrap(); 419 + /// 420 + /// # assert!(tree.get(&grandchild_id).is_err()); 421 + /// # assert_eq!(tree.get(&root_id).unwrap().children().len(), 0); 422 + /// # assert_eq!(child.children().len(), 0); 423 + /// # assert_eq!(child.parent(), None); 424 + /// ``` 425 + #[allow(clippy::needless_pass_by_value)] 426 + pub fn remove_node( 427 + &mut self, 428 + node_id: NodeId, 429 + behavior: RemoveBehavior, 430 + ) -> Result<Node<T>, NodeIdError> { 431 + self.is_valid_node_id(&node_id)?; 432 + 433 + match behavior { 434 + RemoveBehavior::DropChildren => Ok(self.remove_node_drop_children(node_id)), 435 + RemoveBehavior::LiftChildren => Ok(self.remove_node_lift_children(node_id)), 436 + RemoveBehavior::OrphanChildren => Ok(self.remove_node_orphan_children(node_id)), 437 + } 438 + } 439 + 440 + /// Remove a `Node` from the `Tree`, while transferring all of its children 441 + /// to its parent. 442 + fn remove_node_lift_children(&mut self, node_id: NodeId) -> Node<T> { 443 + if let Some(parent_id) = self 444 + .get(&node_id) 445 + .expect("Tree::remove_node_lift_children: Expecting node_id to be valid.") 446 + .parent() 447 + .cloned() 448 + { 449 + for child_id in self 450 + .get(&node_id) 451 + .expect("Tree::remove_node_lift_children: Expecting node_id to be valid.") 452 + .children() 453 + .clone() 454 + { 455 + self.set_as_parent_and_child(&parent_id, &child_id); 456 + } 457 + } else { 458 + self.clear_parent_of_children(&node_id); 459 + } 460 + 461 + self.remove_node_internal(node_id) 462 + } 463 + 464 + /// Remove a `Node` from the `Tree` including all of its children recursively. 465 + fn remove_node_drop_children(&mut self, node_id: NodeId) -> Node<T> { 466 + let children = self 467 + .get_mut(&node_id) 468 + .expect("Tree::remove_node_drop_children: Expecting node_id to be valid.") 469 + .take_children(); 470 + 471 + for child in children { 472 + self.remove_node_drop_children(child); 473 + } 474 + self.remove_node_internal(node_id) 475 + } 476 + 477 + /// Remove a `node` from the `Tree` and leave all of its children in the `Tree` 478 + fn remove_node_orphan_children(&mut self, node_id: NodeId) -> Node<T> { 479 + self.clear_parent_of_children(&node_id); 480 + self.remove_node_internal(node_id) 481 + } 482 + 483 + /// Moves a `Node` in the `Tree`, via the provided `MoveBehavior` 484 + /// 485 + /// # Errors 486 + /// 487 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 488 + /// 489 + /// # Panics 490 + /// 491 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 492 + /// be a bug in `Sakura` 493 + /// 494 + #[allow(clippy::needless_pass_by_value)] 495 + pub fn move_node( 496 + &mut self, 497 + node_id: &NodeId, 498 + behavior: MoveBehavior, 499 + ) -> Result<(), NodeIdError> { 500 + self.is_valid_node_id(node_id)?; 501 + 502 + match behavior { 503 + MoveBehavior::ToRoot => { 504 + self.move_node_to_root(node_id); 505 + Ok(()) 506 + } 507 + MoveBehavior::ToParent(parent_id) => { 508 + self.move_node_to_parent(node_id, parent_id); 509 + Ok(()) 510 + } 511 + } 512 + } 513 + 514 + fn move_node_to_parent(&mut self, node_id: &NodeId, parent_id: &NodeId) { 515 + if let Some(subtree_root_id) = self 516 + .find_subtree_root_between_ids(parent_id, node_id) 517 + .cloned() 518 + { 519 + // node_id is above parent_id, this is a move "down" the tree 520 + let root = self.root.clone(); 521 + 522 + if root.as_ref() == Some(node_id) { 523 + // We're moving the root down the tree. 524 + // Also we know the root exists. 525 + 526 + // Detach subtree_root from node. 527 + self.detach_from_parent(node_id, &subtree_root_id); 528 + 529 + // Set subtree_root as Tree root. 530 + self.clear_parent(&subtree_root_id); 531 + self.root = Some(subtree_root_id); 532 + } else { 533 + // We're moving some other node down the tree. 534 + 535 + if let Some(old_parent) = self 536 + .get(node_id) 537 + .expect("Tree::move_node_to_parent: Expecting valid node_id") 538 + .parent() 539 + .cloned() 540 + { 541 + // Detach from old parent. 542 + self.detach_from_parent(&old_parent, node_id); 543 + 544 + //Connect old parent and subtree root. 545 + self.set_as_parent_and_child(&old_parent, &subtree_root_id); 546 + } else { 547 + // Node is orphaned, need to set subtree_root's parent to None (same as node's). 548 + 549 + self.clear_parent(&subtree_root_id); 550 + } 551 + 552 + // Detach subtree_root from node. 553 + self.detach_from_parent(node_id, &subtree_root_id); 554 + } 555 + } else { 556 + // this is a move "across" or "up" the tree 557 + 558 + // detach from old parent 559 + 560 + if let Some(old_parent) = self 561 + .get(node_id) 562 + .expect("Tree::move_node_to_parent: Expecting valid node_id") 563 + .parent() 564 + .cloned() 565 + { 566 + self.detach_from_parent(&old_parent, node_id); 567 + } 568 + } 569 + self.set_as_parent_and_child(parent_id, node_id); 570 + } 571 + 572 + /// Sorts the children of a `Node`, in-place, using compare to compare 573 + /// the nodes 574 + /// 575 + /// This sort is stable and O(n log n) worst case but allocates 576 + /// approximately 2 * n where n is the length of children 577 + /// 578 + /// # Errors 579 + /// 580 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 581 + /// 582 + /// # Panics 583 + /// 584 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 585 + /// be a bug in `Sakura` 586 + /// 587 + /// ``` 588 + /// use sakura::*; 589 + /// use sakura::InsertBehavior::*; 590 + /// 591 + /// let mut tree: Tree<i32> = Tree::new(); 592 + /// 593 + /// let root_id = tree.insert(Node::new(100), AsRoot).unwrap(); 594 + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 595 + /// tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 596 + /// tree.insert(Node::new(0), UnderNode(&root_id)).unwrap(); 597 + /// 598 + /// tree.sort_children_by(&root_id, |a, b| a.data().cmp(b.data())).unwrap(); 599 + /// 600 + /// # for (i, id) in tree.get(&root_id).unwrap().children().iter().enumerate() { 601 + /// # assert_eq!(*tree.get(&id).unwrap().data(), i as i32); 602 + /// # } 603 + /// ``` 604 + pub fn sort_children_by<F>( 605 + &mut self, 606 + node_id: &NodeId, 607 + mut compare: F, 608 + ) -> Result<(), NodeIdError> 609 + where 610 + F: FnMut(&Node<T>, &Node<T>) -> Ordering, 611 + { 612 + self.is_valid_node_id(node_id)?; 613 + 614 + let mut children = self 615 + .get_mut(node_id) 616 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id") 617 + .take_children(); 618 + 619 + children.sort_by(|a, b| { 620 + compare( 621 + self.get(a) 622 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id"), 623 + self.get(b) 624 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id"), 625 + ) 626 + }); 627 + 628 + self.get_mut(node_id) 629 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id") 630 + .set_children(children); 631 + 632 + Ok(()) 633 + } 634 + 635 + /// Sorts the children of a `Node`, in-place, using their data. 636 + /// 637 + /// This sort is stable and O(n log n) worst case but allocates 638 + /// approximately 2 * n where n is the length of children 639 + /// 640 + /// # Errors 641 + /// 642 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 643 + /// 644 + /// # Panics 645 + /// 646 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 647 + /// be a bug in `Sakura` 648 + /// 649 + /// ``` 650 + /// use sakura::*; 651 + /// use sakura::InsertBehavior::*; 652 + /// 653 + /// let mut tree: Tree<i32> = Tree::new(); 654 + /// 655 + /// let root_id = tree.insert(Node::new(100), AsRoot).unwrap(); 656 + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 657 + /// tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 658 + /// tree.insert(Node::new(0), UnderNode(&root_id)).unwrap(); 659 + /// 660 + /// tree.sort_children_by_data(&root_id).unwrap(); 661 + /// 662 + /// # for (i, id) in tree.get(&root_id).unwrap().children().iter().enumerate() { 663 + /// # assert_eq!(*tree.get(&id).unwrap().data(), i as i32); 664 + /// # } 665 + /// ``` 666 + /// 667 + pub fn sort_children_by_data(&mut self, node_id: &NodeId) -> Result<(), NodeIdError> 668 + where 669 + T: Ord, 670 + { 671 + self.is_valid_node_id(node_id)?; 672 + 673 + let mut children = self 674 + .get_mut(node_id) 675 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id") 676 + .take_children(); 677 + 678 + children.sort_by_key(|a| { 679 + self.get(a) 680 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id") 681 + }); 682 + 683 + self.get_mut(node_id) 684 + .expect("Tree::sort_children_by: expecting to be passed in a valid node_id") 685 + .set_children(children); 686 + 687 + Ok(()) 688 + } 689 + 690 + /// Returns an `Ancestors` iterator 691 + /// 692 + /// # Errors 693 + /// 694 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 695 + /// 696 + /// # Panics 697 + /// 698 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 699 + /// be a bug in `Sakura` 700 + /// 701 + /// ``` 702 + /// use sakura::*; 703 + /// use sakura::InsertBehavior::*; 704 + /// 705 + /// let mut tree: Tree<i32> = Tree::new(); 706 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 707 + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 708 + /// 709 + /// let mut ancestors = tree.ancestors(&node_1).unwrap(); 710 + /// 711 + /// # assert_eq!(ancestors.next().unwrap().data(), &0); 712 + /// # assert!(ancestors.next().is_none()); 713 + /// ``` 714 + pub fn ancestors(&self, node_id: &NodeId) -> Result<Ancestors<'_, T>, NodeIdError> { 715 + self.is_valid_node_id(node_id)?; 716 + Ok(Ancestors::new(self, node_id.clone())) 717 + } 718 + 719 + /// Returns an `AncestorIds` iterator 720 + /// 721 + /// 722 + /// # Errors 723 + /// 724 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 725 + /// 726 + /// # Panics 727 + /// 728 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 729 + /// be a bug in `Sakura` 730 + /// 731 + /// 732 + /// ``` 733 + /// use sakura::*; 734 + /// use sakura::InsertBehavior::*; 735 + /// 736 + /// let mut tree: Tree<i32> = Tree::new(); 737 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 738 + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 739 + /// 740 + /// let mut ancestor_ids = tree.ancestor_ids(&node_1).unwrap(); 741 + /// 742 + /// # assert_eq!(ancestor_ids.next().unwrap(), &root_id); 743 + /// # assert!(ancestor_ids.next().is_none()); 744 + /// ``` 745 + /// 746 + pub fn ancestor_ids(&self, node_id: &NodeId) -> Result<AncestorsIds<'_, T>, NodeIdError> { 747 + self.is_valid_node_id(node_id)?; 748 + 749 + Ok(AncestorsIds::new(self, node_id.clone())) 750 + } 751 + 752 + /// Returns an `Children` iterator for a given `NodeId` 753 + /// 754 + /// # Errors 755 + /// 756 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 757 + /// 758 + /// # Panics 759 + /// 760 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 761 + /// be a bug in `Sakura` 762 + /// 763 + /// ``` 764 + /// use sakura::*; 765 + /// use sakura::InsertBehavior::*; 766 + /// 767 + /// let mut tree: Tree<i32> = Tree::new(); 768 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 769 + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 770 + /// 771 + /// let mut children = tree.children(&root_id).unwrap(); 772 + /// 773 + /// # assert_eq!(children.next().unwrap().data(), &1); 774 + /// # assert!(children.next().is_none()); 775 + /// ``` 776 + pub fn children(&self, node_id: &NodeId) -> Result<Children<'_, T>, NodeIdError> { 777 + self.is_valid_node_id(node_id)?; 778 + Ok(Children::new(self, node_id)) 779 + } 780 + 781 + /// Returns an `Children` iterator for a given `NodeId` 782 + /// 783 + /// # Errors 784 + /// 785 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 786 + /// 787 + /// # Panics 788 + /// 789 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 790 + /// be a bug in `Sakura` 791 + /// 792 + /// ``` 793 + /// use sakura::*; 794 + /// use sakura::InsertBehavior::*; 795 + /// 796 + /// let mut tree: Tree<i32> = Tree::new(); 797 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 798 + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 799 + /// 800 + /// let mut children_ids = tree.children_ids(&root_id).unwrap(); 801 + /// 802 + /// # assert_eq!(children_ids.next().unwrap(), &node_1); 803 + /// # assert!(children_ids.next().is_none()); 804 + /// ``` 805 + pub fn children_ids(&self, node_id: &NodeId) -> Result<ChildrenIds<'_>, NodeIdError> { 806 + self.is_valid_node_id(node_id)?; 807 + Ok(ChildrenIds::new(self, node_id)) 808 + } 809 + 810 + /// Returns a `PreOrderTraversal` iterator 811 + /// 812 + /// # Errors 813 + /// 814 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 815 + /// 816 + /// # Panics 817 + /// 818 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 819 + /// be a bug in `Sakura` 820 + /// 821 + /// ``` 822 + /// use sakura::*; 823 + /// use sakura::InsertBehavior::*; 824 + /// 825 + /// let mut tree: Tree<i32> = Tree::new(); 826 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 827 + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 828 + /// 829 + /// let mut nodes = tree.traverse_pre_order(&root_id).unwrap(); 830 + /// 831 + /// # assert_eq!(nodes.next().unwrap().data(), &0); 832 + /// # assert_eq!(nodes.next().unwrap().data(), &1); 833 + /// # assert!(nodes.next().is_none()); 834 + /// ``` 835 + /// 836 + pub fn traverse_pre_order( 837 + &self, 838 + node_id: &NodeId, 839 + ) -> Result<PreOrderTraversal<'_, T>, NodeIdError> { 840 + self.is_valid_node_id(node_id)?; 841 + 842 + Ok(PreOrderTraversal::new(self, node_id.clone())) 843 + } 844 + 845 + /// Returns a `PreOrderTraversalIds` iterator 846 + /// 847 + /// # Errors 848 + /// 849 + /// Can error if the given `NodeId` is not valid (i.e. it was removed from the `Tree`.) 850 + /// 851 + /// # Panics 852 + /// 853 + /// Can panic if the `NodeId` does not exist in the `Tree`, but this would 854 + /// be a bug in `Sakura` 855 + /// 856 + /// ``` 857 + /// use sakura::*; 858 + /// use sakura::InsertBehavior::*; 859 + /// 860 + /// let mut tree: Tree<i32> = Tree::new(); 861 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 862 + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 863 + /// 864 + /// let mut nodes = tree.traverse_pre_order_ids(&root_id).unwrap(); 865 + /// 866 + /// assert_eq!(tree.get(&nodes.next().unwrap()).unwrap().data(), &0); 867 + /// assert_eq!(tree.get(&nodes.next().unwrap()).unwrap().data(), &1); 868 + /// assert!(nodes.next().is_none()); 869 + /// ``` 870 + /// 871 + pub fn traverse_pre_order_ids( 872 + &self, 873 + node_id: &NodeId, 874 + ) -> Result<PreOrderTraversalIds<'_, T>, NodeIdError> { 875 + self.is_valid_node_id(node_id)?; 876 + 877 + Ok(PreOrderTraversalIds::new(self, node_id.clone())) 878 + } 879 + 880 + fn move_node_to_root(&mut self, node_id: &NodeId) { 881 + let old_root = self.root.clone(); 882 + 883 + if let Some(parent_id) = self 884 + .get(node_id) 885 + .expect("Tree::move_node_to_root Expected a valid NodeId") 886 + .parent 887 + .clone() 888 + { 889 + self.detach_from_parent(&parent_id, node_id); 890 + } 891 + 892 + self.clear_parent(node_id); 893 + 894 + self.root = Some(node_id.clone()); 895 + 896 + if let Some(old_root) = old_root { 897 + self.move_node_to_parent(&old_root, node_id); 898 + } 899 + } 900 + 901 + fn insert_with_parent(&mut self, child: Node<T>, parent_id: &NodeId) -> NodeId { 902 + let new_child_id = self.insert_new_node(child); 903 + self.set_as_parent_and_child(parent_id, &new_child_id); 904 + new_child_id 905 + } 906 + 907 + fn set_root(&mut self, new_root: Node<T>) -> NodeId { 908 + let new_root_id = self.insert_new_node(new_root); 909 + 910 + if let Some(current_root_node_id) = self.root.clone() { 911 + self.set_as_parent_and_child(&new_root_id, &current_root_node_id); 912 + } 913 + 914 + self.root = Some(new_root_id.clone()); 915 + 916 + new_root_id 917 + } 918 + 919 + fn find_subtree_root_between_ids<'a>( 920 + &'a self, 921 + lower_id: &'a NodeId, 922 + upper_id: &'a NodeId, 923 + ) -> Option<&'a NodeId> { 924 + if let Some(lower_parent) = self.get(lower_id).unwrap().parent() { 925 + if lower_parent == upper_id { 926 + return Some(lower_id); 927 + } 928 + return self.find_subtree_root_between_ids(lower_parent, upper_id); 929 + } 930 + 931 + None 932 + } 933 + 934 + fn set_as_parent_and_child(&mut self, parent_id: &NodeId, child_id: &NodeId) { 935 + self.get_mut(parent_id) 936 + .expect("Tree::set_as_parent_and_child: parent_id should be inside the Tree.") 937 + .add_child(child_id.clone()); 938 + 939 + self.get_mut(child_id) 940 + .expect("Tree::set_as_parent_and_child: child_id should be inside the Tree.") 941 + .set_parent(Some(parent_id.clone())); 942 + } 943 + 944 + fn detach_from_parent(&mut self, parent_id: &NodeId, node_id: &NodeId) { 945 + self.get_mut(parent_id) 946 + .expect("Tree::detach_from_parent: parent_id must be present in tree") 947 + .children_mut() 948 + .retain(|child_id| *child_id != *node_id); 949 + } 950 + 951 + fn insert_new_node(&mut self, new_node: Node<T>) -> NodeId { 952 + if self.free_ids.is_empty() { 953 + let new_node_idx = self.nodes.len(); 954 + self.nodes.push(Some(new_node)); 955 + NodeId::new(new_node_idx) 956 + } else { 957 + let new_node_id = self 958 + .free_ids 959 + .pop() 960 + .expect("Tree::insert_new_node: Couldn't pop from vec with len() > 0."); 961 + 962 + self.nodes.push(Some(new_node)); 963 + self.nodes.swap_remove(new_node_id.index as usize); 964 + new_node_id 965 + } 966 + } 967 + 968 + fn is_valid_node_id(&self, node_id: &NodeId) -> Result<(), NodeIdError> { 969 + let idx = node_id.index as usize; 970 + 971 + assert!( 972 + idx <= self.nodes.len(), 973 + "NodeId: {node_id:?} is out of bounds. This is a bug inside 974 + Sakura.", 975 + ); 976 + 977 + if self.nodes.get(idx).is_none() { 978 + return Err(NodeIdError::NodeIdNoLongerValid); 979 + } 980 + 981 + Ok(()) 982 + } 983 + 984 + // We want to have the node_id be consumed by this remove function. 985 + #[allow(clippy::needless_pass_by_value)] 986 + fn remove_node_internal(&mut self, node_id: NodeId) -> Node<T> { 987 + if let Some(root_id) = &self.root 988 + && node_id == *root_id 989 + { 990 + self.root = None; 991 + } 992 + 993 + let mut node = self.take_node(node_id.clone()); 994 + 995 + if let Some(parent_id) = node.parent() { 996 + self.get_mut(parent_id) 997 + .expect( 998 + "Tree::remove_node_internal: expecting 999 + parent_id to be a valid node_id!", 1000 + ) 1001 + .children_mut() 1002 + .retain(|child_id| *child_id != node_id); 1003 + } 1004 + 1005 + node.children_mut().clear(); 1006 + node.set_parent(None); 1007 + 1008 + node 1009 + } 1010 + 1011 + fn take_node(&mut self, node_id: NodeId) -> Node<T> { 1012 + self.nodes.push(None); 1013 + 1014 + let node = self 1015 + .nodes 1016 + .swap_remove(node_id.index as usize) 1017 + .expect("Tree::take_node: expecting node_id to be a valid node_id!"); 1018 + 1019 + self.free_ids.push(node_id); 1020 + 1021 + node 1022 + } 1023 + 1024 + fn clear_parent(&mut self, node_id: &NodeId) { 1025 + self.set_parent(node_id, None); 1026 + } 1027 + 1028 + fn set_parent(&mut self, node_id: &NodeId, parent_id: Option<NodeId>) { 1029 + self.get_mut(node_id) 1030 + .expect( 1031 + "Tree::set_parent: expecting node_id to 1032 + be present inside tree!", 1033 + ) 1034 + .set_parent(parent_id); 1035 + } 1036 + 1037 + fn clear_parent_of_children(&mut self, node_id: &NodeId) { 1038 + self.set_parent_of_children(node_id, None); 1039 + } 1040 + 1041 + fn set_parent_of_children(&mut self, node_id: &NodeId, new_parent: Option<&NodeId>) { 1042 + for child_id in self 1043 + .get(node_id) 1044 + .expect("Tree::set_parent_of_child: expect node_id to be a valid node inside tree.") 1045 + .children 1046 + .clone() 1047 + { 1048 + self.set_parent(&child_id, new_parent.cloned()); 1049 + } 1050 + } 1051 + } 1052 + 1053 + impl<T: std::fmt::Debug> Tree<T> { 1054 + /// Write formatted tree representation and nodes with debug formatting. 1055 + /// 1056 + /// 1057 + /// # Errors 1058 + /// 1059 + /// Function can error if something goes wrong during debug! 1060 + /// 1061 + /// # Panics 1062 + /// 1063 + /// Function can error if something goes wrong during debug! 1064 + /// 1065 + /// ``` 1066 + /// use sakura::Tree; 1067 + /// use sakura::Node; 1068 + /// use sakura::InsertBehavior::*; 1069 + /// 1070 + /// let mut tree = Tree::<i32>::new(); 1071 + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1072 + /// let first_child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1073 + /// let _ = tree.insert(Node::new(2), UnderNode(&first_child_id)).unwrap(); 1074 + /// let _ = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap(); 1075 + /// let mut s = String::new(); 1076 + /// tree.write_formatted(&mut s).unwrap(); 1077 + /// assert_eq!(&s, "\ 1078 + /// 0 1079 + /// ├── 1 1080 + /// │ └── 2 1081 + /// └── 3 1082 + /// "); 1083 + /// ``` 1084 + /// 1085 + /// Writes nothing if the tree is empty. 1086 + /// 1087 + /// ``` 1088 + /// use sakura::Tree; 1089 + /// 1090 + /// let tree = Tree::<i32>::new(); 1091 + /// let mut s = String::new(); 1092 + /// tree.write_formatted(&mut s).unwrap(); 1093 + /// # assert_eq!(&s, ""); 1094 + /// ``` 1095 + pub fn write_formatted<W: std::fmt::Write>(&self, w: &mut W) -> std::fmt::Result { 1096 + if let Some(node_id) = self.root_node_id() { 1097 + let childn = 0; 1098 + let level = 0; 1099 + let last = vec![]; 1100 + let mut stack = vec![(node_id, childn, level, last)]; 1101 + while let Some((node_id, childn, level, last)) = stack.pop() { 1102 + debug_assert_eq!( 1103 + last.len(), 1104 + level, 1105 + "each previous level should indicate whether it has reached the last node" 1106 + ); 1107 + let node = self 1108 + .get(node_id) 1109 + .expect("getting node of existing node ref id"); 1110 + if childn == 0 { 1111 + for i in 1..level { 1112 + if last[i - 1] { 1113 + write!(w, " ")?; 1114 + } else { 1115 + write!(w, "│ ")?; 1116 + } 1117 + } 1118 + if level > 0 { 1119 + if last[level - 1] { 1120 + write!(w, "└── ")?; 1121 + } else { 1122 + write!(w, "├── ")?; 1123 + } 1124 + } 1125 + writeln!(w, "{:?}", node.data())?; 1126 + } 1127 + let mut children = node.children().iter().skip(childn); 1128 + if let Some(child_id) = children.next() { 1129 + let mut next_last = last.clone(); 1130 + if children.next().is_some() { 1131 + stack.push((node_id, childn + 1, level, last)); 1132 + next_last.push(false); 1133 + } else { 1134 + next_last.push(true); 1135 + } 1136 + stack.push((child_id, 0, level + 1, next_last)); 1137 + } 1138 + } 1139 + } 1140 + Ok(()) 1141 + } 1142 + } 1143 + 1144 + #[cfg(test)] 1145 + mod tree_builder_tests { 1146 + use super::super::Node; 1147 + use super::TreeBuilder; 1148 + 1149 + #[test] 1150 + fn test_new() { 1151 + let tb: TreeBuilder<i32> = TreeBuilder::new(); 1152 + assert!(tb.root.is_none()); 1153 + assert_eq!(tb.node_capacity, 0); 1154 + assert_eq!(tb.swap_capacity, 0); 1155 + } 1156 + 1157 + #[test] 1158 + fn test_with_root() { 1159 + let tb: TreeBuilder<i32> = TreeBuilder::new().with_root(Node::new(5)); 1160 + 1161 + assert_eq!(tb.root.unwrap().data(), &5); 1162 + assert_eq!(tb.node_capacity, 0); 1163 + assert_eq!(tb.swap_capacity, 0); 1164 + } 1165 + 1166 + #[test] 1167 + fn test_with_node_capacity() { 1168 + let tb: TreeBuilder<i32> = TreeBuilder::new().with_node_capacity(10); 1169 + 1170 + assert!(tb.root.is_none()); 1171 + assert_eq!(tb.node_capacity, 10); 1172 + assert_eq!(tb.swap_capacity, 0); 1173 + } 1174 + 1175 + #[test] 1176 + fn test_with_swap_capacity() { 1177 + let tb: TreeBuilder<i32> = TreeBuilder::new().with_swap_capacity(10); 1178 + 1179 + assert!(tb.root.is_none()); 1180 + assert_eq!(tb.node_capacity, 0); 1181 + assert_eq!(tb.swap_capacity, 10); 1182 + } 1183 + 1184 + #[test] 1185 + fn test_with_all_settings() { 1186 + let tb: TreeBuilder<i32> = TreeBuilder::new() 1187 + .with_root(Node::new(5)) 1188 + .with_node_capacity(10) 1189 + .with_swap_capacity(3); 1190 + 1191 + assert_eq!(tb.root.unwrap().data(), &5); 1192 + assert_eq!(tb.node_capacity, 10); 1193 + assert_eq!(tb.swap_capacity, 3); 1194 + } 1195 + 1196 + #[test] 1197 + fn test_build() { 1198 + let tree = TreeBuilder::new() 1199 + .with_root(Node::new(5)) 1200 + .with_node_capacity(10) 1201 + .with_swap_capacity(3) 1202 + .build(); 1203 + 1204 + let root = tree.get(tree.root_node_id().unwrap()).unwrap(); 1205 + 1206 + assert_eq!(root.data(), &5); 1207 + assert_eq!(tree.capacity(), 10); 1208 + assert_eq!(tree.free_ids.capacity(), 3); 1209 + } 1210 + } 1211 + 1212 + #[cfg(test)] 1213 + #[allow(clippy::similar_names)] 1214 + mod tree_tests { 1215 + use crate::InsertBehavior; 1216 + use crate::MoveBehavior; 1217 + use crate::RemoveBehavior; 1218 + 1219 + use super::super::Node; 1220 + use super::super::NodeId; 1221 + use super::Tree; 1222 + use super::TreeBuilder; 1223 + 1224 + #[test] 1225 + fn test_new() { 1226 + let tree: Tree<i32> = Tree::new(); 1227 + 1228 + assert_eq!(tree.root, None); 1229 + assert_eq!(tree.nodes.len(), 0); 1230 + assert_eq!(tree.free_ids.len(), 0); 1231 + } 1232 + 1233 + #[test] 1234 + fn test_get() { 1235 + let tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1236 + 1237 + let root_id = tree.root.clone().unwrap(); 1238 + let root = tree.get(&root_id).unwrap(); 1239 + 1240 + assert_eq!(root.data(), &5); 1241 + } 1242 + 1243 + #[test] 1244 + fn test_get_mut() { 1245 + let mut tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1246 + 1247 + let root_id = tree.root.clone().unwrap(); 1248 + 1249 + { 1250 + let root = tree.get(&root_id).unwrap(); 1251 + assert_eq!(root.data(), &5); 1252 + } 1253 + 1254 + { 1255 + let root = tree.get_mut(&root_id).unwrap(); 1256 + *root.data_mut() = 6; 1257 + } 1258 + 1259 + let root = tree.get(&root_id).unwrap(); 1260 + assert_eq!(root.data(), &6); 1261 + } 1262 + 1263 + #[test] 1264 + fn test_set_root() { 1265 + use InsertBehavior::*; 1266 + 1267 + let a = 5; 1268 + let b = 6; 1269 + let node_a = Node::new(a); 1270 + let node_b = Node::new(b); 1271 + 1272 + let mut tree = TreeBuilder::new().build(); 1273 + 1274 + let node_a_id = tree.insert(node_a, AsRoot).unwrap(); 1275 + let root_id = tree.root.clone().unwrap(); 1276 + assert_eq!(node_a_id, root_id); 1277 + 1278 + { 1279 + let node_a_ref = tree.get(&node_a_id).unwrap(); 1280 + let root_ref = tree.get(&root_id).unwrap(); 1281 + assert_eq!(node_a_ref.data(), &a); 1282 + assert_eq!(root_ref.data(), &a); 1283 + } 1284 + 1285 + let node_b_id = tree.insert(node_b, AsRoot).unwrap(); 1286 + let root_id = tree.root.clone().unwrap(); 1287 + assert_eq!(node_b_id, root_id); 1288 + 1289 + { 1290 + let node_b_ref = tree.get(&node_b_id).unwrap(); 1291 + let root_ref = tree.get(&root_id).unwrap(); 1292 + assert_eq!(node_b_ref.data(), &b); 1293 + assert_eq!(root_ref.data(), &b); 1294 + 1295 + let node_b_child_id = node_b_ref.children().first().unwrap(); 1296 + let node_b_child_ref = tree.get(node_b_child_id).unwrap(); 1297 + assert_eq!(node_b_child_ref.data(), &a); 1298 + } 1299 + } 1300 + 1301 + #[test] 1302 + fn test_root_node_id() { 1303 + let tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1304 + 1305 + let root_id = tree.root.clone().unwrap(); 1306 + let root_node_id = tree.root_node_id().unwrap(); 1307 + 1308 + assert_eq!(&root_id, root_node_id); 1309 + } 1310 + 1311 + #[test] 1312 + fn test_insert_with_parent() { 1313 + use InsertBehavior::*; 1314 + 1315 + let a = 1; 1316 + let b = 2; 1317 + let r = 5; 1318 + 1319 + let mut tree = TreeBuilder::new().with_root(Node::new(r)).build(); 1320 + 1321 + let node_a = Node::new(a); 1322 + let node_b = Node::new(b); 1323 + 1324 + let root_id = tree.root.clone().unwrap(); 1325 + let node_a_id = tree.insert(node_a, UnderNode(&root_id)).unwrap(); 1326 + let node_b_id = tree.insert(node_b, UnderNode(&root_id)).unwrap(); 1327 + 1328 + let node_a_ref = tree.get(&node_a_id).unwrap(); 1329 + let node_b_ref = tree.get(&node_b_id).unwrap(); 1330 + assert_eq!(node_a_ref.data(), &a); 1331 + assert_eq!(node_b_ref.data(), &b); 1332 + 1333 + assert_eq!(node_a_ref.parent().unwrap().clone(), root_id); 1334 + assert_eq!(node_b_ref.parent().unwrap().clone(), root_id); 1335 + 1336 + let root_node_ref = tree.get(&root_id).unwrap(); 1337 + let root_children: &Vec<NodeId> = root_node_ref.children(); 1338 + 1339 + let child_1_id = root_children.first().unwrap(); 1340 + let child_2_id = root_children.get(1).unwrap(); 1341 + 1342 + let child_1_ref = tree.get(child_1_id).unwrap(); 1343 + let child_2_ref = tree.get(child_2_id).unwrap(); 1344 + 1345 + assert_eq!(child_1_ref.data(), &a); 1346 + assert_eq!(child_2_ref.data(), &b); 1347 + } 1348 + 1349 + #[test] 1350 + fn test_remove_node_lift_children() { 1351 + use InsertBehavior::*; 1352 + use RemoveBehavior::*; 1353 + 1354 + let mut tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1355 + 1356 + let root_id = tree.root.clone().unwrap(); 1357 + 1358 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1359 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1360 + let node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap(); 1361 + 1362 + let node_1 = tree.remove_node(node_1_id.clone(), LiftChildren).unwrap(); 1363 + 1364 + assert_eq!(Some(&root_id), tree.root_node_id()); 1365 + 1366 + assert_eq!(node_1.data(), &1); 1367 + assert_eq!(node_1.children().len(), 0); 1368 + assert!(node_1.parent().is_none()); 1369 + assert!(tree.get(&node_1_id).is_err()); 1370 + 1371 + let root_ref = tree.get(&root_id).unwrap(); 1372 + let node_2_ref = tree.get(&node_2_id).unwrap(); 1373 + let node_3_ref = tree.get(&node_3_id).unwrap(); 1374 + 1375 + assert_eq!(node_2_ref.data(), &2); 1376 + assert_eq!(node_3_ref.data(), &3); 1377 + 1378 + assert_eq!(node_2_ref.parent().unwrap(), &root_id); 1379 + assert_eq!(node_3_ref.parent().unwrap(), &root_id); 1380 + 1381 + assert!(root_ref.children().contains(&node_2_id)); 1382 + assert!(root_ref.children().contains(&node_3_id)); 1383 + } 1384 + 1385 + #[test] 1386 + fn test_remove_node_orphan_children() { 1387 + use InsertBehavior::*; 1388 + use RemoveBehavior::*; 1389 + 1390 + let mut tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1391 + 1392 + let root_id = tree.root.clone().unwrap(); 1393 + 1394 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1395 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1396 + let node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap(); 1397 + 1398 + let node_1 = tree.remove_node(node_1_id.clone(), OrphanChildren).unwrap(); 1399 + 1400 + assert_eq!(Some(&root_id), tree.root_node_id()); 1401 + 1402 + assert_eq!(node_1.data(), &1); 1403 + assert_eq!(node_1.children().len(), 0); 1404 + assert!(node_1.parent().is_none()); 1405 + assert!(tree.get(&node_1_id).is_err()); 1406 + 1407 + let node_2_ref = tree.get(&node_2_id).unwrap(); 1408 + let node_3_ref = tree.get(&node_3_id).unwrap(); 1409 + 1410 + assert_eq!(node_2_ref.data(), &2); 1411 + assert_eq!(node_3_ref.data(), &3); 1412 + 1413 + assert!(node_2_ref.parent().is_none()); 1414 + assert!(node_3_ref.parent().is_none()); 1415 + } 1416 + 1417 + #[test] 1418 + fn test_remove_root() { 1419 + use RemoveBehavior::*; 1420 + 1421 + let mut tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1422 + 1423 + let root_id = tree.root.clone().unwrap(); 1424 + tree.remove_node(root_id, OrphanChildren).unwrap(); 1425 + assert_eq!(None, tree.root_node_id()); 1426 + 1427 + let mut tree = TreeBuilder::new().with_root(Node::new(5)).build(); 1428 + 1429 + let root_id = tree.root.clone().unwrap(); 1430 + tree.remove_node(root_id, LiftChildren).unwrap(); 1431 + assert_eq!(None, tree.root_node_id()); 1432 + } 1433 + 1434 + #[test] 1435 + fn test_move_node_to_parent() { 1436 + use InsertBehavior::*; 1437 + use MoveBehavior::*; 1438 + 1439 + let mut tree = Tree::new(); 1440 + 1441 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1442 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1443 + let node_2_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1444 + let node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap(); 1445 + 1446 + // Move 3 "across" the tree. 1447 + tree.move_node(&node_3_id, ToParent(&node_2_id)).unwrap(); 1448 + assert!(tree.get(&root_id).unwrap().children().contains(&node_1_id)); 1449 + assert!(tree.get(&root_id).unwrap().children().contains(&node_2_id)); 1450 + assert!( 1451 + tree.get(&node_2_id,) 1452 + .unwrap() 1453 + .children() 1454 + .contains(&node_3_id,) 1455 + ); 1456 + 1457 + // Move 3 "up" the tree. 1458 + tree.move_node(&node_3_id, ToParent(&root_id)).unwrap(); 1459 + assert!(tree.get(&root_id).unwrap().children().contains(&node_1_id)); 1460 + assert!(tree.get(&root_id).unwrap().children().contains(&node_2_id)); 1461 + assert!(tree.get(&root_id).unwrap().children().contains(&node_3_id)); 1462 + 1463 + // Move 3 "down" (really this is across though) the tree. 1464 + tree.move_node(&node_3_id, ToParent(&node_1_id)).unwrap(); 1465 + assert!(tree.get(&root_id).unwrap().children().contains(&node_1_id)); 1466 + assert!(tree.get(&root_id).unwrap().children().contains(&node_2_id)); 1467 + assert!( 1468 + tree.get(&node_1_id,) 1469 + .unwrap() 1470 + .children() 1471 + .contains(&node_3_id,) 1472 + ); 1473 + 1474 + // Move 1 "down" the tree. 1475 + tree.move_node(&node_1_id, ToParent(&node_3_id)).unwrap(); 1476 + assert!(tree.get(&root_id).unwrap().children().contains(&node_2_id)); 1477 + assert!(tree.get(&root_id).unwrap().children().contains(&node_3_id)); 1478 + assert!( 1479 + tree.get(&node_3_id,) 1480 + .unwrap() 1481 + .children() 1482 + .contains(&node_1_id,) 1483 + ); 1484 + 1485 + // Note: node_1 is at the lowest point in the tree before these insertions. 1486 + let node_4_id = tree.insert(Node::new(4), UnderNode(&node_1_id)).unwrap(); 1487 + let node_5_id = tree.insert(Node::new(5), UnderNode(&node_4_id)).unwrap(); 1488 + 1489 + // move 3 "down" the tree 1490 + tree.move_node(&node_3_id, ToParent(&node_5_id)).unwrap(); 1491 + assert!(tree.get(&root_id).unwrap().children().contains(&node_2_id)); 1492 + assert!(tree.get(&root_id).unwrap().children().contains(&node_1_id)); 1493 + assert!( 1494 + tree.get(&node_1_id,) 1495 + .unwrap() 1496 + .children() 1497 + .contains(&node_4_id,) 1498 + ); 1499 + assert!( 1500 + tree.get(&node_4_id,) 1501 + .unwrap() 1502 + .children() 1503 + .contains(&node_5_id,) 1504 + ); 1505 + assert!( 1506 + tree.get(&node_5_id,) 1507 + .unwrap() 1508 + .children() 1509 + .contains(&node_3_id,) 1510 + ); 1511 + 1512 + // move root "down" the tree 1513 + tree.move_node(&root_id, ToParent(&node_2_id)).unwrap(); 1514 + assert!(tree.get(&node_2_id).unwrap().children().contains(&root_id)); 1515 + assert!(tree.get(&root_id).unwrap().children().contains(&node_1_id)); 1516 + assert!( 1517 + tree.get(&node_1_id,) 1518 + .unwrap() 1519 + .children() 1520 + .contains(&node_4_id,) 1521 + ); 1522 + assert!( 1523 + tree.get(&node_4_id,) 1524 + .unwrap() 1525 + .children() 1526 + .contains(&node_5_id,) 1527 + ); 1528 + assert!( 1529 + tree.get(&node_5_id,) 1530 + .unwrap() 1531 + .children() 1532 + .contains(&node_3_id,) 1533 + ); 1534 + assert_eq!(tree.root_node_id(), Some(&node_2_id)); 1535 + } 1536 + 1537 + #[test] 1538 + fn test_move_node_to_root() { 1539 + use InsertBehavior::*; 1540 + 1541 + // test move with existing root 1542 + { 1543 + let mut tree = Tree::new(); 1544 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1545 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1546 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1547 + 1548 + tree.move_node_to_root(&node_2_id); 1549 + 1550 + assert_eq!(tree.root_node_id(), Some(&node_2_id)); 1551 + assert!(tree.get(&node_2_id).unwrap().children().contains(&root_id)); 1552 + assert!( 1553 + !tree 1554 + .get(&node_1_id,) 1555 + .unwrap() 1556 + .children() 1557 + .contains(&node_2_id,) 1558 + ); 1559 + } 1560 + 1561 + // Test move with existing root and with orphan. 1562 + { 1563 + let mut tree = Tree::new(); 1564 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1565 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1566 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1567 + 1568 + tree.remove_node_orphan_children(node_1_id); 1569 + tree.move_node_to_root(&node_2_id); 1570 + 1571 + assert_eq!(tree.root_node_id(), Some(&node_2_id)); 1572 + assert!(tree.get(&node_2_id).unwrap().children().contains(&root_id)); 1573 + assert_eq!(tree.get(&root_id).unwrap().children().len(), 0); 1574 + } 1575 + 1576 + // Test move without root and with orphan. 1577 + { 1578 + let mut tree = Tree::new(); 1579 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1580 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1581 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1582 + 1583 + tree.remove_node_orphan_children(root_id); 1584 + tree.move_node_to_root(&node_1_id); 1585 + 1586 + assert_eq!(tree.root_node_id(), Some(&node_1_id)); 1587 + assert!( 1588 + tree.get(&node_1_id,) 1589 + .unwrap() 1590 + .children() 1591 + .contains(&node_2_id,) 1592 + ); 1593 + assert_eq!(tree.get(&node_1_id).unwrap().children().len(), 1); 1594 + } 1595 + } 1596 + 1597 + #[test] 1598 + fn test_find_subtree_root_below_upper_id() { 1599 + use InsertBehavior::*; 1600 + 1601 + let mut tree = Tree::new(); 1602 + 1603 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1604 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1605 + let node_2_id = tree.insert(Node::new(2), UnderNode(&node_1_id)).unwrap(); 1606 + let node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap(); 1607 + let node_4_id = tree.insert(Node::new(4), UnderNode(&node_2_id)).unwrap(); 1608 + 1609 + let sub_root = tree.find_subtree_root_between_ids(&node_1_id, &root_id); 1610 + assert_eq!(sub_root, Some(&node_1_id)); 1611 + let sub_root = tree.find_subtree_root_between_ids(&root_id, &node_1_id); //invert for None 1612 + assert_eq!(sub_root, None); 1613 + 1614 + let sub_root = tree.find_subtree_root_between_ids(&node_2_id, &root_id); 1615 + assert_eq!(sub_root, Some(&node_1_id)); 1616 + let sub_root = tree.find_subtree_root_between_ids(&root_id, &node_2_id); //invert for None 1617 + assert_eq!(sub_root, None); 1618 + 1619 + let sub_root = tree.find_subtree_root_between_ids(&node_3_id, &node_1_id); 1620 + assert_eq!(sub_root, Some(&node_3_id)); 1621 + let sub_root = tree.find_subtree_root_between_ids(&node_1_id, &node_3_id); //invert for None 1622 + assert_eq!(sub_root, None); 1623 + 1624 + let sub_root = tree.find_subtree_root_between_ids(&node_4_id, &root_id); 1625 + assert_eq!(sub_root, Some(&node_1_id)); 1626 + let sub_root = tree.find_subtree_root_between_ids(&root_id, &node_4_id); //invert for None 1627 + assert_eq!(sub_root, None); 1628 + } 1629 + 1630 + #[test] 1631 + fn test_tree_height() { 1632 + use InsertBehavior::*; 1633 + use RemoveBehavior::*; 1634 + 1635 + // Empty tree. 1636 + let mut tree = Tree::new(); 1637 + assert_eq!(0, tree.height()); 1638 + 1639 + // The tree with single root node. 1640 + let root_id = tree.insert(Node::new(1), AsRoot).unwrap(); 1641 + assert_eq!(1, tree.height()); 1642 + 1643 + // Root node with single child. 1644 + let child_1_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1645 + assert_eq!(2, tree.height()); 1646 + 1647 + // Root node with two children. 1648 + let child_2_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap(); 1649 + assert_eq!(2, tree.height()); 1650 + 1651 + // Grandson. 1652 + tree.insert(Node::new(4), UnderNode(&child_1_id)).unwrap(); 1653 + assert_eq!(3, tree.height()); 1654 + 1655 + // Remove child_1 and grandchild. 1656 + tree.remove_node(child_1_id, DropChildren).unwrap(); 1657 + assert_eq!(2, tree.height()); 1658 + 1659 + // Remove child_2. 1660 + tree.remove_node(child_2_id, LiftChildren).unwrap(); 1661 + assert_eq!(1, tree.height()); 1662 + } 1663 + 1664 + #[test] 1665 + fn test_partial_eq() { 1666 + use InsertBehavior::*; 1667 + 1668 + let mut tree = Tree::new(); 1669 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); 1670 + let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1671 + tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1672 + tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap(); 1673 + 1674 + // Ensure PartialEq doesn't work when the number of used nodes are not equal. 1675 + { 1676 + let mut other = Tree::new(); 1677 + let root_id = other.insert(Node::new(0), AsRoot).unwrap(); 1678 + other.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1679 + other.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1680 + assert_ne!(tree, other); 1681 + } 1682 + 1683 + // Ensure PartialEq doesn't work when the data is not equal. 1684 + { 1685 + let mut other = Tree::new(); 1686 + let root_id = other.insert(Node::new(0), AsRoot).unwrap(); 1687 + let id = other.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1688 + other.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1689 + other.insert(Node::new(4), UnderNode(&id)).unwrap(); 1690 + assert_ne!(tree, other); 1691 + } 1692 + 1693 + // Ensure PartialEq doesn't work when the parents aren't equal. 1694 + { 1695 + let mut other = Tree::new(); 1696 + let root_id = other.insert(Node::new(0), AsRoot).unwrap(); 1697 + other.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1698 + let id = other.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1699 + other.insert(Node::new(3), UnderNode(&id)).unwrap(); 1700 + assert_ne!(tree, other); 1701 + } 1702 + 1703 + // Ensure PartialEq works even if the number of free spots in Tree. 1704 + // Node is different. 1705 + { 1706 + let mut other = Tree::new(); 1707 + let root_id = other.insert(Node::new(0), AsRoot).unwrap(); 1708 + let id = other.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1709 + other.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1710 + other.insert(Node::new(3), UnderNode(&id)).unwrap(); 1711 + let to_delete = other.insert(Node::new(42), UnderNode(&root_id)).unwrap(); 1712 + other.take_node(to_delete); 1713 + assert_ne!( 1714 + tree.nodes.iter().filter(|x| x.is_none()).count(), 1715 + other.nodes.iter().filter(|x| x.is_none()).count() 1716 + ); 1717 + assert_eq!(tree, other); 1718 + } 1719 + 1720 + // Ensure PartialEq doesn't work when the Node's index are different. 1721 + { 1722 + let mut other = Tree::new(); 1723 + let root_id = other.insert(Node::new(0), AsRoot).unwrap(); 1724 + let to_delete = other.insert(Node::new(42), UnderNode(&root_id)).unwrap(); 1725 + let id = other.insert(Node::new(1), UnderNode(&root_id)).unwrap(); 1726 + other.insert(Node::new(2), UnderNode(&root_id)).unwrap(); 1727 + other.insert(Node::new(3), UnderNode(&id)).unwrap(); 1728 + other.take_node(to_delete); 1729 + assert_ne!(tree, other); 1730 + } 1731 + } 1732 + }
+17 -16
flake.lock
··· 8 8 "rust-analyzer-src": "rust-analyzer-src" 9 9 }, 10 10 "locked": { 11 - "lastModified": 1772348640, 12 - "narHash": "sha256-caiKs7O4khFydpKyg8O8/nmvw/NfN4fn/4spageGoig=", 13 - "rev": "47c5355eaba0b08836e720d5d545c8ea1e1783db", 14 - "revCount": 2572, 15 - "type": "tarball", 16 - "url": "https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.2572%2Brev-47c5355eaba0b08836e720d5d545c8ea1e1783db/019ca881-cb35-7cd1-8b46-98117609f8b6/source.tar.gz" 11 + "lastModified": 1773471952, 12 + "narHash": "sha256-kIRggXyT8RzijtfvyRIzj+zIDWM2fnCp8t0X4BkkTVc=", 13 + "owner": "nix-community", 14 + "repo": "fenix", 15 + "rev": "a1b770adbc3f6c27485d03b90462ec414d4e1ce5", 16 + "type": "github" 17 17 }, 18 18 "original": { 19 - "type": "tarball", 20 - "url": "https://flakehub.com/f/nix-community/fenix/0.1" 19 + "owner": "nix-community", 20 + "repo": "fenix", 21 + "type": "github" 21 22 } 22 23 }, 23 24 "nixpkgs": { 24 25 "locked": { 25 - "lastModified": 1772773019, 26 - "narHash": "sha256-E1bxHxNKfDoQUuvriG71+f+s/NT0qWkImXsYZNFFfCs=", 27 - "rev": "aca4d95fce4914b3892661bcb80b8087293536c6", 28 - "revCount": 958961, 26 + "lastModified": 1773389992, 27 + "narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=", 28 + "rev": "c06b4ae3d6599a672a6210b7021d699c351eebda", 29 + "revCount": 962836, 29 30 "type": "tarball", 30 - "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.958961%2Brev-aca4d95fce4914b3892661bcb80b8087293536c6/019cc7ad-65c5-7d4e-9860-842d09d8f4fa/source.tar.gz" 31 + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.962836%2Brev-c06b4ae3d6599a672a6210b7021d699c351eebda/019cec4e-dd38-75a8-9d2d-0d91492115c9/source.tar.gz" 31 32 }, 32 33 "original": { 33 34 "type": "tarball", ··· 43 44 "rust-analyzer-src": { 44 45 "flake": false, 45 46 "locked": { 46 - "lastModified": 1772310333, 47 - "narHash": "sha256-njFwHnxYcfQINwSa+XWhenv8s8PMg/j5ID0HpIa49xM=", 47 + "lastModified": 1773326183, 48 + "narHash": "sha256-tj3piRd9RnnP36HwHmQD4O4XZeowsH/rvMeyp9Pmot0=", 48 49 "owner": "rust-lang", 49 50 "repo": "rust-analyzer", 50 - "rev": "a96b6a9b887008bae01839543f9ca8e1f67f4ebe", 51 + "rev": "6254616e97f358e67b70dfc0463687f5f7911c1a", 51 52 "type": "github" 52 53 }, 53 54 "original": {
+1 -1
flake.nix
··· 7 7 nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; # unstable Nixpkgs 8 8 9 9 fenix = { 10 - url = "https://flakehub.com/f/nix-community/fenix/0.1"; 10 + url = "github:nix-community/fenix"; 11 11 inputs.nixpkgs.follows = "nixpkgs"; 12 12 }; 13 13 };