lr_trie/
lib.rs

1//! To reduce memory demands of `LrTrie`, operations are not particularly optimal.
2//! If alphabet used became wide enough, some rework using e.g. hashmap would be needed.
3
4use std::ptr;
5use std::string::String;
6use std::vec::Vec;
7
8mod tra;
9use tra::{tsdv, TraStrain};
10
11mod uc;
12use uc::UC;
13
14type Links = Vec<Box<Node>>;
15type NodeTrace = Vec<PathNode>;
16type EntryTrace = Vec<char>;
17
18#[derive(Clone, PartialEq, Debug)]
19struct PathNode(usize, *mut Node);
20
21impl PathNode {
22    fn n_mut<'a>(&self) -> &'a mut Node {
23        Node::as_mut(self.1)
24    }
25}
26
27/// `KeyEntry` playing entry role.
28pub type Entry<'a> = KeyEntry<'a>;
29/// `KeyEntry` playing key role.
30pub type Key<'a> = KeyEntry<'a>;
31
32#[cfg_attr(test, derive(Clone))]
33struct Node {
34    c: char,
35    supernode: *const Node,
36    links: Option<Links>,
37    lrref: *const Node,
38    #[cfg(test)]
39    id: usize,
40}
41
42const NULL_CHAR: char = '\0';
43const NULL_NODE: *const Node = ptr::null();
44
45impl Node {
46    fn lrref(&self) -> bool {
47        self.lrref != NULL_NODE
48    }
49
50    const fn links(&self) -> bool {
51        self.links.is_some()
52    }
53
54    const fn empty() -> Self {
55        Node {
56            c: NULL_CHAR,
57            supernode: NULL_NODE,
58            links: None,
59            lrref: NULL_NODE,
60            #[cfg(test)]
61            id: 0,
62        }
63    }
64
65    const fn new(c: char, supernode: *const Node) -> Self {
66        Node {
67            c,
68            supernode,
69            links: None,
70            lrref: NULL_NODE,
71            #[cfg(test)]
72            id: 0,
73        }
74    }
75
76    fn empty_boxed() -> Box<Self> {
77        Box::new(Self::empty())
78    }
79
80    fn new_boxed(c: char, supernode: *const Node) -> Box<Self> {
81        Box::new(Self::new(c, supernode))
82    }
83
84    fn as_mut<'a>(n: *mut Self) -> &'a mut Self {
85        unsafe { n.as_mut().unwrap_unchecked() }
86    }
87
88    fn as_ref<'a>(n: *const Self) -> &'a Self {
89        unsafe { n.as_ref().unwrap_unchecked() }
90    }
91
92    const fn to_mut_ptr(&self) -> *mut Self {
93        (self as *const Self).cast_mut()
94    }
95}
96
97/// `&str` verified for working with `LrTrie`.
98pub struct KeyEntry<'a>(&'a str);
99
100impl<'a> KeyEntry<'a> {
101    /// Returns `None` for 0-len `key`.
102    pub const fn new(key: &'a str) -> Option<Self> {
103        if key.len() == 0 {
104            None
105        } else {
106            Some(Self(key))
107        }
108    }
109}
110
111impl<'a> std::ops::Deref for KeyEntry<'a> {
112    type Target = str;
113
114    /// Returns `&str` of key.
115    fn deref(&self) -> &str {
116        self.0
117    }
118}
119
120/// Denotes desired target tree on respective operations.
121#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
122pub enum LeftRight {
123    Left = 0,
124    Right = 1,
125}
126
127fn insert_crux<'a>(mut supernode: &'a mut Node, e: &Entry) -> &'a mut Node {
128    let e = e.0;
129
130    let mut swap = Node::empty_boxed();
131    let mut sn_ptr: *const Node = supernode;
132    for c in e.chars() {
133        let links = supernode.links.get_or_insert_with(|| Links::new());
134
135        let ix = if let Some(i) = index_of_c(links, c) {
136            i
137        } else {
138            let boxed = Node::new_boxed(c, sn_ptr);
139            links.push(boxed);
140            links.len() - 1
141        };
142
143        let node = &mut links[ix];
144
145        // Can be made coherent after
146        // https://github.com/rust-lang/rust/issues/129090.
147        std::mem::swap(&mut swap, node);
148        let n_raw = Box::into_raw(swap);
149        swap = unsafe { Box::from_raw(n_raw) };
150        std::mem::swap(&mut swap, node);
151
152        supernode = node;
153
154        sn_ptr = n_raw;
155    }
156
157    supernode
158}
159
160fn index_of_c(links: &Links, c: char) -> Option<usize> {
161    let links_len = links.len();
162    let mut ix = 0;
163
164    while ix < links_len {
165        let n = &links[ix];
166        if n.c == c {
167            return Some(ix);
168        }
169
170        ix += 1;
171    }
172
173    None
174}
175
176const fn cl_lrref(keyentry_n: &mut Node) -> bool {
177    if keyentry_n.links() {
178        keyentry_n.lrref = NULL_NODE;
179        true
180    } else {
181        false
182    }
183}
184
185fn delete_subnode(n: &mut Node, subnode_ix: usize) -> bool {
186    let n_links = n.links.as_mut().unwrap();
187    _ = n_links.swap_remove(subnode_ix);
188
189    if n_links.len() == 0 {
190        n.links = None;
191    } else {
192        return true;
193    }
194
195    if n.lrref() {
196        return true;
197    }
198
199    return false;
200}
201
202fn delete_key_side<'a>(path: &NodeTrace) {
203    let mut path = path.iter();
204    let epn = path.next_back();
205    let epn = unsafe { epn.unwrap_unchecked() };
206    let n = epn.n_mut();
207
208    if cl_lrref(n) {
209        return;
210    }
211
212    let mut sub_n_ix = epn.0;
213    while let Some(PathNode(n_ix, n)) = path.next_back() {
214        if delete_subnode(Node::as_mut(*n), sub_n_ix) {
215            break;
216        }
217
218        sub_n_ix = *n_ix;
219    }
220}
221
222fn delete_entry_side(key_side_entry_n: &Node) {
223    let lrref = key_side_entry_n.lrref.cast_mut();
224    let node = Node::as_mut(lrref);
225
226    if cl_lrref(node) {
227        return;
228    }
229
230    const NULL_MUT: *mut Node = ptr::null_mut();
231    let mut node: &mut Node = node;
232    loop {
233        let super_n = node.supernode.cast_mut();
234        if super_n == NULL_MUT {
235            break;
236        }
237
238        let super_n = Node::as_mut(super_n);
239        let sn_links = unsafe { super_n.links.as_ref().unwrap_unchecked() };
240        let n_ix = unsafe { index_of_c(sn_links, node.c).unwrap_unchecked() };
241
242        if delete_subnode(super_n, n_ix) {
243            break;
244        }
245
246        node = super_n;
247    }
248}
249
250fn set_cap<T>(buf: &UC<Vec<T>>, approx_cap: usize) -> usize {
251    let buf = buf.get_mut();
252    let cp = buf.capacity();
253
254    if cp < approx_cap {
255        buf.reserve(approx_cap);
256    } else if cp > approx_cap {
257        *buf = Vec::with_capacity(approx_cap);
258    }
259
260    buf.capacity()
261}
262
263fn ext(l: &Links, k_buf: &mut String, e_buf: &mut Vec<char>, o: &mut Vec<(String, String)>) {
264    for n in l {
265        k_buf.push(n.c);
266
267        let lrref = n.lrref;
268        if lrref != NULL_NODE {
269            let k = k_buf.clone();
270            let e = construct_e(lrref, e_buf);
271            o.push((k, e));
272        }
273
274        if let Some(l) = n.links.as_ref() {
275            ext(l, k_buf, e_buf, o);
276        }
277
278        _ = k_buf.pop();
279    }
280}
281
282fn construct_e(mut node: *const Node, e_buf: &mut Vec<char>) -> String {
283    loop {
284        let n = Node::as_ref(node);
285        let super_n = n.supernode;
286
287        if super_n == NULL_NODE {
288            break;
289        }
290
291        e_buf.push(n.c);
292        node = super_n;
293    }
294
295    let ret = e_buf.iter().rev().collect::<String>();
296    e_buf.clear();
297    ret
298}
299
300/// Denotes desired buffer on respective operations.
301#[derive(Clone, PartialEq, Debug)]
302pub enum Buffer {
303    /// Delete method buffer denotation.
304    Delete = 0,
305    /// Member method buffer denotation.
306    Member = 1,
307}
308
309/// Left-right trie is double-treed trie.
310///
311/// Allows for bi-directional mapping between two trees whereas each entry
312/// has link to counterpart entry in opposite tree.
313///
314/// While each entry-entry pair is settled by nodes in respective tree,
315/// each node carries extra reference to its supernode. Thus `LrTrie` is not memory effecient
316/// unless nodes in each side are reasonably reclaimed.
317///
318/// All methods asymptotical computational time complexity depends on subnodes count,
319/// i.e. Ο(alphabet-size). For small alphabets applies rather Ο(key-length). `member` method
320/// is more requiring because of entry construction.
321///
322/// Node occurs per every `char` as defined by Rust lang.
323#[cfg_attr(test, derive(PartialEq, Debug))]
324pub struct LrTrie {
325    left: Node,
326    right: Node,
327    // backtracing buffer
328    trace: UC<NodeTrace>,
329    entry: UC<EntryTrace>,
330    count: usize,
331}
332
333#[cfg_attr(test, derive(PartialEq, Debug))]
334enum TraRes<'a> {
335    Ok,
336    OkRef(&'a Node),
337    UnknownForNotEntry,
338    UnknownForAbsentPathLinks,
339    UnknownForAbsentPathNode,
340}
341
342impl LrTrie {
343    /// Ctor.
344    pub const fn new() -> Self {
345        LrTrie {
346            left: Node::empty(),
347            right: Node::empty(),
348            trace: UC::new(Vec::new()),
349            entry: UC::new(Vec::new()),
350            count: 0,
351        }
352    }
353
354    /// Inserts entries in respective trees making them pointing one to another.
355    ///
356    /// If entry already exists in respective tree, its current counterpart is removed.
357    pub fn insert(&mut self, l_entry: &Entry, r_entry: &Entry) {
358        // let not make exercises for exact reinsert since
359        // it is supposed to be very rare, if at all
360
361        let mut cntr = 0;
362        if self.delete_crux(l_entry, LeftRight::Left, false).is_ok() {
363            cntr += 1;
364        }
365        if self.delete_crux(r_entry, LeftRight::Right, false).is_ok() {
366            cntr += 1;
367        }
368
369        let l_en = insert_crux(&mut self.left, l_entry);
370        let r_en = insert_crux(&mut self.right, r_entry);
371
372        l_en.lrref = r_en as *const Node;
373        r_en.lrref = l_en as *const Node;
374
375        let count = self.count;
376        self.count = match cntr {
377            0 => count + 1,
378            1 => return,
379            2 => count - 1,
380            _ => panic!("Impossible value."),
381        }
382    }
383
384    fn track(&self, key: &Key, lr: LeftRight, ts: TraStrain) -> TraRes {
385        let root = self.root(lr);
386        let trace = self.trace.get_mut();
387
388        let tracing = TraStrain::has(ts.clone(), tsdv::TRA);
389        if tracing {
390            trace.push(PathNode(usize::MAX, root.to_mut_ptr()));
391        }
392
393        let mut key = key.chars();
394        let mut node = Node::as_ref(root);
395        while let Some(c) = key.next() {
396            if let Some(l) = &node.links {
397                if let Some(ix) = index_of_c(l, c) {
398                    node = &l[ix];
399                    if tracing {
400                        trace.push(PathNode(ix, node.to_mut_ptr()));
401                    }
402
403                    continue;
404                }
405                return TraRes::UnknownForAbsentPathNode;
406            }
407            return TraRes::UnknownForAbsentPathLinks;
408        }
409
410        if node.lrref() {
411            match ts {
412                x if TraStrain::has(x.clone(), tsdv::REF) => TraRes::OkRef(node),
413                x if TraStrain::has(x.clone(), tsdv::EMP) => TraRes::Ok,
414                _ => panic!("Unsupported result scenario."),
415            }
416        } else {
417            TraRes::UnknownForNotEntry
418        }
419    }
420
421    /// Seeks for member in other tree than is specified for key.
422    ///
423    /// Returns `None` if key is not associated with entry.
424    pub fn member(&self, key: &Key, lr: LeftRight) -> Option<String> {
425        let res = self.track(key, lr, TraStrain::NonRef);
426
427        if let TraRes::OkRef(en) = res {
428            let entry = self.entry.get_mut();
429
430            let ret = construct_e(en.lrref, entry);
431            Some(ret)
432        } else {
433            None
434        }
435    }
436
437    const fn root(&self, lr: LeftRight) -> &Node {
438        match lr {
439            LeftRight::Left => &self.left,
440            LeftRight::Right => &self.right,
441        }
442    }
443
444    const fn links(&self, lr: LeftRight) -> Option<&Links> {
445        self.root(lr).links.as_ref()
446    }
447
448    /// Deletes both key and its entry seeking key in specified tree.
449    ///
450    /// Returns `Err` when key is not associated with entry.
451    pub fn delete(&mut self, key: &Key, lr: LeftRight) -> Result<(), ()> {
452        let res = self.delete_crux(key, lr, true);
453        self.trace.get_mut().clear();
454
455        if res.is_ok() {
456            self.count -= 1;
457        }
458
459        res
460    }
461
462    fn delete_crux(&mut self, key: &Key, lr: LeftRight, delete_ks: bool) -> Result<(), ()> {
463        let ts = if delete_ks {
464            TraStrain::TraRef
465        } else {
466            TraStrain::NonRef
467        };
468
469        if let TraRes::OkRef(en) = self.track(key, lr, ts) {
470            delete_entry_side(en);
471
472            if delete_ks {
473                delete_key_side(&*self.trace)
474            }
475
476            Ok(())
477        } else {
478            Err(())
479        }
480    }
481
482    /// `LrTrie` uses internal buffers, to avoid excessive allocations and copying, which grow
483    /// over time due:
484    /// - either backtracing when `delete`-ing, which backtraces whole path from entry
485    /// node to root node
486    /// - or entry constructing in `member`, when traversing back to root
487    ///
488    /// Use this method to shrink or extend buffer to fit actual program needs. Neither shrinking nor extending
489    /// is guaranteed to be exact. See `Vec::with_capacity()` and `Vec::reserve()`. For optimal
490    /// performance, set `approx_cap` to, at least, `key.chars().count()`.
491    ///
492    /// Some high value is sufficient anyway. Since buffer continuous
493    /// usage, its capacity will likely expand at some point in time to size sufficient to all keys.
494    ///
495    /// Returns actual buffer capacity.
496    ///
497    /// **Note:** While `String` is UTF8 encoded, its byte length does not have to equal its `char` count
498    /// which is either equal or lesser.
499    /// ```
500    /// let star = "⭐";
501    /// assert_eq!(3, star.len());
502    /// assert_eq!(1, star.chars().count());
503    ///
504    /// let yes = "sí";
505    /// assert_eq!(3, yes.len());
506    /// assert_eq!(2, yes.chars().nth(1).unwrap().len_utf8());
507    ///
508    /// let abc = "abc";
509    /// assert_eq!(3, abc.len());
510    /// ```
511    pub fn put_buf_cap(&mut self, approx_cap: usize, buf: Buffer) -> usize {
512        if buf == Buffer::Delete {
513            set_cap(&self.trace, approx_cap)
514        } else {
515            #[cfg(test)]
516            assert_eq!(Buffer::Member, buf);
517
518            set_cap(&self.entry, approx_cap)
519        }
520    }
521
522    /// Acquires corresponding buffer capacity.
523    ///
524    /// Check with `fn put_buf_cap` for details.
525    pub fn aq_buf_cap(&self, buf: Buffer) -> usize {
526        if buf == Buffer::Delete {
527            self.trace.capacity()
528        } else {
529            #[cfg(test)]
530            assert_eq!(Buffer::Member, buf);
531
532            self.entry.capacity()
533        }
534    }
535
536    /// Clears both trees leaving `LrTrie` instance blank.
537    ///
538    /// Returns count of entry-entry pairs before clearing.
539    ///
540    /// Keeps capacity of all of internal buffers intact. Check with `put_buf_cap` for details.
541    pub fn clear(&mut self) -> usize {
542        self.left = Node::empty();
543        self.right = Node::empty();
544        let count = self.count;
545        self.count = 0;
546        count
547    }
548
549    /// Returns count of entry-entry pairs.
550    pub const fn count(&self) -> usize {
551        self.count
552    }
553
554    /// Extracts all entry-entry pairs.
555    ///
556    /// Returns `None` when `LrTrie` is blank.
557    ///
558    /// Returned set is alphabetically unordered. Exactly, order depends on current order of `char`s
559    /// at each node.
560    ///
561    /// Both trees are kept settled.
562    ///
563    /// Use `lr` `LeftRight` parameter for `0` field source tree selection.
564    ///
565    /// Returned set can be overcapacitated, i.e. its capacity will not
566    /// be shrunken according to its length.
567    pub fn extract(&self, lr: LeftRight) -> Option<Vec<(String, String)>> {
568        if let Some(l) = self.links(lr) {
569            let mut o = Vec::with_capacity(1000);
570            let mut e_buf = Vec::with_capacity(1000);
571            let mut k_buf = String::with_capacity(1000);
572
573            ext(l, &mut k_buf, &mut e_buf, &mut o);
574
575            Some(o)
576        } else {
577            None
578        }
579    }
580}
581
582#[cfg(test)]
583mod tests_of_units {
584
585    use crate::{LeftRight, LrTrie, Node};
586
587    impl PartialEq for Node {
588        fn eq(&self, other: &Self) -> bool {
589            self.c == other.c
590                && self.supernode == other.supernode
591                && self.links == other.links
592                && self.lrref == other.lrref
593        }
594    }
595
596    mod node_test_imp {
597        use crate::Node;
598
599        #[test]
600        fn eq() {
601            let sn = Node::empty();
602            let mut n1 = Node::new('x', &sn);
603            let links = vec![Node::new_boxed('y', &sn)];
604            n1.links = Some(links);
605            n1.lrref = &sn;
606
607            let n2 = n1.clone();
608
609            assert_eq!(true, n1.eq(&n2));
610        }
611    }
612
613    use std::fmt::{Debug, Formatter};
614
615    impl Debug for Node {
616        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
617            let links = if self.links() { "Some" } else { "None" };
618            let lrref = if self.lrref() { "Some" } else { "None" };
619            let sn = if self.supernode.is_null() {
620                "Null"
621            } else {
622                "Parent"
623            };
624
625            f.write_fmt(format_args!(
626                "Node {{\n  c: {}\n  sn: {}\n  links: {}\n  lrref: {}\n}}",
627                self.c, sn, links, lrref
628            ))
629        }
630    }
631
632    use crate::NodeTrace;
633    impl LrTrie {
634        fn cc_trace(&mut self) -> NodeTrace {
635            let trace = self.trace.get_mut();
636            let clone = trace.clone();
637            trace.clear();
638            clone
639        }
640    }
641
642    mod lrtrie_test_impl {
643        use std::ptr::NonNull;
644
645        use crate::{LrTrie, Node, PathNode};
646
647        #[test]
648        fn cc_trace() {
649            let n1 = NonNull::<Node>::dangling().as_ptr();
650            let n2 = NonNull::<Node>::dangling().as_ptr();
651
652            let mut trie = LrTrie::new();
653            let trace = trie.trace.get_mut();
654            trace.push(PathNode(usize::MIN, n1));
655            trace.push(PathNode(usize::MAX, n2));
656
657            let proof = trace.clone();
658            let test = trie.cc_trace();
659
660            assert_eq!(proof, test);
661            assert_eq!(0, trie.trace.len());
662        }
663    }
664
665    impl LeftRight {
666        fn invert(&self) -> Self {
667            match self {
668                LeftRight::Left => LeftRight::Right,
669                LeftRight::Right => LeftRight::Left,
670            }
671        }
672    }
673
674    mod leftright_test_impl {
675        use crate::LeftRight;
676
677        #[test]
678        fn invert() {
679            assert_eq!(LeftRight::Left, LeftRight::Right.invert());
680            assert_eq!(LeftRight::Right, LeftRight::Left.invert());
681        }
682    }
683
684    use crate::PathNode;
685    impl PathNode {
686        fn n_ref<'a>(&self) -> &'a Node {
687            Node::as_ref(self.1)
688        }
689    }
690
691    mod pathnode_test_impl {
692        use crate::{Node, PathNode};
693
694        #[test]
695        fn n_ref() {
696            let mut n = Node::empty();
697            let pn = PathNode(0, &mut n);
698            assert_eq!(
699                &n as *const Node as usize,
700                pn.n_ref() as *const Node as usize
701            );
702        }
703    }
704
705    mod pathnode {
706        use crate::{Node, PathNode};
707
708        #[test]
709        fn n_mut() {
710            let n = &mut Node::empty();
711            let pn = PathNode(0, n);
712            assert_eq!(
713                n as *const Node as usize,
714                pn.n_mut() as *const Node as usize
715            );
716        }
717    }
718
719    mod node {
720
721        use crate::{Links, Node, NULL_CHAR};
722        use std::ptr;
723
724        #[test]
725        fn lrref() {
726            let mut node = Node::empty();
727
728            assert_eq!(false, node.lrref());
729            node.lrref = &node;
730            assert!(node.lrref());
731        }
732
733        #[test]
734        fn links() {
735            let mut node = Node::empty();
736
737            assert_eq!(false, node.links());
738            node.links = Some(Links::new());
739            assert!(node.links());
740        }
741
742        #[test]
743        fn empty() {
744            let null_ptr = ptr::null();
745
746            let node = Node::empty();
747
748            assert_eq!(NULL_CHAR, node.c);
749            assert_eq!(null_ptr, node.supernode);
750            assert_eq!(None, node.links);
751            assert_eq!(null_ptr, node.lrref);
752        }
753
754        #[test]
755        fn new() {
756            let c = '🫀';
757            let sn = Node::empty();
758
759            let new = Node::new(c, &sn);
760
761            assert_eq!(c, new.c);
762            assert_eq!(&sn as *const Node, new.supernode);
763            assert_eq!(None, new.links);
764            assert_eq!(0, new.lrref as usize);
765        }
766
767        #[test]
768        fn as_mut() {
769            let n = &mut Node::empty() as *mut Node;
770            assert_eq!(n as usize, Node::as_mut(n) as *const Node as usize);
771        }
772
773        #[test]
774        fn as_ref() {
775            let n = &Node::empty() as *const Node;
776            assert_eq!(n as usize, Node::as_ref(n) as *const Node as usize);
777        }
778
779        #[test]
780        fn to_mut_ptr() {
781            let n = Node::empty();
782            let n_add = &n as *const Node as usize;
783            assert_eq!(n_add, n.to_mut_ptr() as usize);
784        }
785    }
786
787    mod keyentry {
788        use crate::KeyEntry;
789
790        mod new {
791            use crate::KeyEntry;
792
793            #[test]
794            fn some() {
795                const KEY: &str = "emoción";
796                let key = KeyEntry::new(KEY);
797                assert!(key.is_some());
798                let key = key.unwrap();
799                assert_eq!(KEY, key.0);
800            }
801
802            #[test]
803            fn none() {
804                let key = KeyEntry::new("");
805                assert!(key.is_none());
806            }
807        }
808
809        use std::ops::Deref;
810
811        #[test]
812        fn deref() {
813            const KEY: &str = "key";
814            let key = KeyEntry(KEY);
815            assert_eq!(KEY, key.deref());
816        }
817    }
818
819    mod insert_crux {
820        use std::ops::Deref;
821
822        use crate::{insert_crux, tra::TraStrain, Entry, KeyEntry, LeftRight, LrTrie, Node};
823
824        #[test]
825        fn basic_test() {
826            let mut root = Node::empty();
827
828            const ENTRY: &str = "lr_links_inserT";
829            let limit = ENTRY.len() - 1;
830
831            let entry: Entry = KeyEntry(ENTRY);
832            let node = insert_crux(&mut root, &entry);
833
834            assert_eq!('T', node.c);
835            assert_eq!(None, node.links);
836
837            assert!(root.links.is_some());
838
839            let mut links = root.links.as_ref().unwrap();
840            let mut super_n: *const Node = &root;
841            for (ix, c) in ENTRY.chars().enumerate() {
842                let node = links.get(0);
843
844                assert!(node.is_some());
845                let node = node.unwrap();
846
847                assert_eq!(c, node.c);
848                assert_eq!(super_n, node.supernode);
849                super_n = node.deref();
850
851                if ix < limit {
852                    let temp = &node.links;
853                    assert!(temp.is_some());
854                    links = temp.as_ref().unwrap();
855                } else {
856                    assert!(&node.links.is_none());
857                }
858            }
859        }
860
861        #[test]
862        fn existing_path_insert() {
863            const OLD: &str = "touchstone";
864            const NEW: &str = "touch";
865
866            let old = KeyEntry(OLD);
867            let new = KeyEntry(NEW);
868
869            let mut trie = LrTrie::new();
870
871            _ = insert_crux(&mut trie.left, &old);
872            _ = insert_crux(&mut trie.left, &new);
873
874            _ = trie.track(&old, LeftRight::Left, TraStrain::TraEmp);
875            let old_path = trie.cc_trace();
876
877            _ = trie.track(&new, LeftRight::Left, TraStrain::TraEmp);
878            let new_path = trie.cc_trace();
879
880            assert_eq!(OLD.len() + 1, old_path.len());
881            assert_eq!(new_path, old_path[..NEW.len() + 1]);
882        }
883    }
884
885    mod index_of_c {
886
887        use crate::{index_of_c, Links, Node};
888
889        fn links(cs: &[char]) -> Links {
890            cs.iter()
891                .map(|x| Node::new_boxed(*x, 0 as *const Node))
892                .collect::<Links>()
893        }
894
895        #[test]
896        fn some() {
897            let links = links(&['a', 'b', 'c']);
898
899            let index = index_of_c(&links, 'c');
900            assert!(index.is_some());
901            assert_eq!(2, index.unwrap());
902        }
903
904        #[test]
905        fn none() {
906            let links = links(&['a', 'b', 'c']);
907
908            let index = index_of_c(&links, 'd');
909            assert!(index.is_none());
910        }
911    }
912
913    mod cl_lrref {
914        use crate::{cl_lrref, Links, Node};
915        use std::ptr;
916
917        #[test]
918        fn has_to() {
919            let mut node = Node::empty();
920            node.lrref = &node;
921            node.links = Some(Links::new());
922
923            assert_eq!(true, cl_lrref(&mut node));
924            assert_eq!(ptr::null(), node.lrref);
925        }
926
927        #[test]
928        fn has_not_to() {
929            let mut node = Node::empty();
930            node.lrref = &node;
931
932            assert_eq!(false, cl_lrref(&mut node));
933            assert_eq!(&node as *const Node, node.lrref);
934        }
935    }
936
937    mod delete_subnode {
938        use crate::{delete_subnode, Links, Node};
939        use std::{ops::Deref, vec};
940
941        // deletion continues when and only when
942        // node does not participates in path to another
943        // node, where path length is allowed to be 0
944        #[test]
945        fn deletion_continues() {
946            let mut node = Node::empty();
947            node.links = Some(vec![Node::empty_boxed()]);
948
949            assert_eq!(false, delete_subnode(&mut node, 0));
950            assert_eq!(None, node.links);
951        }
952
953        // when node holds some links after removing subnode in
954        // question, it participates in path to another node
955        #[test]
956        fn node_with_links() {
957            let mut node = Node::empty();
958
959            #[rustfmt::skip]
960            let links = vec![
961            Node::empty_boxed(),
962            Node::new_boxed('a', 0 as *const Node),
963            Node::new_boxed('b', 0 as *const Node),
964            Node::new_boxed('c', 0 as *const Node),
965            ];
966
967            node.links = Some(links);
968            assert_eq!(true, delete_subnode(&mut node, 1));
969
970            let links = node.links.as_ref().unwrap();
971            assert_eq!(3, links.len());
972            assert_eq!(&Node::empty(), links[0].deref());
973            assert_eq!('c', links[1].c);
974            assert_eq!('b', links[2].c);
975        }
976
977        // key node has reference to entry node
978        // so it participates in 0-len path to
979        // another node
980        #[test]
981        fn key_node() {
982            let mut node = Node::empty();
983
984            node.links = Some(vec![Node::empty_boxed()]);
985            node.lrref = &node;
986
987            assert_eq!(true, delete_subnode(&mut node, 0));
988            assert_eq!(None, node.links);
989        }
990
991        #[test]
992        #[should_panic(expected = "swap_remove index (is 0) should be < len (is 0)")]
993        fn index_out_of_bounds() {
994            let mut node = Node::empty();
995            node.links = Some(Links::new());
996            delete_subnode(&mut node, 0);
997        }
998    }
999
1000    mod delete_key_side {
1001        use crate::{delete_key_side, Links, Node, PathNode};
1002        use std::{ops::DerefMut, ptr};
1003
1004        #[test]
1005        fn keynode_with_links() {
1006            let mut n = Node::empty();
1007            n.lrref = &n;
1008            n.links = Some(Links::new());
1009
1010            #[rustfmt::skip]
1011            let path = vec![
1012                PathNode(usize::MAX, &mut n),
1013                PathNode(usize::MAX, &mut n)
1014            ];
1015
1016            delete_key_side(&path);
1017
1018            assert_eq!(ptr::null(), n.lrref);
1019        }
1020
1021        #[test]
1022        fn node_with_links() {
1023            let mut empty_n = Node::empty();
1024
1025            let mut n = Node::empty();
1026            n.links = Some(vec![Node::empty_boxed(), Node::empty_boxed()]);
1027
1028            #[rustfmt::skip]
1029            let path = vec![
1030                PathNode(usize::MAX, &mut empty_n),
1031                PathNode(usize::MAX, &mut n),
1032                PathNode(1, &mut empty_n),
1033            ];
1034
1035            delete_key_side(&path);
1036
1037            assert_eq!(1, n.links.as_ref().unwrap().len());
1038        }
1039
1040        #[test]
1041        fn node_being_keyentry() {
1042            let mut empty_n = Node::empty();
1043
1044            let mut n1 = Node::empty();
1045            n1.lrref = &n1;
1046            n1.links = Some(vec![Node::empty_boxed()]);
1047
1048            let mut n2 = Node::empty();
1049            n2.links = Some(vec![Node::empty_boxed()]);
1050
1051            #[rustfmt::skip]
1052            let path = vec![
1053                PathNode(usize::MAX, &mut empty_n),
1054                PathNode(usize::MAX, &mut n1),
1055                PathNode(0, &mut n2),
1056                PathNode(0, &mut empty_n),
1057            ];
1058
1059            delete_key_side(&path);
1060
1061            assert_eq!(false, n1.links());
1062            assert_eq!(false, n2.links());
1063        }
1064
1065        #[test]
1066        fn root_escape() {
1067            let mut root = Node::empty();
1068            let node = Node::new_boxed('a', &root);
1069            root.links = Some(vec![node]);
1070
1071            #[rustfmt::skip]
1072            let path = vec![
1073                PathNode(usize::MAX, &mut root),
1074                PathNode(0, root.links.as_mut().unwrap()[0].deref_mut()),
1075            ];
1076
1077            delete_key_side(&path);
1078            assert_eq!(None, root.links);
1079        }
1080    }
1081
1082    mod delete_entry_side {
1083        use crate::{delete_entry_side, Links, Node};
1084        use std::{ops::Deref, ptr};
1085
1086        #[test]
1087        fn keynode_with_links() {
1088            let mut n = Node::empty();
1089            n.supernode = &n;
1090            n.lrref = &n;
1091            n.links = Some(Links::new());
1092
1093            delete_entry_side(&n);
1094
1095            assert_eq!(ptr::null(), n.lrref);
1096        }
1097
1098        #[test]
1099        fn node_with_links() {
1100            let mut n = Node::empty();
1101            n.supernode = &n;
1102            n.links = Some(vec![Node::new_boxed('a', &n), Node::empty_boxed()]);
1103
1104            let mut ks_en = Node::empty();
1105            ks_en.lrref = n.links.as_ref().unwrap()[0].deref();
1106
1107            delete_entry_side(&ks_en);
1108
1109            let links = n.links.as_ref();
1110            assert!(links.is_some());
1111            let links = links.unwrap();
1112
1113            assert_eq!(1, links.len());
1114            assert_eq!('\0', links[0].c);
1115        }
1116
1117        #[test]
1118        fn node_being_keyentry() {
1119            let mut n = Node::empty();
1120            n.supernode = &n;
1121            n.links = Some(vec![Node::new_boxed('a', &n)]);
1122            n.lrref = &n;
1123
1124            let mut ks_en = Node::empty();
1125            ks_en.lrref = n.links.as_ref().unwrap()[0].deref();
1126
1127            delete_entry_side(&ks_en);
1128
1129            assert_eq!(None, n.links);
1130        }
1131
1132        #[test]
1133        fn root_escape() {
1134            let mut root = Node::empty();
1135            let node = Node::new_boxed('a', &root);
1136            root.links = Some(vec![node]);
1137
1138            let mut ks_en = Node::empty();
1139            ks_en.lrref = root.links.as_ref().unwrap()[0].deref();
1140
1141            delete_entry_side(&ks_en);
1142            assert_eq!(None, root.links);
1143        }
1144    }
1145
1146    mod set_cap {
1147
1148        use crate::{set_cap, UC};
1149
1150        #[test]
1151        fn extend() {
1152            let new_cap = 10;
1153
1154            let buf = UC::new(Vec::<usize>::new());
1155            assert!(buf.capacity() < new_cap);
1156
1157            let size = set_cap(&buf, new_cap);
1158            assert!(size >= new_cap);
1159            assert!(buf.capacity() >= new_cap);
1160        }
1161
1162        #[test]
1163        fn shrink() {
1164            let new_cap = 10;
1165            let old_cap = 50;
1166
1167            let buf = UC::new(Vec::<usize>::with_capacity(old_cap));
1168
1169            let size = set_cap(&buf, new_cap);
1170            assert!(size >= new_cap && size < old_cap);
1171            let cap = buf.capacity();
1172            assert!(cap >= new_cap && cap < old_cap);
1173        }
1174
1175        #[test]
1176        fn same() {
1177            let cap = 10;
1178            let buf = UC::new(Vec::<usize>::new());
1179
1180            assert!(buf.capacity() < cap);
1181            buf.get_mut().reserve_exact(cap);
1182            let cap = buf.capacity();
1183
1184            let size = set_cap(&buf, cap);
1185            assert_eq!(cap, size);
1186            assert_eq!(cap, buf.capacity());
1187        }
1188    }
1189
1190    mod ext {
1191        use crate::{ext, KeyEntry, LrTrie};
1192
1193        #[test]
1194        fn basic_test() {
1195            let proof = [("opalescence", "black locust"), ("olivewood", "limehound")];
1196
1197            let mut trie = LrTrie::new();
1198            for es in proof {
1199                trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
1200            }
1201
1202            let mut k_buf = String::new();
1203            let mut e_buf = Vec::new();
1204            let mut res = Vec::new();
1205
1206            let links = trie.left.links.as_ref().unwrap();
1207
1208            ext(links, &mut k_buf, &mut e_buf, &mut res);
1209
1210            assert_eq!(2, res.len());
1211            for z in proof.iter().zip(res.iter()) {
1212                let p = z.0;
1213                let t = z.1;
1214
1215                assert_eq!(p.0, t.0);
1216                assert_eq!(p.1, t.1);
1217            }
1218
1219            assert_eq!(0, k_buf.len());
1220            assert_eq!(0, e_buf.len());
1221        }
1222
1223        #[test]
1224        fn load() {
1225            let proof = [
1226                ("olivenite", "limelight"),
1227                ("olivewood", "limehound"),
1228                ("olivary", "limestone"),
1229                ("oligotrophic", "limescale"),
1230                ("lemon", "bandoline"),
1231                ("lemonade", "podium"),
1232                ("lemon balm", "platina"),
1233                ("tapestry", "platform"),
1234                ("lemongrass", "rostrum"),
1235                ("temperate", "region"),
1236                ("tapis", "constituent"),
1237                ("cheque", "constellation"),
1238                ("season", "crops"),
1239                ("array", "formation"),
1240                ("glassware", "glasswork"),
1241            ];
1242
1243            let mut trie = LrTrie::new();
1244            for es in proof {
1245                trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
1246            }
1247
1248            let mut k_buf = String::new();
1249            let mut e_buf = Vec::new();
1250            let mut res = Vec::new();
1251
1252            let links = trie.right.links.as_ref().unwrap();
1253
1254            ext(links, &mut k_buf, &mut e_buf, &mut res);
1255
1256            assert_eq!(proof.len(), res.len());
1257            for z in proof.iter().zip(res.iter()) {
1258                let p = z.0;
1259                let t = z.1;
1260
1261                assert_eq!(p.1, t.0, "{}", p.0);
1262                assert_eq!(p.0, t.1, "{}", p.1);
1263            }
1264        }
1265    }
1266
1267    mod construct_e {
1268        use crate::{construct_e, Node};
1269
1270        #[test]
1271        fn construction() {
1272            let root = Node::empty();
1273            let n1 = Node::new('l', &root);
1274            let n2 = Node::new('r', &n1);
1275            let n3 = Node::new('_', &n2);
1276            let n4 = Node::new('t', &n3);
1277            let n5 = Node::new('r', &n4);
1278            let n6 = Node::new('i', &n5);
1279            let n7 = Node::new('e', &n6);
1280
1281            let mut buf = Vec::new();
1282
1283            let res = construct_e(&n7, &mut buf);
1284            assert_eq!("lr_trie", res.as_str());
1285            assert_eq!(0, buf.len());
1286        }
1287
1288        #[test]
1289        fn root_escape() {
1290            let mut root = Node::empty();
1291            root.c = 'r';
1292
1293            let mut buf = Vec::new();
1294
1295            let res = construct_e(&root, &mut buf);
1296            assert_eq!("", res.as_str());
1297            assert_eq!(0, buf.len());
1298            assert_eq!(0, buf.capacity());
1299        }
1300    }
1301
1302    mod trie {
1303
1304        use crate::{uc::UC, LeftRight, LrTrie, Node};
1305
1306        #[test]
1307        fn new() {
1308            let trie = LrTrie::new();
1309            let empty = Node::empty();
1310
1311            assert_eq!(empty, trie.left);
1312            assert_eq!(empty, trie.right);
1313            assert_eq!(UC::new(Vec::new()), trie.trace);
1314            assert_eq!(UC::new(Vec::new()), trie.entry);
1315            assert_eq!(0, trie.count);
1316        }
1317
1318        mod insert {
1319
1320            use crate::{Entry, Key, KeyEntry, LeftRight, Links, LrTrie, Node};
1321
1322            fn last_node(links: &Links) -> &Node {
1323                let node = links.get(0);
1324                assert!(node.is_some());
1325
1326                let mut node = node.unwrap();
1327                while let Some(l) = node.links.as_ref() {
1328                    let n = l.get(0);
1329                    assert!(n.is_some());
1330
1331                    node = n.as_ref().unwrap();
1332                }
1333
1334                node
1335            }
1336
1337            fn insert(trie: &mut LrTrie, lke: &Entry, rke: &Entry) -> (*const Node, *const Node) {
1338                trie.insert(lke, rke);
1339
1340                let l_links = &trie.left.links.as_ref().unwrap();
1341                let r_links = &trie.right.links.as_ref().unwrap();
1342
1343                (last_node(l_links), last_node(r_links))
1344            }
1345
1346            fn put_id(node: *const Node, val: usize) {
1347                let node = node.cast_mut();
1348                Node::as_mut(node).id = val;
1349            }
1350
1351            #[test]
1352            fn basic_test() {
1353                let left_ke = &KeyEntry("LEFT");
1354                let right_ke = &KeyEntry("RIGHT");
1355
1356                let trie = &mut LrTrie::new();
1357                trie.insert(left_ke, right_ke);
1358
1359                assert_eq!(1, trie.count);
1360
1361                let left = verify(trie, left_ke, LeftRight::Left, right_ke);
1362                let right = verify(trie, right_ke, LeftRight::Right, left_ke);
1363
1364                assert_eq!(left.lrref, right as *const Node);
1365                assert_eq!(right.lrref, left as *const Node);
1366
1367                fn verify<'a>(trie: &'a LrTrie, key: &Key, lr: LeftRight, e: &Entry) -> &'a Node {
1368                    let member = trie.member(key, lr.clone());
1369                    assert!(member.is_some());
1370                    assert_eq!(e.0, &member.unwrap());
1371
1372                    last_node(trie.links(lr).unwrap())
1373                }
1374            }
1375
1376            #[test]
1377            fn reinsert_same() {
1378                #[rustfmt::skip]
1379                let duos = [
1380                    ("LEFT", "RIGHT"),
1381                    ("L", "R"),
1382                    ("LEFT", "R"),
1383                    ("L", "RIGHT")
1384                ];
1385
1386                for d in duos {
1387                    let left_ke = &KeyEntry(d.0);
1388                    let right_ke = &KeyEntry(d.1);
1389
1390                    let trie = &mut LrTrie::new();
1391
1392                    let (lln_a_ptr, rln_a_ptr) = insert(trie, left_ke, right_ke);
1393                    assert_eq!(1, trie.count);
1394
1395                    put_id(lln_a_ptr, 1);
1396                    put_id(rln_a_ptr, 2);
1397
1398                    let (lln_b_ptr, rln_b_ptr) = insert(trie, left_ke, right_ke);
1399                    assert_eq!(1, trie.count);
1400
1401                    let lln_b_ref = Node::as_ref(lln_b_ptr);
1402                    let rln_b_ref = Node::as_ref(rln_b_ptr);
1403
1404                    assert_eq!(1, lln_b_ref.id); // left (key side) preserved
1405                    assert_ne!(2, rln_b_ref.id); // right (entry side) removed
1406                    assert_eq!(0, rln_b_ref.id); // right (entry side) removed
1407
1408                    verify(trie, left_ke, LeftRight::Left, right_ke);
1409                    verify(trie, right_ke, LeftRight::Right, left_ke);
1410
1411                    fn verify(trie: &LrTrie, key: &Key, lr: LeftRight, e: &Entry) {
1412                        let member = trie.member(key, lr);
1413                        assert!(member.is_some());
1414                        assert_eq!(e.0, member.unwrap());
1415                    }
1416                }
1417            }
1418
1419            #[test]
1420            fn reinsert_different() {
1421                #[rustfmt::skip]
1422                let triplets = [
1423                    ("ONE", "ANOTHER", "REPLACEMENT"),
1424                    ("ONE", "A", "R"),
1425                    ("ONE", "ANOTHER", "R"),
1426                    ("ONE", "A", "REPLACEMENT"),
1427
1428                    ("O", "ANOTHER", "REPLACEMENT"),
1429                    ("O", "A", "R"),
1430                    ("O", "A", "REPLACEMENT"),
1431                    ("O", "ANOTHER", "R"),
1432                ];
1433
1434                for t in triplets {
1435                    let one = &KeyEntry(t.0);
1436                    let another = &KeyEntry(t.1);
1437                    let replacement = &KeyEntry(t.2);
1438
1439                    for lr in [LeftRight::Left, LeftRight::Right] {
1440                        let trie = &mut LrTrie::new();
1441
1442                        let (lln_a_ptr, rln_a_ptr) = insert(trie, one, another);
1443                        assert_eq!(1, trie.count);
1444
1445                        put_id(lln_a_ptr, 97);
1446                        put_id(rln_a_ptr, 98);
1447
1448                        let (lln_b_ptr, rln_b_ptr) = if lr == LeftRight::Left {
1449                            insert(trie, replacement, another)
1450                        } else {
1451                            insert(trie, one, replacement)
1452                        };
1453
1454                        assert_eq!(1, trie.count);
1455
1456                        let (lln_b_ref, rln_b_ref) =
1457                            (Node::as_ref(lln_b_ptr), Node::as_ref(rln_b_ptr));
1458
1459                        let (kept, removed) = if lr == LeftRight::Left {
1460                            assert_eq!(0, lln_b_ref.id);
1461                            assert_eq!(98, rln_b_ref.id);
1462                            (another, one)
1463                        } else {
1464                            assert_eq!(97, lln_b_ref.id);
1465                            assert_eq!(0, rln_b_ref.id);
1466                            (one, another)
1467                        };
1468
1469                        assert!(trie.member(replacement, lr.clone()).is_some());
1470                        assert!(trie.member(kept, lr.clone().invert()).is_some());
1471                        assert!(trie.member(removed, lr).is_none());
1472                    }
1473                }
1474            }
1475
1476            #[test]
1477            fn entry_map_merge() {
1478                let mut trie = LrTrie::new();
1479
1480                let a1 = &KeyEntry("A1");
1481                let a2 = &KeyEntry("A2");
1482                let b1 = &KeyEntry("B1");
1483                let b2 = &KeyEntry("B2");
1484
1485                trie.insert(a1, b1);
1486                trie.insert(b2, a2);
1487
1488                assert_eq!(2, trie.count);
1489                trie.insert(a1, a2);
1490                assert_eq!(1, trie.count);
1491
1492                assert_eq!(Some(a2.0.to_string()), trie.member(a1, LeftRight::Left));
1493                assert_eq!(Some(a1.0.to_string()), trie.member(a2, LeftRight::Right));
1494
1495                assert_eq!(None, trie.member(b1, LeftRight::Right));
1496                assert_eq!(None, trie.member(b2, LeftRight::Left));
1497            }
1498        }
1499
1500        mod track {
1501
1502            use crate::{KeyEntry, LeftRight, LrTrie, Node, TraRes, TraStrain};
1503
1504            #[test]
1505            fn tracing() {
1506                let mut trie = LrTrie::new();
1507
1508                let entries = ["key", "keyword", "keyboard", "keyhole"];
1509                let entries = entries.map(|x| KeyEntry(x));
1510
1511                for e in entries.iter() {
1512                    trie.insert(&e, &e);
1513                }
1514
1515                let keyword = &entries[1];
1516                _ = trie.track(keyword, LeftRight::Left, TraStrain::TraEmp);
1517
1518                let trace = trie.cc_trace();
1519
1520                assert_eq!(keyword.0.len() + 1, trace.len());
1521
1522                let l_root: *const Node = &trie.left;
1523                assert_eq!(l_root as usize, trace[0].1 as usize);
1524
1525                for k in entries[0..2].iter() {
1526                    let s = k.0;
1527                    for (ix, c) in s.chars().enumerate() {
1528                        let pn = &trace[ix + 1];
1529                        assert_eq!(0, pn.0);
1530
1531                        let n = pn.n_ref();
1532                        assert_eq!(c, n.c);
1533                    }
1534
1535                    let en = &trace[s.len()].n_ref();
1536                    assert_eq!(true, en.lrref());
1537                }
1538
1539                _ = trie.track(&entries[3], LeftRight::Left, TraStrain::TraEmp);
1540                let trace = trie.cc_trace();
1541
1542                let h_node = &trace[4];
1543                assert_eq!('h', h_node.n_ref().c);
1544
1545                assert_eq!(2, h_node.0);
1546            }
1547
1548            #[test]
1549            fn ok() {
1550                let entry = &KeyEntry("información meteorológica");
1551
1552                let mut trie = LrTrie::new();
1553                _ = trie.insert(entry, entry);
1554                let res = trie.track(entry, LeftRight::Left, TraStrain::NonEmp);
1555
1556                match res {
1557                    TraRes::Ok => {}
1558                    _ => panic!("Not `TraRes::Ok`, but {:?}.", res),
1559                }
1560            }
1561
1562            #[test]
1563            fn ok_ref() {
1564                let entry = &KeyEntry("información meteorológica X");
1565
1566                let mut trie = LrTrie::new();
1567                _ = trie.insert(entry, entry);
1568                let res = trie.track(entry, LeftRight::Left, TraStrain::NonRef);
1569
1570                match res {
1571                    TraRes::OkRef(n) => {
1572                        assert_eq!(true, n.lrref());
1573                        assert_eq!('X', n.c);
1574                    }
1575                    _ => panic!("Not `TraRes::OkRef(_)`, but {:?}.", res),
1576                }
1577            }
1578
1579            #[test]
1580            #[should_panic(expected = "Unsupported result scenario.")]
1581            fn unsupported_result() {
1582                let entry = &KeyEntry("información meteorológica");
1583
1584                let mut trie = LrTrie::new();
1585                _ = trie.insert(entry, entry);
1586
1587                _ = trie.track(entry, LeftRight::Left, TraStrain::NonMut);
1588            }
1589
1590            #[test]
1591            fn unknown_not_path() {
1592                let entry = &KeyEntry("wordbook");
1593                let key = &KeyEntry("wordbooks");
1594
1595                let mut trie = LrTrie::new();
1596                _ = trie.insert(entry, entry);
1597                let res = trie.track(key, LeftRight::Left, TraStrain::NonEmp);
1598                assert_eq!(TraRes::UnknownForAbsentPathLinks, res);
1599            }
1600
1601            #[test]
1602            fn unknown_not_path2() {
1603                let entry = &KeyEntry("wordbookz");
1604                let key = &KeyEntry("wordbooks");
1605
1606                let mut trie = LrTrie::new();
1607                _ = trie.insert(entry, entry);
1608                let res = trie.track(key, LeftRight::Left, TraStrain::NonEmp);
1609                assert_eq!(TraRes::UnknownForAbsentPathNode, res);
1610            }
1611
1612            #[test]
1613            fn unknown_not_entry() {
1614                let entry = &KeyEntry("wordbooks");
1615                let key = &KeyEntry("wordbook");
1616
1617                let mut trie = LrTrie::new();
1618                _ = trie.insert(entry, entry);
1619
1620                let res = trie.track(key, LeftRight::Left, TraStrain::NonEmp);
1621                assert_eq!(TraRes::UnknownForNotEntry, res);
1622            }
1623        }
1624
1625        mod member {
1626
1627            use crate::{Entry, Key, KeyEntry, LeftRight, LrTrie};
1628
1629            #[test]
1630            fn member() {
1631                let left_ke = KeyEntry("LEFT");
1632                let right_ke = KeyEntry("RIGHT");
1633
1634                let mut trie = LrTrie::new();
1635                trie.insert(&left_ke, &right_ke);
1636                assert_eq!(0, trie.entry.capacity());
1637
1638                verify(&left_ke, LeftRight::Left, &right_ke, &trie);
1639                verify(&right_ke, LeftRight::Right, &left_ke, &trie);
1640
1641                fn verify(key: &Key, lr: LeftRight, e: &Entry, trie: &LrTrie) {
1642                    let entry = trie.member(key, lr);
1643                    assert!(entry.is_some());
1644                    assert_eq!(e.0, &entry.unwrap());
1645                    assert_eq!(0, trie.entry.len());
1646                    assert_eq!(true, trie.entry.capacity() > 0);
1647                }
1648            }
1649
1650            #[test]
1651            fn not_member() {
1652                let keyword = KeyEntry("Keyword");
1653
1654                let mut trie = LrTrie::new();
1655                trie.insert(&keyword, &keyword);
1656
1657                for lr in [LeftRight::Left, LeftRight::Right] {
1658                    for key in ["Key", "Opener"] {
1659                        let key = KeyEntry(key);
1660
1661                        let member = trie.member(&key, lr.clone());
1662                        assert!(member.is_none());
1663                    }
1664                }
1665            }
1666        }
1667
1668        #[test]
1669        fn root() {
1670            let trie = LrTrie::new();
1671
1672            let left = &trie.left as *const Node as usize;
1673            let right = &trie.right as *const Node as usize;
1674
1675            let vals = [(left, LeftRight::Left), (right, LeftRight::Right)];
1676            for v in vals {
1677                let test = trie.root(v.1) as *const Node as usize;
1678                assert_eq!(v.0, test);
1679            }
1680        }
1681
1682        use crate::Links;
1683
1684        #[test]
1685        fn links() {
1686            let mut trie = LrTrie::new();
1687            let l_proof: *const Links = trie.left.links.get_or_insert(Links::new());
1688            let r_proof: *const Links = trie.right.links.get_or_insert(Links::new());
1689
1690            let l_test: *const Links = trie.links(LeftRight::Left).unwrap();
1691            let r_test: *const Links = trie.links(LeftRight::Right).unwrap();
1692
1693            assert_eq!(l_proof, l_test);
1694            assert_eq!(r_proof, r_test);
1695        }
1696
1697        /// Node in path to entry being deleted
1698        /// cannot be deleted if and only if participates
1699        /// in path to another entry. Path len varies 0…m.
1700        mod delete {
1701
1702            use std::ops::Deref;
1703
1704            use crate::{tra::TraStrain, Key, KeyEntry, LeftRight, LrTrie};
1705
1706            #[test]
1707            fn known_unknown() {
1708                let known = &KeyEntry("plainoperator");
1709                let unknown = &KeyEntry("secretagent");
1710
1711                let mut trie = LrTrie::new();
1712                _ = trie.insert(&known, &known);
1713
1714                assert_eq!(Err(()), trie.delete(&unknown, LeftRight::Left));
1715                assert_eq!(0, trie.trace.len());
1716                assert_eq!(1, trie.count);
1717
1718                assert_eq!(Ok(()), trie.delete(&known, LeftRight::Left));
1719                assert_eq!(0, trie.trace.len());
1720                assert_eq!(0, trie.count);
1721                assert_eq!(None, trie.member(&known, LeftRight::Right));
1722            }
1723
1724            #[test]
1725            fn inner_entry() {
1726                let mut trie = LrTrie::new();
1727
1728                let outer = KeyEntry("Keyword");
1729                trie.insert(&outer, &outer);
1730
1731                for lr in [LeftRight::Left, LeftRight::Right] {
1732                    let inner = KeyEntry("Key");
1733                    trie.insert(&inner, &inner);
1734
1735                    assert!(trie.delete(&inner, lr).is_ok());
1736                    assert!(trie.member(&inner, LeftRight::Left).is_none());
1737                    assert!(trie.member(&inner, LeftRight::Right).is_none());
1738                    assert!(trie.member(&outer, LeftRight::Left).is_some());
1739                    assert!(trie.member(&outer, LeftRight::Right).is_some());
1740                }
1741            }
1742
1743            #[test]
1744            fn branching_node() {
1745                let keyword = KeyEntry("Keyword");
1746                let keyboard = KeyEntry("Keyboard");
1747                let keypad = KeyEntry("Keypad");
1748                let key: Key = KeyEntry("Key");
1749
1750                for lr in [LeftRight::Left, LeftRight::Right] {
1751                    let mut trie = LrTrie::new();
1752                    trie.insert(&keyword, &keyword);
1753                    trie.insert(&keyboard, &keyboard);
1754                    trie.insert(&keypad, &keypad);
1755
1756                    assert!(trie.delete(&keyboard, lr).is_ok());
1757
1758                    for lr in [LeftRight::Left, LeftRight::Right] {
1759                        assert!(trie.member(&keyboard, lr.clone()).is_none());
1760                        assert!(trie.member(&keyword, lr.clone()).is_some());
1761                        assert!(trie.member(&keypad, lr.clone()).is_some());
1762
1763                        _ = trie.track(&key, lr, TraStrain::TraEmp);
1764                        let y_node = trie.trace[key.0.len()].n_ref();
1765                        let links = y_node.links.as_ref().unwrap();
1766                        assert_eq!(2, links.len());
1767                        let filtered = links.iter().filter(|x| x.c == 'w' || x.c == 'p').count();
1768                        assert_eq!(2, filtered);
1769                    }
1770                }
1771            }
1772
1773            #[test]
1774            fn links_removal() {
1775                let keyword = KeyEntry("Keyword");
1776                let mut trie = LrTrie::new();
1777
1778                for lr in [LeftRight::Left, LeftRight::Right] {
1779                    trie.insert(&keyword, &keyword);
1780
1781                    assert!(trie.delete(&keyword, lr.clone()).is_ok());
1782                    assert!(trie.member(&keyword, lr.clone()).is_none());
1783                    assert!(trie.member(&keyword, lr.invert()).is_none());
1784
1785                    assert!(trie.links(LeftRight::Left).is_none());
1786                    assert!(trie.links(LeftRight::Right).is_none());
1787                }
1788            }
1789
1790            #[test]
1791            fn node_composing_path() {
1792                let dissimilar = KeyEntry("Dissimilar");
1793                let keyword = KeyEntry("Keyword");
1794
1795                for lr in [LeftRight::Left, LeftRight::Right] {
1796                    let mut trie = LrTrie::new();
1797
1798                    trie.insert(&dissimilar, &dissimilar);
1799                    trie.insert(&keyword, &keyword);
1800
1801                    assert!(trie.delete(&keyword, lr.clone()).is_ok());
1802                    assert!(trie.member(&keyword, lr.clone()).is_none());
1803                    assert!(trie.member(&dissimilar, lr).is_some());
1804                }
1805            }
1806
1807            #[test]
1808            fn node_being_keyentry() {
1809                let keyword = KeyEntry("Keyword");
1810                let k = KeyEntry("K");
1811
1812                let mut trie = LrTrie::new();
1813                trie.insert(&k, &k);
1814
1815                for lr in [LeftRight::Left, LeftRight::Right] {
1816                    trie.insert(&keyword, &keyword);
1817
1818                    assert!(trie.delete(&keyword, lr.clone()).is_ok());
1819                    assert!(trie.member(&keyword, lr.clone()).is_none());
1820                    assert!(trie.member(&k, lr.clone()).is_some());
1821
1822                    let links = trie.links(lr);
1823                    let k = &links.unwrap()[0];
1824                    assert_eq!(false, k.links());
1825                }
1826            }
1827
1828            #[test]
1829            fn one_letter_a() {
1830                let keyword = KeyEntry("Keyword");
1831                let k = KeyEntry("K");
1832
1833                let mut trie = LrTrie::new();
1834                trie.insert(&keyword, &keyword);
1835
1836                for lr in [LeftRight::Left, LeftRight::Right] {
1837                    trie.insert(&k, &k);
1838
1839                    assert!(trie.delete(&k, lr.clone()).is_ok());
1840                    assert!(trie.member(&k, lr.clone()).is_none());
1841                    assert!(trie.member(&keyword, lr.clone()).is_some());
1842
1843                    let links = trie.links(lr);
1844                    let k = links.unwrap()[0].deref();
1845                    assert_eq!('K', k.c);
1846                    assert_eq!(true, k.links());
1847                }
1848            }
1849
1850            #[test]
1851            fn one_letter_b() {
1852                let c = KeyEntry("C");
1853                let k = KeyEntry("K");
1854
1855                let mut trie = LrTrie::new();
1856                trie.insert(&c, &c);
1857
1858                for lr in [LeftRight::Left, LeftRight::Right] {
1859                    trie.insert(&k, &k);
1860
1861                    assert!(trie.delete(&k, lr.clone()).is_ok());
1862                    assert!(trie.member(&k, lr.clone()).is_none());
1863                    assert!(trie.member(&c, lr.clone()).is_some());
1864
1865                    let links = trie.links(lr);
1866                    let c = links.unwrap()[0].deref();
1867                    assert_eq!('C', c.c);
1868                }
1869            }
1870        }
1871
1872        mod put_buf_cap {
1873            use crate::{Buffer, LrTrie};
1874
1875            #[test]
1876            fn trace() {
1877                let mut trie = LrTrie::new();
1878                assert_eq!(0, trie.trace.capacity());
1879
1880                let cap = 100;
1881                let size = trie.put_buf_cap(cap, Buffer::Delete);
1882                assert_eq!(true, size >= cap);
1883                assert_eq!(true, trie.trace.capacity() >= cap);
1884            }
1885
1886            #[test]
1887            fn entry() {
1888                let mut trie = LrTrie::new();
1889                assert_eq!(0, trie.entry.capacity());
1890
1891                let cap = 100;
1892                let size = trie.put_buf_cap(cap, Buffer::Member);
1893                assert_eq!(true, size >= cap);
1894                assert_eq!(true, trie.entry.capacity() >= cap);
1895            }
1896        }
1897
1898        mod aq_buf_cap {
1899            use crate::{Buffer, LrTrie};
1900
1901            #[test]
1902            fn trace() {
1903                let cap = 10;
1904                let trie = LrTrie::new();
1905                let buf = trie.trace.get_mut();
1906
1907                assert!(buf.capacity() < cap);
1908                buf.reserve_exact(cap);
1909                let cap = buf.capacity();
1910
1911                assert_eq!(cap, trie.aq_buf_cap(Buffer::Delete));
1912            }
1913
1914            #[test]
1915            fn entry() {
1916                let cap = 10;
1917                let trie = LrTrie::new();
1918                let buf = trie.entry.get_mut();
1919
1920                assert!(buf.capacity() < cap);
1921                buf.reserve_exact(cap);
1922                let cap = buf.capacity();
1923
1924                assert_eq!(cap, trie.aq_buf_cap(Buffer::Member));
1925            }
1926        }
1927    }
1928
1929    use crate::KeyEntry;
1930    #[test]
1931    fn clear() {
1932        let mut trie = LrTrie::new();
1933        let entry = KeyEntry("Key");
1934        trie.insert(&entry, &entry);
1935
1936        assert_eq!(1, trie.clear());
1937        assert_eq!(0, trie.count);
1938
1939        assert_eq!(trie.left, Node::empty());
1940        assert_eq!(trie.right, Node::empty());
1941        assert_eq!(trie, LrTrie::new());
1942    }
1943
1944    #[test]
1945    fn count() {
1946        let mut trie = LrTrie::new();
1947        assert_eq!(0, trie.count());
1948
1949        trie.count = 99;
1950
1951        assert_eq!(99, trie.count());
1952    }
1953
1954    mod extract {
1955        use crate::{KeyEntry, LeftRight, LrTrie};
1956
1957        #[test]
1958        fn left() {
1959            let proof = [
1960                ("olivenite", "limelight"),
1961                ("olivewood", "limehound"),
1962                ("tapestry", "platform"),
1963                ("lemonade", "podium"),
1964                ("lemongrass", "rostrum"),
1965                ("cheque", "constellation"),
1966                ("array", "formation"),
1967            ];
1968
1969            let mut trie = LrTrie::new();
1970            for es in proof {
1971                trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
1972            }
1973
1974            let ext = trie.extract(LeftRight::Left);
1975            assert_eq!(true, ext.is_some());
1976            let ext = ext.unwrap();
1977
1978            assert_eq!(proof.len(), ext.len());
1979
1980            for z in proof.iter().zip(ext.iter()) {
1981                let p = z.0;
1982                let l = z.1;
1983
1984                assert_eq!(p.0, l.0);
1985                assert_eq!(p.1, l.1);
1986            }
1987        }
1988
1989        #[test]
1990        fn right() {
1991            let proof = [
1992                ("olivenite", "limelight"),
1993                ("olivewood", "limehound"),
1994                ("lemon", "bandoline"),
1995                ("lemonade", "podium"),
1996                ("lemon balm", "platina"),
1997                ("cheque", "constellation"),
1998                ("season", "crops"),
1999            ];
2000
2001            let mut trie = LrTrie::new();
2002            for es in proof {
2003                trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
2004            }
2005
2006            let ext = trie.extract(LeftRight::Right);
2007            assert_eq!(true, ext.is_some());
2008            let ext = ext.unwrap();
2009
2010            assert_eq!(proof.len(), ext.len());
2011
2012            for z in proof.iter().zip(ext.iter()) {
2013                let p = z.0;
2014                let r = z.1;
2015
2016                assert_eq!(p.0, r.1);
2017                assert_eq!(p.1, r.0);
2018            }
2019        }
2020
2021        #[test]
2022        fn empty() {
2023            let trie = LrTrie::new();
2024            assert_eq!(None, trie.extract(LeftRight::Right));
2025            assert_eq!(None, trie.extract(LeftRight::Left));
2026        }
2027    }
2028
2029    // exercise logic in greater deep
2030    #[test]
2031    fn load_1() {
2032        const P_LEN: usize = 15;
2033        let proof: [(&str, &str); P_LEN] = [
2034            ("olivenite", "limelight"),
2035            ("olivewood", "limehound"),
2036            ("olivary", "limestone"),
2037            ("oligotrophic", "limescale"),
2038            ("lemon", "bandoline"),
2039            ("lemonade", "podium"),
2040            ("lemongrass", "rostrum"),
2041            ("lemon balm", "platina"),
2042            ("tapestry", "platform"),
2043            ("tapis", "constituent"),
2044            ("temperate", "region"),
2045            ("cheque", "constellation"),
2046            ("array", "formation"),
2047            ("season", "crops"),
2048            ("glassware", "glasswork"),
2049        ];
2050
2051        let mut trie = LrTrie::new();
2052        for es in proof {
2053            trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
2054        }
2055        for p in proof {
2056            let entry = trie.member(&KeyEntry(p.0), LeftRight::Left);
2057            assert_eq!(p.1, entry.unwrap().as_str());
2058
2059            let entry = trie.member(&KeyEntry(p.1), LeftRight::Right);
2060            assert_eq!(p.0, entry.unwrap().as_str());
2061        }
2062
2063        for i in 0..P_LEN {
2064            if i & 1 == 0 {
2065                assert_eq!(Ok(()), trie.delete(&KeyEntry(proof[i].0), LeftRight::Left));
2066            }
2067        }
2068
2069        for i in 0..P_LEN {
2070            let p = proof[i];
2071
2072            if i & 1 == 1 {
2073                let entry = trie.member(&KeyEntry(p.0), LeftRight::Left);
2074                assert_eq!(p.1, entry.unwrap().as_str());
2075
2076                let entry = trie.member(&KeyEntry(p.1), LeftRight::Right);
2077                assert_eq!(p.0, entry.unwrap().as_str());
2078            } else {
2079                let entry = trie.member(&KeyEntry(p.0), LeftRight::Left);
2080                assert_eq!(true, entry.is_none());
2081
2082                let entry = trie.member(&KeyEntry(p.1), LeftRight::Right);
2083                assert_eq!(true, entry.is_none());
2084            }
2085        }
2086    }
2087
2088    // exercise logic in greater deep
2089    #[test]
2090    fn load_2() {
2091        const P_LEN: usize = 15;
2092        let last_ix = P_LEN - 1;
2093        let proof: [(&str, &str); P_LEN] = [
2094            ("olivenite", "limelight"),
2095            ("olivewood", "limehound"),
2096            ("olivary", "limestone"),
2097            ("oligotrophic", "limescale"),
2098            ("lemon", "bandoline"),
2099            ("lemonade", "podium"),
2100            ("lemongrass", "rostrum"),
2101            ("lemon balm", "platina"),
2102            ("tapestry", "platform"),
2103            ("tapis", "constituent"),
2104            ("temperate", "region"),
2105            ("cheque", "constellation"),
2106            ("array", "formation"),
2107            ("season", "crops"),
2108            ("glassware", "glasswork"),
2109        ];
2110
2111        let mut trie = LrTrie::new();
2112        for es in proof {
2113            trie.insert(&KeyEntry(es.0), &KeyEntry(es.1));
2114        }
2115        for p in proof {
2116            let entry = trie.member(&KeyEntry(p.0), LeftRight::Left);
2117            assert_eq!(p.1, entry.unwrap().as_str());
2118
2119            let entry = trie.member(&KeyEntry(p.1), LeftRight::Right);
2120            assert_eq!(p.0, entry.unwrap().as_str());
2121        }
2122
2123        for i in 1..last_ix {
2124            assert_eq!(Ok(()), trie.delete(&KeyEntry(proof[i].1), LeftRight::Right));
2125        }
2126
2127        for i in 1..last_ix {
2128            let p = proof[i];
2129
2130            assert_eq!(None, trie.member(&KeyEntry(p.0), LeftRight::Left));
2131            assert_eq!(None, trie.member(&KeyEntry(p.1), LeftRight::Right));
2132        }
2133
2134        for i in [0, last_ix] {
2135            let p = proof[i];
2136
2137            let entry = trie.member(&KeyEntry(p.0), LeftRight::Left);
2138            assert_eq!(p.1, entry.unwrap().as_str());
2139
2140            let entry = trie.member(&KeyEntry(p.1), LeftRight::Right);
2141            assert_eq!(p.0, entry.unwrap().as_str());
2142        }
2143    }
2144
2145    mod readme {
2146        use crate::{KeyEntry, LeftRight, LrTrie};
2147
2148        #[test]
2149        fn test() {
2150            const ONE: &str = "emoción";
2151            const ANOTHER: &str = "emotion";
2152            const REPLACEMENT: &str = "equilibrio sicofísico";
2153
2154            let mut trie = LrTrie::new();
2155
2156            let one = &KeyEntry::new(ONE).unwrap();
2157            let another = &KeyEntry::new(ANOTHER).unwrap();
2158            let replacement = &KeyEntry::new(REPLACEMENT).unwrap();
2159
2160            trie.insert(one, another);
2161            assert!(trie.member(one, LeftRight::Left).is_some());
2162            assert!(trie.member(another, LeftRight::Left).is_none());
2163            assert!(trie.member(another, LeftRight::Right).is_some());
2164
2165            trie.insert(one, replacement);
2166            assert_eq!(
2167                Some(String::from(REPLACEMENT)),
2168                trie.member(&one, LeftRight::Left)
2169            );
2170            assert!(trie.member(another, LeftRight::Right).is_none());
2171            assert_eq!(
2172                Some(String::from(ONE)),
2173                trie.member(replacement, LeftRight::Right)
2174            );
2175
2176            assert_eq!(Ok(()), trie.delete(one, LeftRight::Left));
2177
2178            assert!(trie.member(one, LeftRight::Left).is_none());
2179            assert!(trie.member(replacement, LeftRight::Right).is_none());
2180
2181            assert_eq!(Err(()), trie.delete(replacement, LeftRight::Right));
2182        }
2183    }
2184}
2185
2186// cargo fmt && cargo test --release