Skip to main content

t_oc/
lib.rs

1//! Trie Occurrence Counter is frequency dictionary that uses any `impl Iterator<Item = char>` type as occurrent.
2//!
3//! Support for English letters A–Za–z OOB.
4
5use std::vec::Vec;
6
7/// Versatile result type used by tree entry operations.
8pub type VerRes = Result<usize, KeyError>;
9/// Addition result type used by [`Toc::add`] operation.
10pub type AddRes = Result<Option<usize>, KeyError>;
11
12use uc::UC;
13mod uc {
14    use std::{cell::UnsafeCell, ops::Deref};
15
16    pub struct UC<T>(UnsafeCell<T>);
17
18    impl<T> UC<T> {
19        pub fn get_ref(&self) -> &T {
20            let t = self.0.get();
21            unsafe { t.as_mut().unwrap_unchecked() }
22        }
23
24        pub fn get_mut(&self) -> &mut T {
25            let t = self.0.get();
26            unsafe { t.as_mut().unwrap_unchecked() }
27        }
28
29        pub const fn new(t: T) -> Self {
30            Self(UnsafeCell::new(t))
31        }
32    }
33
34    impl<T> Deref for UC<T> {
35        type Target = T;
36
37        fn deref(&self) -> &T {
38            self.get_ref()
39        }
40    }
41
42    #[cfg(test)]
43    mod tests_of_units {
44        use std::ops::Deref;
45
46        use super::UC;
47
48        #[test]
49        fn get_ref() {
50            let zero = &0usize as *const usize;
51            let uc = UC::new(zero);
52            let test = uc.get_ref();
53
54            assert_eq!(zero as usize, *test as usize);
55        }
56
57        #[test]
58        fn get_mut() {
59            let zero = &0usize as *const usize;
60            let uc = UC::new(zero);
61            let test = uc.get_mut();
62
63            assert_eq!(zero as usize, *test as usize);
64        }
65
66        #[test]
67        fn new() {
68            let uc = UC::new(333);
69            let mut test = uc.0;
70            assert_eq!(333, *test.get_mut());
71        }
72
73        #[test]
74        fn deref() {
75            let uc = UC::new(11);
76            assert_eq!(uc.get_ref(), uc.deref());
77        }
78    }
79}
80
81/// `Letter` is `Alphabet` element, represents tree node.
82#[cfg_attr(test, derive(PartialEq))]
83struct Letter {
84    #[cfg(test)]
85    val: char,
86    ab: Option<Alphabet>,
87    ct: Option<usize>,
88}
89
90impl Letter {
91    const fn new() -> Self {
92        Letter {
93            #[cfg(test)]
94            val: '💚',
95            ab: None,
96            ct: None,
97        }
98    }
99
100    const fn ab(&self) -> bool {
101        self.ab.is_some()
102    }
103
104    const fn ct(&self) -> bool {
105        self.ct.is_some()
106    }
107
108    const fn to_mut_ptr(&self) -> *mut Self {
109        (self as *const Self).cast_mut()
110    }
111}
112
113/// Tree node arms. Consists of `Letter`s.
114type Alphabet = Box<[Letter]>;
115/// Index conversion function. Tighten with alphabet used.
116/// Returns corresponding `usize`d index of `char`.
117///
118/// For details see `english_letters::ix` implementation.
119pub type Ix = fn(char) -> usize;
120
121/// Reversal index conversion function. Symmetrically mirrors `Ix` function.
122///
123/// For details see `english_letters::re` implementation.
124pub type Re = fn(usize) -> char;
125
126/// Alphabet function, tree arms generation of length specified.
127fn ab(len: usize) -> Alphabet {
128    let mut ab = Vec::new();
129    ab.reserve_exact(len);
130
131    #[cfg(test)]
132    #[cfg(feature = "test-ext")]
133    let mut c = 'A' as u8;
134
135    let sc = ab.spare_capacity_mut();
136    for ix in 0..len {
137        let mut _letter = sc[ix].write(Letter::new());
138
139        #[cfg(test)]
140        #[cfg(feature = "test-ext")]
141        {
142            _letter.val = c as char;
143
144            const Z: u8 = 'Z' as u8;
145            c = if c == Z { 'a' as u8 } else { c + 1 }
146        }
147    }
148
149    unsafe { ab.set_len(len) };
150
151    ab.into_boxed_slice()
152}
153
154/// Module for working with English alphabet letters, A-Za-z.
155///
156/// For details see `Toc::new_with()`.
157pub mod english_letters {
158
159    /// 26
160    pub const BASE_ALPHABET_LEN: usize = 26;
161    /// 52
162    pub const ALPHABET_LEN: usize = BASE_ALPHABET_LEN * 2;
163
164    const A: usize = 'A' as usize;
165    #[allow(non_upper_case_globals)]
166    const a: usize = 'a' as usize;
167
168    /// Index conversion function.
169    pub fn ix(c: char) -> usize {
170        let code_point = c as usize;
171
172        match code_point {
173            | c if c > 64 && c < 91 => c - A,
174            | c if c > 96 && c < 123 => c - a + BASE_ALPHABET_LEN,
175            | _ => {
176                panic!("Index conversion failed because code point `{code_point}` is unsupported.")
177            },
178        }
179    }
180
181    /// Index reversal conversion function.
182    pub fn re(i: usize) -> char {
183        let code_point = match i {
184            | i if i < 26 => i + A,
185            | i if i > 25 && i < 52 => i + a - BASE_ALPHABET_LEN,
186            | _ => {
187                panic!("Char conversion failed because index `{i}` conversion is not supported.")
188            },
189        };
190
191        code_point as u8 as char
192    }
193}
194
195/// Key error type used by tree entry operations.
196#[derive(Debug, PartialEq, Eq, Clone)]
197pub enum KeyError {
198    /// Zero occurrent usage.
199    ZeroLen,
200    /// Unknown occurrent usage.
201    Unknown,
202}
203
204#[cfg_attr(test, derive(PartialEq, Debug))]
205enum TraRes<'a> {
206    Ok(&'a Letter),
207    OkMut(&'a mut Letter),
208    ZeroLen,
209    UnknownForNotEntry,
210    UnknownForAbsentPath,
211}
212
213impl<'a> TraRes<'a> {
214    fn ver_res(&self) -> KeyError {
215        let p = || panic!("Unsupported");
216
217        return match self {
218            | TraRes::ZeroLen => KeyError::ZeroLen,
219            | TraRes::UnknownForNotEntry | TraRes::UnknownForAbsentPath => KeyError::Unknown,
220            | TraRes::Ok(_) => p(),
221            | TraRes::OkMut(_) => p(),
222        };
223    }
224}
225
226// TC: Ω(n ⋅ alphabet size) ⇒ Ω(n), n = nodes count
227// SC: Θ(s + n) ⇒ Θ(s), n = nodes count, s = key lengths sum
228// to lower estimation add unpredictable count of string clonings
229// and buffers (capacity-) reallocations
230fn ext(ab: &Alphabet, buff: &mut String, re: Re, o: &mut Vec<(String, usize)>) {
231    for ix in 0..ab.len() {
232        buff.push(re(ix));
233
234        let letter = &ab[ix];
235
236        if let Some(ct) = letter.ct {
237            let key = buff.clone();
238            o.push((key, ct));
239        }
240
241        if let Some(ab) = letter.ab.as_ref() {
242            ext(ab, buff, re, o);
243        }
244
245        _ = buff.pop();
246    }
247}
248
249/// Trie Occurrence Counter is frequency dictionary that uses any `impl Iterator<Item = char>` type as occurrent.
250///
251/// OOB English letters A–Za–z support only.
252///
253/// ```
254/// use t_oc::Toc;
255/// use std::panic::catch_unwind;
256///
257/// let mut toc = Toc::new();
258/// let occurrent = "true";
259///
260/// _ = toc.add(occurrent.chars(), None);
261/// _ = toc.add(true.to_string().chars(), None);
262///
263/// assert_eq!(2, toc.acq(occurrent.chars()).unwrap());
264/// toc.put(occurrent.chars(), 15);
265/// assert_eq!(15, toc.acq(occurrent.chars()).unwrap());
266///
267/// let catch = catch_unwind(move|| _ = toc.add("#&%".chars(), None));
268/// assert!(catch.is_err());
269/// ```
270///
271/// When asymptotic computational complexity is not explicitly specified , it is:
272/// - TC: Θ(c) where c is count of `char`s iterated over.
273/// - SC: Θ(0).
274pub struct Toc {
275    // tree root
276    rt: Alphabet,
277    // index fn
278    ix: Ix,
279    // rev index fn
280    re: Option<Re>,
281    // alphabet len
282    al: usize,
283    // backtrace buff
284    tr: UC<Vec<*mut Letter>>,
285    // occurrent count
286    ct: usize,
287}
288
289impl Toc {
290    /// Constructs default version of `Toc`, i.e. via
291    /// `fn new_with()` with `english_letters::{ix, re, ALPHABET_LEN}`.
292    pub fn new() -> Self {
293        Self::new_with(
294            english_letters::ix,
295            Some(english_letters::re),
296            english_letters::ALPHABET_LEN,
297        )
298    }
299
300    /// Allows to use custom alphabet different from default alphabet.
301    ///
302    /// ```
303    /// use t_oc::Toc;
304    ///
305    /// fn ix(c: char) -> usize {
306    ///     match c {
307    ///         '&' => 0,
308    ///         '|' => 1,
309    ///         _ => panic!(),
310    ///     }
311    /// }
312    ///
313    /// // if `fn Toc::ext` will not be used, pass `None` for `re`
314    /// fn re(i: usize) -> char {
315    ///     match i {
316    ///         0 => '&',
317    ///         1 => '|',
318    ///         _ => panic!(),
319    ///     }
320    /// }
321    ///
322    /// let ab_len = 2;
323    ///
324    /// let mut toc = Toc::new_with(ix, Some(re), ab_len);
325    /// let a = "&";
326    /// let b = "|";
327    /// let aba = "&|&";
328    /// _ = toc.add(a.chars(), None);
329    /// _ = toc.add(a.chars(), None);
330    /// _ = toc.add(b.chars(), None);
331    /// _ = toc.add(aba.chars(), None);
332    /// assert_eq!(2, toc.acq(a.chars()).unwrap());
333    /// assert_eq!(1, toc.acq(aba.chars()).unwrap());
334    pub fn new_with(ix: Ix, re: Option<Re>, ab_len: usize) -> Self {
335        Self {
336            rt: ab(ab_len),
337            ix,
338            re,
339            al: ab_len,
340            tr: UC::new(Vec::new()),
341            ct: 0,
342        }
343    }
344
345    /// Used to set internal backtracing buffer capacity.
346    ///
347    /// `Toc` uses internal buffer, to avoid excessive allocations and copying, which grows
348    /// over time due backtracing in `rem` method which backtraces whole path from entry
349    /// node to root node.
350    ///
351    /// Use this method to shrink or extend it to fit actual program needs. Neither shrinking nor extending
352    /// is guaranteed to be exact. See `Vec::with_capacity()` and `Vec::reserve()`. For optimal `rem` performance, set `approx_cap` to, at least, `occurrent.count()`.
353    ///
354    /// Some high value is sufficient anyway. Since buffer continuous
355    /// usage, its capacity will likely expand at some point in time to size sufficient to all occurrents.
356    ///
357    /// Return value is actual buffer capacity.
358    ///
359    /// **Note:** While `String` is UTF8 encoded, its byte length does not have to equal its `char` count
360    /// which is either equal or lesser.
361    /// ```
362    /// let sights = "🤩";
363    /// assert_eq!(4, sights.len());
364    /// assert_eq!(1, sights.chars().count());
365    ///
366    /// let yes = "sí";
367    /// assert_eq!(3, yes.len());
368    /// assert_eq!(2, yes.chars().nth(1).unwrap().len_utf8());
369    ///
370    /// let abc = "abc";
371    /// assert_eq!(3, abc.len());
372    /// ```
373    pub fn put_trace_cap(&mut self, approx_cap: usize) -> usize {
374        let tr = &mut self.tr;
375        let cp = tr.capacity();
376
377        if cp < approx_cap {
378            tr.get_mut().reserve(approx_cap);
379        } else if cp > approx_cap {
380            *tr = UC::new(Vec::with_capacity(approx_cap));
381        }
382
383        tr.capacity()
384    }
385
386    /// Used to obtain internal backtracing buffer capacity.
387    ///
388    /// Check with `fn put_trace_cap` for details.
389    pub fn acq_trace_cap(&self) -> usize {
390        self.tr.capacity()
391    }
392
393    /// Used to add occurence to tree.
394    ///
395    /// Counter is of word size. Add overflow is wrapped using [`usize::wrapping_add`].
396    ///
397    /// Optional `val` parameter can be used to insert exact value.
398    ///
399    /// Return value is `Ok(Option<usize>)` for non-zero occurent and holds previous value, if there was some.
400    ///
401    /// Only invalid key classified is zero-length key.
402    ///
403    /// - SC: Θ(q) where q is number of unique nodes, i.e. `char`s in respective branches.
404    pub fn add(&mut self, mut occurrent: impl Iterator<Item = char>, val: Option<usize>) -> AddRes {
405        let c = occurrent.next();
406
407        if c.is_none() {
408            return Err(KeyError::ZeroLen);
409        }
410
411        let c = unsafe { c.unwrap_unchecked() };
412
413        let ix = self.ix;
414        let al = self.al;
415
416        let mut letter = &mut self.rt[ix(c)];
417
418        while let Some(c) = occurrent.next() {
419            let alphabet = letter.ab.get_or_insert_with(|| ab(al));
420            letter = &mut alphabet[ix(c)];
421        }
422
423        let ct = letter.ct;
424
425        let ct_none = ct.is_none();
426        if ct_none {
427            self.ct += 1;
428        }
429
430        letter.ct = Some(if let Some(v) = val {
431            v
432        } else {
433            if ct_none {
434                1
435            } else {
436                unsafe { ct.unwrap_unchecked() }.wrapping_add(1)
437            }
438        });
439
440        Ok(ct)
441    }
442
443    /// Used to acquire value for `occurrent`.
444    ///
445    /// If `Ok(usize)`, `usize` is `occurrent` occurrences count.
446    pub fn acq(&self, occurrent: impl Iterator<Item = char>) -> VerRes {
447        let track_res = self.track(occurrent, false, false);
448        if let TraRes::Ok(l) = track_res {
449            let ct = l.ct;
450            let ct = unsafe { ct.unwrap_unchecked() };
451            Ok(ct)
452        } else {
453            Err(track_res.ver_res())
454        }
455    }
456
457    /// Used to put new value for `occurrent` occurrences.
458    ///
459    /// If `Ok(usize)`, `usize` is previous value.
460    pub fn put(&mut self, occurrent: impl Iterator<Item = char>, val: usize) -> VerRes {
461        let track_res = self.track(occurrent, false, true);
462
463        if let TraRes::OkMut(l) = track_res {
464            let old = l.ct.replace(val);
465            let old = unsafe { old.unwrap_unchecked() };
466            Ok(old)
467        } else {
468            Err(track_res.ver_res())
469        }
470    }
471
472    /// Used to remove `occurrent` from tree.
473    ///
474    /// If `Ok(usize)`, `usize` is `occurrent` occurrences count.
475    ///
476    /// - _c_ is count of `char`s iterated over.
477    /// - TC: Ω(c) or ϴ(c) (backtracing buffer capacity dependent complexity).
478    /// - SC: ϴ(c).
479    ///
480    /// Check with `put_trace_cap` for details on backtracing.
481    pub fn rem(&mut self, occurrent: impl Iterator<Item = char>) -> VerRes {
482        let track_res = self.track(occurrent, true, false);
483        let res = if let TraRes::Ok(_) = track_res {
484            let ct = Self::rem_actual(self);
485            self.ct -= 1;
486            Ok(ct)
487        } else {
488            Err(track_res.ver_res())
489        };
490
491        self.tr.get_mut().clear();
492        res
493    }
494
495    fn rem_actual(&mut self) -> usize {
496        let mut trace = self.tr.iter().map(|x| unsafe { x.as_mut() }.unwrap());
497        let entry = unsafe { trace.next_back().unwrap_unchecked() };
498
499        let ct = entry.ct.take();
500
501        if !entry.ab() {
502            while let Some(l) = trace.next_back() {
503                let alphabet = l.ab.as_ref().unwrap();
504                let mut remove_alphab = true;
505
506                for ix in 0..self.al {
507                    let letter = &alphabet[ix];
508
509                    if letter.ab() || letter.ct() {
510                        remove_alphab = false;
511                        break;
512                    }
513                }
514
515                if remove_alphab {
516                    l.ab = None;
517                } else {
518                    break;
519                }
520
521                if l.ct() {
522                    break;
523                }
524            }
525        }
526
527        unsafe { ct.unwrap_unchecked() }
528    }
529
530    // - s is count of `char`s iterated over
531    // - TC: Ω(s) when `tracing = true`, ϴ(s) otherwise
532    // - SC: ϴ(s) when `tracing = true`, ϴ(0) otherwise
533    fn track(
534        &self,
535        mut occurrent: impl Iterator<Item = char>,
536        tracing: bool,
537        okmut: bool,
538    ) -> TraRes {
539        let c = occurrent.next();
540
541        if c.is_none() {
542            return TraRes::ZeroLen;
543        }
544
545        let c = unsafe { c.unwrap_unchecked() };
546
547        let ix = &self.ix;
548        let tr = self.tr.get_mut();
549
550        let mut letter = &self.rt[ix(c)];
551
552        loop {
553            if tracing {
554                tr.push(letter.to_mut_ptr())
555            }
556
557            if let Some(c) = occurrent.next() {
558                if let Some(ab) = letter.ab.as_ref() {
559                    letter = &ab[ix(c)];
560                } else {
561                    return TraRes::UnknownForAbsentPath;
562                }
563            } else {
564                break;
565            }
566        }
567
568        if letter.ct() {
569            if okmut {
570                let l_mut = unsafe { letter.to_mut_ptr().as_mut().unwrap_unchecked() };
571                TraRes::OkMut(l_mut)
572            } else {
573                TraRes::Ok(letter)
574            }
575        } else {
576            TraRes::UnknownForNotEntry
577        }
578    }
579
580    /// Used to extract occurences from tree.
581    ///
582    /// Extraction is alphabetically ordered. Does not clear tree. Use `fn clr` for clearing.
583    ///
584    /// Return value is `None` for empty `Toc`.
585    ///
586    /// - TC: Ω(n) where n is count of nodes in tree.
587    /// - SC: Θ(s) where s is occurrent lengths summation.
588    ///
589    /// Returned set can be overcapacitated, i.e. its capacity
590    /// will not be shrunken according to its length.
591    pub fn ext(&self) -> Option<Vec<(String, usize)>> {
592        if let Some(re) = self.re {
593            if self.ct == 0 {
594                return None;
595            }
596
597            // capacity is prebuffered to 1000
598            let mut buff = String::with_capacity(1000);
599
600            // capacity is prebuffered to 1000
601            let mut res = Vec::with_capacity(1000);
602
603            ext(&self.rt, &mut buff, re, &mut res);
604            Some(res)
605        } else {
606            panic!("This method is unsupported when `new_with` `re` parameter is provided with `None`.");
607        }
608    }
609
610    /// Used to clear tree.
611    ///
612    /// Return value is count of occurrents in tree before clearing.
613    ///
614    /// TC: Θ(n) where n is count of nodes in tree.
615    pub fn clr(&mut self) -> usize {
616        self.rt = ab(self.al);
617        let ct = self.ct;
618        self.ct = 0;
619        ct
620    }
621
622    /// Used to acquire count of occurrents in tree.
623    pub const fn ct(&self) -> usize {
624        self.ct
625    }
626}
627
628#[cfg(test)]
629mod tests_of_units {
630
631    use crate::Letter;
632    use std::fmt::{Debug, Formatter};
633
634    impl Debug for Letter {
635        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
636            let ab = some_none(self.ab.as_ref());
637
638            return f.write_fmt(format_args!(
639                "Letter {{\n  val: {}\n  ab: {}\n  ct: {:?}\n}}",
640                self.val, ab, self.ct
641            ));
642
643            fn some_none<T>(val: Option<&T>) -> &'static str {
644                if val.is_some() {
645                    "Some"
646                } else {
647                    "None"
648                }
649            }
650        }
651    }
652
653    mod letter {
654
655        use crate::{Letter, ab as ab_fn};
656
657        #[test]
658        fn new() {
659            let letter = Letter::new();
660
661            assert_eq!('💚', letter.val);
662            assert!(letter.ab.is_none());
663            assert!(letter.ct.is_none());
664        }
665
666        #[test]
667        fn ab() {
668            let mut letter = Letter::new();
669            assert_eq!(false, letter.ab());
670
671            letter.ab = Some(ab_fn(0));
672            assert_eq!(true, letter.ab());
673        }
674
675        #[test]
676        fn ct() {
677            let mut letter = Letter::new();
678            assert_eq!(false, letter.ct());
679
680            letter.ct = Some(0);
681            assert_eq!(true, letter.ct());
682        }
683    }
684
685    mod ab {
686
687        use crate::english_letters::ALPHABET_LEN;
688        use crate::ab as ab_fn;
689
690        #[test]
691        fn ab() {
692            let ab = ab_fn(ALPHABET_LEN);
693            assert_eq!(ALPHABET_LEN, ab.len());
694
695            #[cfg(feature = "test-ext")]
696            {
697                let chain = ('A'..='Z').chain('a'..='z');
698
699                for (ix, c) in chain.enumerate() {
700                    let letter = &ab[ix];
701
702                    assert_eq!(c, letter.val);
703                    assert!(letter.ab.is_none());
704                    assert!(letter.ct.is_none());
705                }
706            }
707        }
708
709        #[test]
710        fn zero_len() {
711            let ab = ab_fn(0);
712            assert_eq!(0, ab.len());
713        }
714    }
715
716    mod english_letters {
717
718        use crate::english_letters::{ALPHABET_LEN, BASE_ALPHABET_LEN};
719
720        #[test]
721        fn consts() {
722            assert_eq!(26, BASE_ALPHABET_LEN);
723            assert_eq!(52, ALPHABET_LEN);
724        }
725
726        mod ix {
727            use crate::english_letters::ix;
728            use std::panic::catch_unwind;
729
730            #[test]
731            fn ixes() {
732                assert_eq!(0, ix('A'));
733                assert_eq!(25, ix('Z'));
734                assert_eq!(26, ix('a'));
735                assert_eq!(51, ix('z'));
736            }
737
738            #[test]
739            fn unsupported_char() {
740                let ucs = unsupported_chars();
741
742                for (c, cp) in ucs.map(|x| (x as char, x)) {
743                    let result = catch_unwind(|| ix(c));
744                    assert!(result.is_err());
745
746                    let err = unsafe { result.unwrap_err_unchecked() };
747                    let downcast = err.downcast_ref::<String>().unwrap();
748                    let proof = format!(
749                        "Index conversion failed because code point `{cp}` is unsupported."
750                    );
751                    assert_eq!(&proof, downcast);
752                }
753            }
754
755            fn unsupported_chars() -> [u8; 4] {
756                #[rustfmt::skip] let ucs =
757                [
758                    'A' as u8 -1, 'Z' as u8 +1, // 65–90
759                    'a' as u8 -1, 'z' as u8 +1, // 97–122
760                ];
761                ucs
762            }
763        }
764
765        mod re {
766            use crate::english_letters::re;
767
768            #[test]
769            fn ixes() {
770                assert_eq!('A', re(0));
771                assert_eq!('Z', re(25));
772                assert_eq!('a', re(26));
773                assert_eq!('z', re(51));
774            }
775
776            #[test]
777            #[should_panic(
778                expected = "Char conversion failed because index `52` conversion is not supported."
779            )]
780            fn unsupported_ix() {
781                _ = re(52)
782            }
783        }
784    }
785
786    mod ext {
787
788        type Nest = (char, usize);
789
790        use crate::{ab as ab_ctor, ext, Alphabet};
791        use crate::english_letters::{ALPHABET_LEN, ix, re};
792
793        fn ab_fn() -> Alphabet {
794            ab_ctor(ALPHABET_LEN)
795        }
796
797        #[test]
798        fn basic_test() {
799            let mut ab = ab_fn();
800
801            ab[ix('A')].ct = Some(1);
802            ab[ix('z')].ct = Some(2);
803
804            let mut buff = String::new();
805            let mut test = Vec::new();
806
807            ext(&ab, &mut buff, re, &mut test);
808
809            let proof = vec![(String::from("A"), 1), (String::from("z"), 2)];
810            assert_eq!(proof, test);
811        }
812
813        #[test]
814        fn nesting() {
815            let mut root = ab_fn();
816
817            let nesting = [
818                (('A', 3), ('z', 5)),
819                (('B', 5), ('y', 8)),
820                (('y', 10), ('B', 12)),
821                (('z', 99), ('A', 103)),
822            ];
823
824            for n in nesting {
825                prep(&mut root, n);
826            }
827
828            let mut buff = String::new();
829            let mut test = Vec::new();
830
831            ext(&root, &mut buff, re, &mut test);
832
833            let proof = vec![
834                (String::from("A"), 3),
835                (String::from("Az"), 5),
836                (String::from("B"), 5),
837                (String::from("By"), 8),
838                (String::from("y"), 10),
839                (String::from("yB"), 12),
840                (String::from("z"), 99),
841                (String::from("zA"), 103),
842            ];
843
844            assert_eq!(proof, test);
845
846            fn prep(ab: &mut Alphabet, n: (Nest, Nest)) {
847                let ultra = n.0;
848                let infra = n.1;
849
850                let u_l = &mut ab[ix(ultra.0)];
851                let mut ul_ab = ab_fn();
852
853                let i_l = &mut ul_ab[ix(infra.0)];
854                i_l.ct = Some(infra.1);
855
856                u_l.ab = Some(ul_ab);
857                u_l.ct = Some(ultra.1);
858            }
859        }
860
861        #[test]
862        fn in_depth_recursion() {
863            let mut root = ab_fn();
864
865            let paths = [
866                ("AA", 13),
867                ("AzBq", 11),
868                ("By", 329),
869                ("ZaZazAzAzAbYyb", 55),
870                ("yBC", 7),
871                ("ybXr", 53),
872                ("ybXrQUTmop", 33),
873                ("ybXrQUTmopFVB", 99),
874                ("ybXrQUTmopRFG", 80),
875                ("zAzAZaZaZaByYB", 44),
876            ];
877
878            for p in paths {
879                let mut chars = p.0.chars();
880                let mut le = &mut root[ix(chars.next().unwrap())];
881
882                while let Some(c) = chars.next() {
883                    let ab = le.ab.get_or_insert_with(|| ab_fn());
884                    le = &mut ab[ix(c)];
885                }
886
887                le.ct = Some(p.1)
888            }
889
890            let mut buff = String::new();
891            let mut test = Vec::new();
892
893            ext(&root, &mut buff, re, &mut test);
894
895            let proof = vec![
896                (String::from("AA"), 13),
897                (String::from("AzBq"), 11),
898                (String::from("By"), 329),
899                (String::from("ZaZazAzAzAbYyb"), 55),
900                (String::from("yBC"), 7),
901                (String::from("ybXr"), 53),
902                (String::from("ybXrQUTmop"), 33),
903                (String::from("ybXrQUTmopFVB"), 99),
904                (String::from("ybXrQUTmopRFG"), 80),
905                (String::from("zAzAZaZaZaByYB"), 44),
906            ];
907
908            assert_eq!(proof, test);
909        }
910    }
911
912    mod track_res {
913        use crate::{TraRes, Letter};
914        use crate::KeyError::{ZeroLen, Unknown};
915
916        #[test]
917        fn ver_res_convertible() {
918            assert_eq!(ZeroLen, TraRes::ZeroLen.ver_res());
919            assert_eq!(Unknown, TraRes::UnknownForAbsentPath.ver_res());
920            assert_eq!(Unknown, TraRes::UnknownForNotEntry.ver_res());
921        }
922
923        use std::{ops::Deref, panic::catch_unwind};
924        #[test]
925        fn ver_res_nonconvertible() {
926            let err = catch_unwind(|| TraRes::Ok(&Letter::new()).ver_res());
927
928            assert_eq!(true, err.is_err());
929            assert_eq!(
930                &"Unsupported",
931                err.unwrap_err().downcast::<&str>().unwrap().deref()
932            );
933
934            let err = catch_unwind(|| TraRes::OkMut(&mut Letter::new()).ver_res());
935
936            assert_eq!(true, err.is_err());
937            assert_eq!(
938                &"Unsupported",
939                err.unwrap_err().downcast::<&str>().unwrap().deref()
940            );
941        }
942    }
943
944    mod toc {
945        use crate::{Toc, ab};
946        use crate::english_letters::{ix, re, ALPHABET_LEN};
947
948        #[test]
949        fn new() {
950            let toc = Toc::new();
951            assert_eq!(ALPHABET_LEN, toc.al);
952            assert_eq!(ix as usize, toc.ix as usize);
953            assert_eq!(re as usize, toc.re.unwrap() as usize);
954        }
955
956        #[test]
957        fn new_with() {
958            fn test_ix(_c: char) -> usize {
959                0
960            }
961
962            fn test_re(_i: usize) -> char {
963                '\0'
964            }
965
966            let ab_len = 10;
967            let toc = Toc::new_with(test_ix, Some(test_re), ab_len);
968
969            assert_eq!(ab(ab_len), toc.rt);
970            assert_eq!(ab_len, toc.al);
971            assert_eq!(test_ix as usize, toc.ix as usize);
972            assert_eq!(test_re as usize, toc.re.unwrap() as usize);
973            assert_eq!(0, toc.tr.capacity());
974            assert_eq!(0, toc.ct);
975        }
976
977        mod put_trace_cap {
978            use crate::{Toc, uc::UC};
979
980            #[test]
981            fn extend() {
982                const NEW_CAP: usize = 10;
983
984                let mut toc = Toc::new();
985                assert!(toc.tr.capacity() < NEW_CAP);
986
987                let size = toc.put_trace_cap(NEW_CAP);
988                assert!(size >= NEW_CAP);
989                assert!(toc.tr.capacity() >= NEW_CAP);
990            }
991
992            #[test]
993            fn shrink() {
994                const NEW_CAP: usize = 10;
995                const OLD_CAP: usize = 50;
996
997                let mut toc = Toc::new();
998                toc.tr = UC::new(Vec::with_capacity(OLD_CAP));
999
1000                let size = toc.put_trace_cap(NEW_CAP);
1001                assert!(size >= NEW_CAP && size < OLD_CAP);
1002                let cap = toc.tr.capacity();
1003                assert!(cap >= NEW_CAP && cap < OLD_CAP);
1004            }
1005
1006            #[test]
1007            fn same() {
1008                let mut toc = Toc::new();
1009                let cap = toc.tr.capacity();
1010
1011                let size = toc.put_trace_cap(cap);
1012                assert_eq!(cap, size);
1013                assert_eq!(cap, toc.tr.capacity());
1014            }
1015        }
1016
1017        #[test]
1018        fn acq_trace_cap() {
1019            const VAL: usize = 10;
1020
1021            let mut toc = Toc::new();
1022            let tr = &mut toc.tr;
1023
1024            assert!(tr.capacity() < VAL);
1025            tr.get_mut().reserve_exact(VAL);
1026            assert_eq!(VAL, toc.acq_trace_cap());
1027        }
1028
1029        mod add {
1030            use crate::Toc;
1031            use crate::KeyError::ZeroLen;
1032            use crate::english_letters::ix;
1033
1034            #[test]
1035            fn basic_test() {
1036                let entry = || "impreciseness".chars();
1037
1038                let mut toc = Toc::new();
1039                assert_eq!(Ok(None), toc.add(entry(), None));
1040                assert_eq!(1, toc.ct);
1041
1042                let chars: Vec<char> = entry().collect();
1043                let len = chars.len();
1044                let last_ix = len - 1;
1045
1046                let mut sup_ab = &toc.rt;
1047                for c_ix in 0..len {
1048                    let c = chars[c_ix];
1049                    let l = &sup_ab[ix(c)];
1050
1051                    let terminal_it = c_ix == last_ix;
1052
1053                    let sub_ab = l.ab.as_ref();
1054                    assert_eq!(terminal_it, sub_ab.is_none(), "{c_ix}, {c}, {terminal_it}",);
1055
1056                    if terminal_it {
1057                        let ct = l.ct.as_ref();
1058                        assert!(ct.is_some());
1059                        let ct = unsafe { ct.unwrap_unchecked() };
1060                        assert_eq!(&1, ct);
1061                    } else {
1062                        sup_ab = unsafe { sub_ab.unwrap_unchecked() };
1063                    }
1064                }
1065            }
1066
1067            #[test]
1068            fn zero_occurrent() {
1069                let mut toc = Toc::new();
1070                assert_eq!(Err(ZeroLen), toc.add("".chars(), None));
1071                assert_eq!(0, toc.ct);
1072            }
1073
1074            #[test]
1075            fn singular_occurrent() {
1076                let mut toc = Toc::new();
1077                assert_eq!(Ok(None), toc.add("a".chars(), None));
1078                assert_eq!(Some(1), toc.rt[ix('a')].ct);
1079                assert_eq!(1, toc.ct);
1080            }
1081
1082            #[test]
1083            fn double_add() {
1084                let entry = || "impreciseness".chars();
1085
1086                let mut toc = Toc::new();
1087                assert_eq!(Ok(None), toc.add(entry(), None));
1088                assert_eq!(1, toc.ct);
1089
1090                assert_eq!(Ok(Some(1)), toc.add(entry(), None));
1091                assert_eq!(1, toc.ct);
1092
1093                let chars: Vec<char> = entry().collect();
1094                let len = chars.len();
1095                let last_ix = len - 1;
1096
1097                let mut sup_ab = &toc.rt;
1098                for c_ix in 0..len {
1099                    let c = chars[c_ix];
1100                    let l = &sup_ab[ix(c)];
1101
1102                    let terminal_it = c_ix == last_ix;
1103
1104                    let sub_ab = l.ab.as_ref();
1105                    assert_eq!(terminal_it, sub_ab.is_none(), "{c_ix}, {c}, {terminal_it}",);
1106
1107                    if terminal_it {
1108                        let ct = l.ct.as_ref();
1109                        assert!(ct.is_some());
1110                        let ct = unsafe { ct.unwrap_unchecked() };
1111                        assert_eq!(&2, ct);
1112                    } else {
1113                        sup_ab = unsafe { sub_ab.unwrap_unchecked() };
1114                    }
1115                }
1116            }
1117
1118            #[test]
1119            fn exact() {
1120                let entry = || "impreciseness".chars();
1121                const VAL: usize = 15;
1122
1123                let mut toc = Toc::new();
1124                assert_eq!(Ok(None), toc.add(entry(), Some(VAL)));
1125                assert_eq!(1, toc.ct);
1126
1127                assert_eq!(Ok(VAL), toc.acq(entry()));
1128            }
1129
1130            #[test]
1131            fn exact_over() {
1132                let entry = || "impreciseness".chars();
1133                const VAL: usize = 15;
1134
1135                let mut toc = Toc::new();
1136                _ = toc.add(entry(), None);
1137                assert_eq!(1, toc.ct);
1138
1139                assert_eq!(Ok(Some(1)), toc.add(entry(), Some(VAL)));
1140                assert_eq!(1, toc.ct);
1141
1142                assert_eq!(Ok(VAL), toc.acq(entry()));
1143            }
1144
1145            #[test]
1146            #[allow(non_snake_case)]
1147            #[rustfmt::skip]
1148            #[cfg(feature = "test-ext")]
1149            fn load() {
1150
1151                let strs = [
1152                    ("zzbb", 44_441), ("zzaa", 88_999),
1153                    ("xya", 77_666), ("xyz", 22_333),
1154                    ("abc", 33_222), ("abd", 74_332),
1155                    ("abcd", 11_234), ("abce", 11_234),
1156                    ("qaa", 16_678), ("qrs", 24_555),
1157                    ("qrt", 900_001), ("qua", 130_901),
1158                    ("qwa", 2_006),
1159                    ("percent", 77_110), ("percentile", 99_888),
1160                    ("quail", 20_333), ("qualification", 33_111),
1161                    ("quality", 555_666), ("quantity", 116_777),
1162                    ("XYAB", 544_555), ("XYABA", 111_900),
1163                    ("JUI", 30_000), ("JUN", 100_000),
1164                    ("XYA", 80_000), ("XYQ", 11_111),
1165                    ("XYZ", 111_333), ("XYABC", 222_000),
1166                    ("MOMENT", 15_999), ("INSTANT", 34_341),
1167                    ("JUNCTURE", 789_223),
1168                    ("ABC", 14_234), ("ABD", 34_123)
1169                ];
1170
1171                let mut toc = Toc::new();
1172                for (s, c) in strs {
1173                    for i in 0..c {
1174                        let res = toc.add(s.chars(), None);
1175                        let prev = if i > 0 {
1176                            Some(i)
1177                        } else {
1178                            None
1179                        };        
1180                        assert_eq!(Ok(prev), res);
1181                    }
1182                }
1183
1184                for (s, c) in strs {
1185                    let res = toc.acq(s.chars());
1186                    assert_eq!(Ok(c), res);                 
1187                }
1188                
1189                assert_eq!(strs.len(), toc.ct);
1190            }
1191
1192            #[test]
1193            fn overflow_wrap() {
1194                let mut toc = Toc::new();
1195
1196                let entry = || "a".chars();
1197
1198                _ = toc.add(entry(), None);
1199                _ = toc.put(entry(), usize::MAX);
1200                _ = toc.add(entry(), None);
1201                assert_eq!(Ok(0), toc.acq(entry()));
1202                assert_eq!(1, toc.ct);
1203            }
1204        }
1205
1206        mod acq {
1207            use crate::Toc;
1208            use crate::KeyError::{ZeroLen, Unknown};
1209
1210            #[test]
1211            #[allow(non_upper_case_globals)]
1212            fn known_unknown() {
1213                let a = || "a".chars();
1214                let b = || "b".chars();
1215
1216                let mut toc = Toc::new();
1217                _ = toc.add(a(), None);
1218
1219                assert_eq!(Ok(1), toc.acq(a()));
1220                assert_eq!(Err(Unknown), toc.acq(b()));
1221            }
1222
1223            #[test]
1224            fn zero_occurrent() {
1225                let toc = Toc::new();
1226                assert_eq!(Err(ZeroLen), toc.acq("".chars()));
1227            }
1228        }
1229
1230        mod put {
1231            use crate::Toc;
1232            use crate::KeyError::{ZeroLen, Unknown};
1233
1234            #[test]
1235            #[allow(non_upper_case_globals)]
1236            fn known_unknown() {
1237                let a = || "a".chars();
1238                let b = || "b".chars();
1239
1240                let mut toc = Toc::new();
1241                _ = toc.add(a(), None);
1242
1243                assert_eq!(Ok(1), toc.put(a(), 3));
1244                assert_eq!(Ok(3), toc.acq(a()));
1245                assert_eq!(Err(Unknown), toc.put(b(), 3));
1246            }
1247
1248            #[test]
1249            fn zero_occurrent() {
1250                let mut toc = Toc::new();
1251                assert_eq!(Err(ZeroLen), toc.put("".chars(), 3));
1252            }
1253        }
1254
1255        mod rem {
1256            use crate::Toc;
1257            use crate::KeyError::{ZeroLen, Unknown};
1258
1259            #[test]
1260            fn known_unknown() {
1261                let known = || "VigilantAndVigourous".chars();
1262                let unknown = || "NeglectfulAndFeeble".chars();
1263
1264                let mut toc = Toc::new();
1265                _ = toc.add(known(), None);
1266
1267                assert_eq!(Err(Unknown), toc.rem(unknown()));
1268                assert_eq!(0, toc.tr.len());
1269
1270                assert_eq!(1, toc.ct());
1271
1272                assert_eq!(Ok(1), toc.rem(known()));
1273                assert_eq!(Err(Unknown), toc.acq(known()));
1274                assert_eq!(0, toc.tr.len());
1275
1276                assert_eq!(0, toc.ct());
1277            }
1278
1279            #[test]
1280            fn zero_occurrent() {
1281                let mut toc = Toc::new();
1282                assert_eq!(Err(ZeroLen), toc.rem("".chars()));
1283            }
1284        }
1285
1286        mod rem_actual {
1287            use crate::{Toc, TraRes};
1288            use crate::KeyError::Unknown;
1289            use crate::english_letters::ix;
1290
1291            #[test]
1292            fn basic_test() {
1293                let entry = || "ABCxyz".chars();
1294                let mut toc = Toc::new();
1295                _ = toc.add(entry(), None);
1296
1297                _ = toc.track(entry(), true, false);
1298
1299                assert_eq!(1, Toc::rem_actual(&mut toc));
1300
1301                #[allow(non_snake_case)]
1302                let K = &toc.rt[ix('A')];
1303                assert_eq!(false, K.ab());
1304            }
1305
1306            #[test]
1307            fn ab_len_test() {
1308                let ix = |c| match c {
1309                    | 'a' => 0,
1310                    | 'z' => 99,
1311                    | _ => panic!(),
1312                };
1313
1314                let key_1 = || "aaa".chars();
1315                let key_2 = || "aaz".chars();
1316
1317                let key_1_val = 50;
1318                let key_2_val = 60;
1319
1320                let mut toc = Toc::new_with(ix, None, 100);
1321                _ = toc.add(key_1(), Some(key_1_val));
1322                _ = toc.add(key_2(), Some(key_2_val));
1323
1324                _ = toc.track(key_1(), true, false);
1325
1326                assert_eq!(key_1_val, Toc::rem_actual(&mut toc));
1327                assert!(toc.acq(key_2()).is_ok());
1328            }
1329
1330            #[test]
1331            fn inner_entry() {
1332                let mut toc = Toc::new();
1333
1334                let outer = || "Keyword".chars();
1335                _ = toc.add(outer(), None);
1336
1337                let inner = || "Key".chars();
1338                _ = toc.add(inner(), None);
1339
1340                _ = toc.track(inner(), true, false);
1341
1342                assert_eq!(1, Toc::rem_actual(&mut toc));
1343                assert_eq!(Err(Unknown), toc.acq(inner()));
1344                assert_eq!(Ok(1), toc.acq(outer()));
1345            }
1346
1347            #[test]
1348            fn entry_with_peer_entry() {
1349                let mut toc = Toc::new();
1350
1351                let peer = || "Keyworder".chars();
1352                _ = toc.add(peer(), None);
1353
1354                let test = || "Keywordee".chars();
1355                _ = toc.add(test(), None);
1356
1357                _ = toc.track(test(), true, false);
1358
1359                assert_eq!(1, Toc::rem_actual(&mut toc));
1360                assert_eq!(Err(Unknown), toc.acq(test()));
1361                assert_eq!(Ok(1), toc.acq(peer()));
1362            }
1363
1364            #[test]
1365            fn entry_with_peer_with_alphabet() {
1366                let mut toc = Toc::new();
1367
1368                let peer = || "Keyworders".chars();
1369                _ = toc.add(peer(), None);
1370
1371                let test = || "Keywordee".chars();
1372                _ = toc.add(test(), None);
1373
1374                _ = toc.track(test(), true, false);
1375
1376                assert_eq!(1, Toc::rem_actual(&mut toc));
1377                assert_eq!(Err(Unknown), toc.acq(test()));
1378                assert_eq!(Ok(1), toc.acq(peer()));
1379            }
1380
1381            #[test]
1382            fn entry_under_entry() {
1383                let mut toc = Toc::new();
1384
1385                let above = || "Keyworder".chars();
1386                _ = toc.add(above(), None);
1387
1388                let under = || "Keyworders".chars();
1389                _ = toc.add(under(), None);
1390
1391                _ = toc.track(under(), true, false);
1392
1393                assert_eq!(1, Toc::rem_actual(&mut toc));
1394                assert_eq!(Err(Unknown), toc.acq(under()));
1395                assert_eq!(Ok(1), toc.acq(above()));
1396
1397                let res = toc.track(above(), false, false);
1398                if let TraRes::Ok(l) = res {
1399                    #[cfg(feature = "test-ext")]
1400                    assert_eq!('r', l.val);
1401                    assert_eq!(false, l.ab());
1402                } else {
1403                    panic!("TraRes::Ok(_) was expected, instead {:?}.", res);
1404                }
1405            }
1406        }
1407
1408        mod track {
1409            use crate::{Toc, TraRes};
1410
1411            #[test]
1412            fn zero_occurrent() {
1413                let toc = Toc::new();
1414                let res = toc.track("".chars(), false, false);
1415                assert_eq!(TraRes::ZeroLen, res);
1416            }
1417
1418            #[test]
1419            #[cfg(feature = "test-ext")]
1420            fn singular_occurrent() {
1421                let entry = || "A".chars();
1422
1423                let mut toc = Toc::new();
1424
1425                _ = toc.add(entry(), None);
1426                let res = toc.track(entry(), true, false);
1427
1428                if let TraRes::Ok(l) = res {
1429                    let l_val = l.val;
1430                    let tr = &toc.tr;
1431
1432                    assert_eq!('A', l_val);
1433                    assert_eq!(1, tr.len());
1434
1435                    let l = unsafe { tr[0].as_ref() }.unwrap();
1436                    assert_eq!('A', l.val)
1437                } else {
1438                    panic!("TraRes::Ok(_) was expected, instead {:?}.", res);
1439                }
1440            }
1441
1442            #[test]
1443            #[cfg(feature = "test-ext")]
1444            fn tracing() {
1445                let entry = || "DictionaryLexicon".chars();
1446
1447                let mut toc = Toc::new();
1448                _ = toc.add(entry(), None);
1449                _ = toc.track(entry(), true, false);
1450
1451                let proof = entry().collect::<Vec<char>>();
1452                let tr = &toc.tr;
1453
1454                assert_eq!(proof.len(), tr.len());
1455
1456                for (x, &c) in proof.iter().enumerate() {
1457                    let l = tr[x];
1458                    let l = unsafe { l.as_ref() }.unwrap();
1459                    assert_eq!(c, l.val);
1460                }
1461            }
1462
1463            #[test]
1464            #[cfg(feature = "test-ext")]
1465            fn ok_variants() {
1466                let entry = || "Wordbook".chars();
1467                let last = 'k';
1468
1469                let mut toc = Toc::new();
1470                _ = toc.add(entry(), None);
1471                let res = toc.track(entry(), false, false);
1472
1473                match res {
1474                    | TraRes::Ok(l) => assert_eq!(last, l.val),
1475                    | _ => panic!("TraRes::Ok(_) was expected, instead {:?}.", res),
1476                }
1477
1478                let res = toc.track(entry(), false, true);
1479                match res {
1480                    | TraRes::OkMut(l) => assert_eq!(last, l.val),
1481                    | _ => panic!("TraRes::OkMut(_) was expected, instead {:?}.", res),
1482                }
1483            }
1484
1485            #[test]
1486            fn unknown_not_path() {
1487                let key = || "Wordbook".chars();
1488                let bad_key = || "Wordbooks".chars();
1489
1490                let mut toc = Toc::new();
1491                _ = toc.add(key(), None);
1492                let res = toc.track(bad_key(), false, false);
1493                assert_eq!(TraRes::UnknownForAbsentPath, res);
1494            }
1495
1496            #[test]
1497            fn unknown_not_entry() {
1498                let key = || "Wordbooks".chars();
1499                let bad_key = || "Wordbook".chars();
1500
1501                let mut toc = Toc::new();
1502                _ = toc.add(key(), None);
1503                let res = toc.track(bad_key(), false, false);
1504                assert_eq!(TraRes::UnknownForNotEntry, res);
1505            }
1506        }
1507
1508        mod ext {
1509            use crate::Toc;
1510            use crate::english_letters::ix;
1511
1512            #[test]
1513            fn basic_test() {
1514                let proof = vec![
1515                    (String::from("AA"), 13),
1516                    (String::from("AzBq"), 11),
1517                    (String::from("By"), 329),
1518                    (String::from("ZaZazAzAzAbYyb"), 55),
1519                    (String::from("yBC"), 7),
1520                    (String::from("ybXr"), 53),
1521                    (String::from("ybXrQUTmop"), 33),
1522                    (String::from("ybXrQUTmopFVB"), 99),
1523                    (String::from("ybXrQUTmopRFG"), 80),
1524                    (String::from("zAzAZaZaZaByYB"), 44),
1525                ];
1526
1527                let mut toc = Toc::new();
1528                for p in proof.iter() {
1529                    _ = toc.add(p.0.chars(), Some(p.1));
1530                }
1531
1532                let ext = toc.ext();
1533                assert_eq!(true, ext.is_some());
1534
1535                let ext = ext.unwrap();
1536                assert_eq!(proof.len(), ext.len());
1537                assert_eq!(proof, ext);
1538                assert_eq!(true, ext.capacity() >= 1000);
1539
1540                for p in proof.iter() {
1541                    assert_eq!(Ok(p.1), toc.acq(p.0.chars()));
1542                }
1543            }
1544
1545            #[test]
1546            #[should_panic(
1547                expected = "This method is unsupported when `new_with` `re` parameter is provided with `None`."
1548            )]
1549            fn re_not_provided() {
1550                _ = Toc::new_with(ix, None, 0).ext()
1551            }
1552
1553            #[test]
1554            fn empty_tree() {
1555                let toc = Toc::new();
1556                assert_eq!(None, toc.ext());
1557            }
1558        }
1559
1560        use crate::KeyError::Unknown;
1561
1562        #[test]
1563        fn clr() {
1564            let key = || "abc".chars();
1565
1566            let mut toc = Toc::new();
1567            _ = toc.add(key(), None);
1568            assert_eq!(1, toc.clr());
1569
1570            assert_eq!(Err(Unknown), toc.acq(key()));
1571            assert_eq!(ab(ALPHABET_LEN), toc.rt);
1572            assert_eq!(0, toc.ct);
1573        }
1574
1575        #[test]
1576        fn ct() {
1577            let test = 3;
1578            let mut toc = Toc::new();
1579            assert_eq!(0, toc.ct());
1580            toc.ct = test;
1581            assert_eq!(test, toc.ct());
1582        }
1583    }
1584}
1585
1586// cargo fmt && cargo test --features test-ext --release
1587// cargo fmt && cargo test --release