1use std::vec::Vec;
6
7pub type VerRes = Result<usize, KeyError>;
9pub type AddRes = Result<Option<usize>, KeyError>;
11
12mod uc;
13use uc::UC;
14
15mod aide;
16
17#[cfg_attr(test, derive(PartialEq))]
19struct Letter {
20 #[cfg(test)]
21 val: char,
22 ab: Option<Alphabet>,
23 ct: Option<usize>,
24}
25
26impl Letter {
27 const fn new() -> Self {
28 Letter {
29 #[cfg(test)]
30 val: '💚',
31 ab: None,
32 ct: None,
33 }
34 }
35
36 const fn ab(&self) -> bool {
37 self.ab.is_some()
38 }
39
40 const fn ct(&self) -> bool {
41 self.ct.is_some()
42 }
43
44 const fn to_mut_ptr(&self) -> *mut Self {
45 (self as *const Self).cast_mut()
46 }
47}
48
49type Alphabet = Box<[Letter]>;
51pub type Ix = fn(char) -> usize;
56
57pub type Re = fn(usize) -> char;
61
62fn ab(len: usize) -> Alphabet {
64 let mut ab = Vec::with_capacity(len);
65
66 #[cfg(test)]
67 #[cfg(feature = "test-ext")]
68 let mut c = 'A' as u8;
69
70 let sc = ab.spare_capacity_mut();
71 for ix in 0..len {
72 let mut _letter = sc[ix].write(Letter::new());
73
74 #[cfg(test)]
75 #[cfg(feature = "test-ext")]
76 {
77 _letter.val = c as char;
78
79 const Z: u8 = 'Z' as u8;
80 c = if c == Z { 'a' as u8 } else { c + 1 }
81 }
82 }
83
84 unsafe { ab.set_len(len) };
85
86 ab.into_boxed_slice()
87}
88
89pub mod english_letters {
93
94 pub const BASE_ALPHABET_LEN: usize = 26;
96 pub const ALPHABET_LEN: usize = BASE_ALPHABET_LEN * 2;
98
99 const A: usize = 'A' as usize;
100 #[allow(non_upper_case_globals)]
101 const a: usize = 'a' as usize;
102
103 pub fn ix(c: char) -> usize {
105 let code_point = c as usize;
106
107 match code_point {
108 | c if c > 64 && c < 91 => c - A,
109 | c if c > 96 && c < 123 => c - a + BASE_ALPHABET_LEN,
110 | _ => {
111 panic!("Index conversion failed because code point `{code_point}` is unsupported.")
112 },
113 }
114 }
115
116 pub fn re(i: usize) -> char {
118 let code_point = match i {
119 | i if i < 26 => i + A,
120 | i if i > 25 && i < 52 => i + a - BASE_ALPHABET_LEN,
121 | _ => {
122 panic!("Char conversion failed because index `{i}` conversion is not supported.")
123 },
124 };
125
126 code_point as u8 as char
127 }
128}
129
130#[derive(Debug, PartialEq, Eq, Clone)]
132pub enum KeyError {
133 ZeroLen,
135 Unknown,
137}
138
139#[cfg_attr(test, derive(PartialEq, Debug))]
140enum TraRes<'a> {
141 Ok(&'a Letter),
142 OkMut(&'a mut Letter),
143 ZeroLen,
144 UnknownForNotEntry,
145 UnknownForAbsentPath,
146}
147
148impl<'a> TraRes<'a> {
149 fn ver_res(&self) -> KeyError {
150 let p = || panic!("Unsupported");
151
152 return match self {
153 | TraRes::ZeroLen => KeyError::ZeroLen,
154 | TraRes::UnknownForNotEntry | TraRes::UnknownForAbsentPath => KeyError::Unknown,
155 | TraRes::Ok(_) => p(),
156 | TraRes::OkMut(_) => p(),
157 };
158 }
159}
160
161fn ext(ab: &Alphabet, buff: &mut String, re: Re, o: &mut Vec<(String, usize)>) {
166 for ix in 0..ab.len() {
167 buff.push(re(ix));
168
169 let letter = &ab[ix];
170
171 if let Some(ct) = letter.ct {
172 let key = buff.clone();
173 o.push((key, ct));
174 }
175
176 if let Some(ab) = letter.ab.as_ref() {
177 ext(ab, buff, re, o);
178 }
179
180 _ = buff.pop();
181 }
182}
183
184pub struct Toc {
210 rt: Alphabet,
212 ix: Ix,
214 re: Option<Re>,
216 al: usize,
218 tr: UC<Vec<*mut Letter>>,
220 ct: usize,
222}
223
224impl Toc {
225 pub fn new() -> Self {
228 Self::new_with(
229 english_letters::ix,
230 Some(english_letters::re),
231 english_letters::ALPHABET_LEN,
232 )
233 }
234
235 pub fn new_with(ix: Ix, re: Option<Re>, ab_len: usize) -> Self {
270 Self {
271 rt: ab(ab_len),
272 ix,
273 re,
274 al: ab_len,
275 tr: UC::new(Vec::new()),
276 ct: 0,
277 }
278 }
279
280 pub fn put_trace_cap(&mut self, approx_cap: usize) -> usize {
309 let tr = &mut self.tr;
310 let cp = tr.capacity();
311
312 if cp < approx_cap {
313 tr.reserve(approx_cap);
314 } else if cp > approx_cap {
315 *tr.aq_mut() = Vec::with_capacity(approx_cap);
316 }
317
318 tr.capacity()
319 }
320
321 pub fn acq_trace_cap(&self) -> usize {
325 self.tr.capacity()
326 }
327
328 pub fn add(&mut self, mut occurrent: impl Iterator<Item = char>, val: Option<usize>) -> AddRes {
340 let c = occurrent.next();
341
342 if c.is_none() {
343 return Err(KeyError::ZeroLen);
344 }
345
346 let c = unsafe { c.unwrap_unchecked() };
347
348 let ix = self.ix;
349 let al = self.al;
350
351 let mut letter = &mut self.rt[ix(c)];
352
353 while let Some(c) = occurrent.next() {
354 let alphabet = letter.ab.get_or_insert_with(|| ab(al));
355 letter = &mut alphabet[ix(c)];
356 }
357
358 let ct = letter.ct;
359
360 let ct_none = ct.is_none();
361 if ct_none {
362 self.ct += 1;
363 }
364
365 letter.ct = Some(if let Some(v) = val {
366 v
367 } else {
368 if ct_none {
369 1
370 } else {
371 unsafe { ct.unwrap_unchecked() }.wrapping_add(1)
372 }
373 });
374
375 Ok(ct)
376 }
377
378 pub fn acq(&self, occurrent: impl Iterator<Item = char>) -> VerRes {
382 let track_res = self.track(occurrent, false, false);
383 if let TraRes::Ok(l) = track_res {
384 let ct = l.ct;
385 let ct = unsafe { ct.unwrap_unchecked() };
386 Ok(ct)
387 } else {
388 Err(track_res.ver_res())
389 }
390 }
391
392 pub fn put(&mut self, occurrent: impl Iterator<Item = char>, val: usize) -> VerRes {
396 let track_res = self.track(occurrent, false, true);
397
398 if let TraRes::OkMut(l) = track_res {
399 let old = l.ct.replace(val);
400 let old = unsafe { old.unwrap_unchecked() };
401 Ok(old)
402 } else {
403 Err(track_res.ver_res())
404 }
405 }
406
407 pub fn rem(&mut self, occurrent: impl Iterator<Item = char>) -> VerRes {
417 let track_res = self.track(occurrent, true, false);
418 let res = if let TraRes::Ok(_) = track_res {
419 let ct = Self::rem_actual(self);
420 self.ct -= 1;
421 Ok(ct)
422 } else {
423 Err(track_res.ver_res())
424 };
425
426 self.tr.clear();
427 res
428 }
429
430 fn rem_actual(&mut self) -> usize {
431 let mut trace = self.tr.iter().map(|x| unsafe { x.as_mut() }.unwrap());
432 let entry = unsafe { trace.next_back().unwrap_unchecked() };
433
434 let ct = entry.ct.take();
435
436 if !entry.ab() {
437 while let Some(l) = trace.next_back() {
438 let alphabet = l.ab.as_ref().unwrap();
439 let mut remove_alphab = true;
440
441 for ix in 0..self.al {
442 let letter = &alphabet[ix];
443
444 if letter.ab() || letter.ct() {
445 remove_alphab = false;
446 break;
447 }
448 }
449
450 if remove_alphab {
451 l.ab = None;
452 } else {
453 break;
454 }
455
456 if l.ct() {
457 break;
458 }
459 }
460 }
461
462 unsafe { ct.unwrap_unchecked() }
463 }
464
465 fn track(
469 &self,
470 mut occurrent: impl Iterator<Item = char>,
471 tracing: bool,
472 okmut: bool,
473 ) -> TraRes {
474 let c = occurrent.next();
475
476 if c.is_none() {
477 return TraRes::ZeroLen;
478 }
479
480 let c = unsafe { c.unwrap_unchecked() };
481
482 let ix = &self.ix;
483 let tr = self.tr.uplift();
484
485 let mut letter = &self.rt[ix(c)];
486
487 loop {
488 if tracing {
489 tr.push(letter.to_mut_ptr())
490 }
491
492 if let Some(c) = occurrent.next() {
493 if let Some(ab) = letter.ab.as_ref() {
494 letter = &ab[ix(c)];
495 } else {
496 return TraRes::UnknownForAbsentPath;
497 }
498 } else {
499 break;
500 }
501 }
502
503 if letter.ct() {
504 if okmut {
505 let l_mut = unsafe { letter.to_mut_ptr().as_mut().unwrap_unchecked() };
506 TraRes::OkMut(l_mut)
507 } else {
508 TraRes::Ok(letter)
509 }
510 } else {
511 TraRes::UnknownForNotEntry
512 }
513 }
514
515 pub fn ext(&self) -> Option<Vec<(String, usize)>> {
527 if let Some(re) = self.re {
528 if self.ct == 0 {
529 return None;
530 }
531
532 let mut buff = String::with_capacity(1000);
534
535 let mut res = Vec::with_capacity(1000);
537
538 ext(&self.rt, &mut buff, re, &mut res);
539 Some(res)
540 } else {
541 panic!("This method is unsupported when `new_with` `re` parameter is provided with `None`.");
542 }
543 }
544
545 pub fn clr(&mut self) -> usize {
551 self.rt = ab(self.al);
552 let ct = self.ct;
553 self.ct = 0;
554 ct
555 }
556
557 pub const fn ct(&self) -> usize {
559 self.ct
560 }
561}
562
563#[cfg(test)]
564mod tests_of_units {
565
566 use crate::Letter;
567 use std::fmt::{Debug, Formatter};
568
569 impl Debug for Letter {
570 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
571 let ab = some_none(self.ab.as_ref());
572
573 return f.write_fmt(format_args!(
574 "Letter {{\n val: {}\n ab: {}\n ct: {:?}\n}}",
575 self.val, ab, self.ct
576 ));
577
578 fn some_none<T>(val: Option<&T>) -> &'static str {
579 if val.is_some() {
580 "Some"
581 } else {
582 "None"
583 }
584 }
585 }
586 }
587
588 mod letter {
589
590 use crate::{Letter, ab as ab_fn};
591
592 #[test]
593 fn new() {
594 let letter = Letter::new();
595
596 assert_eq!('💚', letter.val);
597 assert!(letter.ab.is_none());
598 assert!(letter.ct.is_none());
599 }
600
601 #[test]
602 fn ab() {
603 let mut letter = Letter::new();
604 assert_eq!(false, letter.ab());
605
606 letter.ab = Some(ab_fn(0));
607 assert_eq!(true, letter.ab());
608 }
609
610 #[test]
611 fn ct() {
612 let mut letter = Letter::new();
613 assert_eq!(false, letter.ct());
614
615 letter.ct = Some(0);
616 assert_eq!(true, letter.ct());
617 }
618 }
619
620 mod ab {
621
622 use crate::english_letters::ALPHABET_LEN;
623 use crate::ab as ab_fn;
624
625 #[test]
626 fn ab() {
627 let ab = ab_fn(ALPHABET_LEN);
628 assert_eq!(ALPHABET_LEN, ab.len());
629
630 #[cfg(feature = "test-ext")]
631 {
632 let chain = ('A'..='Z').chain('a'..='z');
633
634 for (ix, c) in chain.enumerate() {
635 let letter = &ab[ix];
636
637 assert_eq!(c, letter.val);
638 assert!(letter.ab.is_none());
639 assert!(letter.ct.is_none());
640 }
641 }
642 }
643
644 #[test]
645 fn zero_len() {
646 let ab = ab_fn(0);
647 assert_eq!(0, ab.len());
648 }
649 }
650
651 mod english_letters {
652
653 use crate::english_letters::{ALPHABET_LEN, BASE_ALPHABET_LEN};
654
655 #[test]
656 fn consts() {
657 assert_eq!(26, BASE_ALPHABET_LEN);
658 assert_eq!(52, ALPHABET_LEN);
659 }
660
661 mod ix {
662 use crate::english_letters::ix;
663 use std::panic::catch_unwind;
664
665 #[test]
666 fn ixes() {
667 assert_eq!(0, ix('A'));
668 assert_eq!(25, ix('Z'));
669 assert_eq!(26, ix('a'));
670 assert_eq!(51, ix('z'));
671 }
672
673 #[test]
674 fn unsupported_char() {
675 let ucs = unsupported_chars();
676
677 for (c, cp) in ucs.map(|x| (x as char, x)) {
678 let result = catch_unwind(|| ix(c));
679 assert!(result.is_err());
680
681 let err = unsafe { result.unwrap_err_unchecked() };
682 let downcast = err.downcast_ref::<String>().unwrap();
683 let proof = format!(
684 "Index conversion failed because code point `{cp}` is unsupported."
685 );
686 assert_eq!(&proof, downcast);
687 }
688 }
689
690 fn unsupported_chars() -> [u8; 4] {
691 #[rustfmt::skip] let ucs =
692 [
693 'A' as u8 -1, 'Z' as u8 +1, 'a' as u8 -1, 'z' as u8 +1, ];
696 ucs
697 }
698 }
699
700 mod re {
701 use crate::english_letters::re;
702
703 #[test]
704 fn ixes() {
705 assert_eq!('A', re(0));
706 assert_eq!('Z', re(25));
707 assert_eq!('a', re(26));
708 assert_eq!('z', re(51));
709 }
710
711 #[test]
712 #[should_panic(
713 expected = "Char conversion failed because index `52` conversion is not supported."
714 )]
715 fn unsupported_ix() {
716 _ = re(52)
717 }
718 }
719 }
720
721 mod ext {
722
723 type Nest = (char, usize);
724
725 use crate::{ab as ab_ctor, ext, Alphabet};
726 use crate::english_letters::{ALPHABET_LEN, ix, re};
727
728 fn ab_fn() -> Alphabet {
729 ab_ctor(ALPHABET_LEN)
730 }
731
732 #[test]
733 fn basic_test() {
734 let mut ab = ab_fn();
735
736 ab[ix('A')].ct = Some(1);
737 ab[ix('z')].ct = Some(2);
738
739 let mut buff = String::new();
740 let mut test = Vec::new();
741
742 ext(&ab, &mut buff, re, &mut test);
743
744 let proof = vec![(String::from("A"), 1), (String::from("z"), 2)];
745 assert_eq!(proof, test);
746 }
747
748 #[test]
749 fn nesting() {
750 let mut root = ab_fn();
751
752 let nesting = [
753 (('A', 3), ('z', 5)),
754 (('B', 5), ('y', 8)),
755 (('y', 10), ('B', 12)),
756 (('z', 99), ('A', 103)),
757 ];
758
759 for n in nesting {
760 prep(&mut root, n);
761 }
762
763 let mut buff = String::new();
764 let mut test = Vec::new();
765
766 ext(&root, &mut buff, re, &mut test);
767
768 let proof = vec![
769 (String::from("A"), 3),
770 (String::from("Az"), 5),
771 (String::from("B"), 5),
772 (String::from("By"), 8),
773 (String::from("y"), 10),
774 (String::from("yB"), 12),
775 (String::from("z"), 99),
776 (String::from("zA"), 103),
777 ];
778
779 assert_eq!(proof, test);
780
781 fn prep(ab: &mut Alphabet, n: (Nest, Nest)) {
782 let ultra = n.0;
783 let infra = n.1;
784
785 let u_l = &mut ab[ix(ultra.0)];
786 let mut ul_ab = ab_fn();
787
788 let i_l = &mut ul_ab[ix(infra.0)];
789 i_l.ct = Some(infra.1);
790
791 u_l.ab = Some(ul_ab);
792 u_l.ct = Some(ultra.1);
793 }
794 }
795
796 #[test]
797 fn in_depth_recursion() {
798 let mut root = ab_fn();
799
800 let paths = [
801 ("AA", 13),
802 ("AzBq", 11),
803 ("By", 329),
804 ("ZaZazAzAzAbYyb", 55),
805 ("yBC", 7),
806 ("ybXr", 53),
807 ("ybXrQUTmop", 33),
808 ("ybXrQUTmopFVB", 99),
809 ("ybXrQUTmopRFG", 80),
810 ("zAzAZaZaZaByYB", 44),
811 ];
812
813 for p in paths {
814 let mut chars = p.0.chars();
815 let mut le = &mut root[ix(chars.next().unwrap())];
816
817 while let Some(c) = chars.next() {
818 let ab = le.ab.get_or_insert_with(|| ab_fn());
819 le = &mut ab[ix(c)];
820 }
821
822 le.ct = Some(p.1)
823 }
824
825 let mut buff = String::new();
826 let mut test = Vec::new();
827
828 ext(&root, &mut buff, re, &mut test);
829
830 let proof = vec![
831 (String::from("AA"), 13),
832 (String::from("AzBq"), 11),
833 (String::from("By"), 329),
834 (String::from("ZaZazAzAzAbYyb"), 55),
835 (String::from("yBC"), 7),
836 (String::from("ybXr"), 53),
837 (String::from("ybXrQUTmop"), 33),
838 (String::from("ybXrQUTmopFVB"), 99),
839 (String::from("ybXrQUTmopRFG"), 80),
840 (String::from("zAzAZaZaZaByYB"), 44),
841 ];
842
843 assert_eq!(proof, test);
844 }
845 }
846
847 mod track_res {
848 use crate::{TraRes, Letter};
849 use crate::KeyError::{ZeroLen, Unknown};
850
851 #[test]
852 fn ver_res_convertible() {
853 assert_eq!(ZeroLen, TraRes::ZeroLen.ver_res());
854 assert_eq!(Unknown, TraRes::UnknownForAbsentPath.ver_res());
855 assert_eq!(Unknown, TraRes::UnknownForNotEntry.ver_res());
856 }
857
858 use std::{ops::Deref, panic::catch_unwind};
859 #[test]
860 fn ver_res_nonconvertible() {
861 let err = catch_unwind(|| TraRes::Ok(&Letter::new()).ver_res());
862
863 assert_eq!(true, err.is_err());
864 assert_eq!(
865 &"Unsupported",
866 err.unwrap_err().downcast::<&str>().unwrap().deref()
867 );
868
869 let err = catch_unwind(|| TraRes::OkMut(&mut Letter::new()).ver_res());
870
871 assert_eq!(true, err.is_err());
872 assert_eq!(
873 &"Unsupported",
874 err.unwrap_err().downcast::<&str>().unwrap().deref()
875 );
876 }
877 }
878
879 mod toc {
880 use crate::{Toc, ab};
881 use crate::english_letters::{ix, re, ALPHABET_LEN};
882
883 #[test]
884 fn new() {
885 let toc = Toc::new();
886 assert_eq!(ALPHABET_LEN, toc.al);
887 assert_eq!(ix as usize, toc.ix as usize);
888 assert_eq!(re as usize, toc.re.unwrap() as usize);
889 }
890
891 #[test]
892 fn new_with() {
893 fn test_ix(_c: char) -> usize {
894 0
895 }
896
897 fn test_re(_i: usize) -> char {
898 '\0'
899 }
900
901 let ab_len = 10;
902 let toc = Toc::new_with(test_ix, Some(test_re), ab_len);
903
904 assert_eq!(ab(ab_len), toc.rt);
905 assert_eq!(ab_len, toc.al);
906 assert_eq!(test_ix as usize, toc.ix as usize);
907 assert_eq!(test_re as usize, toc.re.unwrap() as usize);
908 assert_eq!(0, toc.tr.capacity());
909 assert_eq!(0, toc.ct);
910 }
911
912 mod put_trace_cap {
913 use crate::Toc;
914
915 #[test]
916 fn extend() {
917 const NEW_CAP: usize = 10;
918
919 let mut toc = Toc::new();
920 assert!(toc.tr.capacity() < NEW_CAP);
921
922 let size = toc.put_trace_cap(NEW_CAP);
923 assert!(size >= NEW_CAP);
924 assert!(toc.tr.capacity() >= NEW_CAP);
925 }
926
927 #[test]
928 fn shrink() {
929 const NEW_CAP: usize = 10;
930 const OLD_CAP: usize = 50;
931
932 let mut toc = Toc::new();
933 *toc.tr = Vec::with_capacity(OLD_CAP);
934
935 let size = toc.put_trace_cap(NEW_CAP);
936 assert!(size >= NEW_CAP && size < OLD_CAP);
937 let cap = toc.tr.capacity();
938 assert!(cap >= NEW_CAP && cap < OLD_CAP);
939 }
940
941 #[test]
942 fn same() {
943 let mut toc = Toc::new();
944 let cap = toc.tr.capacity();
945
946 let size = toc.put_trace_cap(cap);
947 assert_eq!(cap, size);
948 assert_eq!(cap, toc.tr.capacity());
949 }
950 }
951
952 #[test]
953 fn acq_trace_cap() {
954 const VAL: usize = 10;
955
956 let mut toc = Toc::new();
957 let tr = &mut toc.tr;
958
959 assert!(tr.capacity() < VAL);
960 tr.reserve_exact(VAL);
961 let cap = tr.capacity();
962 assert_eq!(cap, toc.acq_trace_cap());
963 }
964
965 mod add {
966 use crate::Toc;
967 use crate::KeyError::ZeroLen;
968 use crate::english_letters::ix;
969
970 #[test]
971 fn basic_test() {
972 let entry = || "impreciseness".chars();
973
974 let mut toc = Toc::new();
975 assert_eq!(Ok(None), toc.add(entry(), None));
976 assert_eq!(1, toc.ct);
977
978 let chars: Vec<char> = entry().collect();
979 let len = chars.len();
980 let last_ix = len - 1;
981
982 let mut sup_ab = &toc.rt;
983 for c_ix in 0..len {
984 let c = chars[c_ix];
985 let l = &sup_ab[ix(c)];
986
987 let terminal_it = c_ix == last_ix;
988
989 let sub_ab = l.ab.as_ref();
990 assert_eq!(terminal_it, sub_ab.is_none(), "{c_ix}, {c}, {terminal_it}",);
991
992 if terminal_it {
993 let ct = l.ct.as_ref();
994 assert!(ct.is_some());
995 let ct = unsafe { ct.unwrap_unchecked() };
996 assert_eq!(&1, ct);
997 } else {
998 sup_ab = unsafe { sub_ab.unwrap_unchecked() };
999 }
1000 }
1001 }
1002
1003 #[test]
1004 fn zero_occurrent() {
1005 let mut toc = Toc::new();
1006 assert_eq!(Err(ZeroLen), toc.add("".chars(), None));
1007 assert_eq!(0, toc.ct);
1008 }
1009
1010 #[test]
1011 fn singular_occurrent() {
1012 let mut toc = Toc::new();
1013 assert_eq!(Ok(None), toc.add("a".chars(), None));
1014 assert_eq!(Some(1), toc.rt[ix('a')].ct);
1015 assert_eq!(1, toc.ct);
1016 }
1017
1018 #[test]
1019 fn double_add() {
1020 let entry = || "impreciseness".chars();
1021
1022 let mut toc = Toc::new();
1023 assert_eq!(Ok(None), toc.add(entry(), None));
1024 assert_eq!(1, toc.ct);
1025
1026 assert_eq!(Ok(Some(1)), toc.add(entry(), None));
1027 assert_eq!(1, toc.ct);
1028
1029 let chars: Vec<char> = entry().collect();
1030 let len = chars.len();
1031 let last_ix = len - 1;
1032
1033 let mut sup_ab = &toc.rt;
1034 for c_ix in 0..len {
1035 let c = chars[c_ix];
1036 let l = &sup_ab[ix(c)];
1037
1038 let terminal_it = c_ix == last_ix;
1039
1040 let sub_ab = l.ab.as_ref();
1041 assert_eq!(terminal_it, sub_ab.is_none(), "{c_ix}, {c}, {terminal_it}",);
1042
1043 if terminal_it {
1044 let ct = l.ct.as_ref();
1045 assert!(ct.is_some());
1046 let ct = unsafe { ct.unwrap_unchecked() };
1047 assert_eq!(&2, ct);
1048 } else {
1049 sup_ab = unsafe { sub_ab.unwrap_unchecked() };
1050 }
1051 }
1052 }
1053
1054 #[test]
1055 fn exact() {
1056 let entry = || "impreciseness".chars();
1057 const VAL: usize = 15;
1058
1059 let mut toc = Toc::new();
1060 assert_eq!(Ok(None), toc.add(entry(), Some(VAL)));
1061 assert_eq!(1, toc.ct);
1062
1063 assert_eq!(Ok(VAL), toc.acq(entry()));
1064 }
1065
1066 #[test]
1067 fn exact_over() {
1068 let entry = || "impreciseness".chars();
1069 const VAL: usize = 15;
1070
1071 let mut toc = Toc::new();
1072 _ = toc.add(entry(), None);
1073 assert_eq!(1, toc.ct);
1074
1075 assert_eq!(Ok(Some(1)), toc.add(entry(), Some(VAL)));
1076 assert_eq!(1, toc.ct);
1077
1078 assert_eq!(Ok(VAL), toc.acq(entry()));
1079 }
1080
1081 #[test]
1082 #[allow(non_snake_case)]
1083 #[rustfmt::skip]
1084 #[cfg(feature = "test-ext")]
1085 fn load() {
1086
1087 let strs = [
1088 ("zzbb", 44_441), ("zzaa", 88_999),
1089 ("xya", 77_666), ("xyz", 22_333),
1090 ("abc", 33_222), ("abd", 74_332),
1091 ("abcd", 11_234), ("abce", 11_234),
1092 ("qaa", 16_678), ("qrs", 24_555),
1093 ("qrt", 900_001), ("qua", 130_901),
1094 ("qwa", 2_006),
1095 ("percent", 77_110), ("percentile", 99_888),
1096 ("quail", 20_333), ("qualification", 33_111),
1097 ("quality", 555_666), ("quantity", 116_777),
1098 ("XYAB", 544_555), ("XYABA", 111_900),
1099 ("JUI", 30_000), ("JUN", 100_000),
1100 ("XYA", 80_000), ("XYQ", 11_111),
1101 ("XYZ", 111_333), ("XYABC", 222_000),
1102 ("MOMENT", 15_999), ("INSTANT", 34_341),
1103 ("JUNCTURE", 789_223),
1104 ("ABC", 14_234), ("ABD", 34_123)
1105 ];
1106
1107 let mut toc = Toc::new();
1108 for (s, c) in strs {
1109 for i in 0..c {
1110 let res = toc.add(s.chars(), None);
1111 let prev = if i > 0 {
1112 Some(i)
1113 } else {
1114 None
1115 };
1116 assert_eq!(Ok(prev), res);
1117 }
1118 }
1119
1120 for (s, c) in strs {
1121 let res = toc.acq(s.chars());
1122 assert_eq!(Ok(c), res);
1123 }
1124
1125 assert_eq!(strs.len(), toc.ct);
1126 }
1127
1128 #[test]
1129 fn overflow_wrap() {
1130 let mut toc = Toc::new();
1131
1132 let entry = || "a".chars();
1133
1134 _ = toc.add(entry(), None);
1135 _ = toc.put(entry(), usize::MAX);
1136 _ = toc.add(entry(), None);
1137 assert_eq!(Ok(0), toc.acq(entry()));
1138 assert_eq!(1, toc.ct);
1139 }
1140 }
1141
1142 mod acq {
1143 use crate::Toc;
1144 use crate::KeyError::{ZeroLen, Unknown};
1145
1146 #[test]
1147 #[allow(non_upper_case_globals)]
1148 fn known_unknown() {
1149 let a = || "a".chars();
1150 let b = || "b".chars();
1151
1152 let mut toc = Toc::new();
1153 _ = toc.add(a(), None);
1154
1155 assert_eq!(Ok(1), toc.acq(a()));
1156 assert_eq!(Err(Unknown), toc.acq(b()));
1157 }
1158
1159 #[test]
1160 fn zero_occurrent() {
1161 let toc = Toc::new();
1162 assert_eq!(Err(ZeroLen), toc.acq("".chars()));
1163 }
1164 }
1165
1166 mod put {
1167 use crate::Toc;
1168 use crate::KeyError::{ZeroLen, Unknown};
1169
1170 #[test]
1171 #[allow(non_upper_case_globals)]
1172 fn known_unknown() {
1173 let a = || "a".chars();
1174 let b = || "b".chars();
1175
1176 let mut toc = Toc::new();
1177 _ = toc.add(a(), None);
1178
1179 assert_eq!(Ok(1), toc.put(a(), 3));
1180 assert_eq!(Ok(3), toc.acq(a()));
1181 assert_eq!(Err(Unknown), toc.put(b(), 3));
1182 }
1183
1184 #[test]
1185 fn zero_occurrent() {
1186 let mut toc = Toc::new();
1187 assert_eq!(Err(ZeroLen), toc.put("".chars(), 3));
1188 }
1189 }
1190
1191 mod rem {
1192 use crate::Toc;
1193 use crate::KeyError::{ZeroLen, Unknown};
1194
1195 #[test]
1196 fn known_unknown() {
1197 let known = || "VigilantAndVigourous".chars();
1198 let unknown = || "NeglectfulAndFeeble".chars();
1199
1200 let mut toc = Toc::new();
1201 _ = toc.add(known(), None);
1202
1203 assert_eq!(Err(Unknown), toc.rem(unknown()));
1204 assert_eq!(0, toc.tr.len());
1205
1206 assert_eq!(1, toc.ct());
1207
1208 assert_eq!(Ok(1), toc.rem(known()));
1209 assert_eq!(Err(Unknown), toc.acq(known()));
1210 assert_eq!(0, toc.tr.len());
1211
1212 assert_eq!(0, toc.ct());
1213 }
1214
1215 #[test]
1216 fn zero_occurrent() {
1217 let mut toc = Toc::new();
1218 assert_eq!(Err(ZeroLen), toc.rem("".chars()));
1219 }
1220 }
1221
1222 mod rem_actual {
1223 use crate::{Toc, TraRes};
1224 use crate::KeyError::Unknown;
1225 use crate::english_letters::ix;
1226
1227 #[test]
1228 fn basic_test() {
1229 let entry = || "ABCxyz".chars();
1230 let mut toc = Toc::new();
1231 _ = toc.add(entry(), None);
1232
1233 _ = toc.track(entry(), true, false);
1234
1235 assert_eq!(1, Toc::rem_actual(&mut toc));
1236
1237 #[allow(non_snake_case)]
1238 let K = &toc.rt[ix('A')];
1239 assert_eq!(false, K.ab());
1240 }
1241
1242 #[test]
1243 fn ab_len_test() {
1244 let ix = |c| match c {
1245 | 'a' => 0,
1246 | 'z' => 99,
1247 | _ => panic!(),
1248 };
1249
1250 let key_1 = || "aaa".chars();
1251 let key_2 = || "aaz".chars();
1252
1253 let key_1_val = 50;
1254 let key_2_val = 60;
1255
1256 let mut toc = Toc::new_with(ix, None, 100);
1257 _ = toc.add(key_1(), Some(key_1_val));
1258 _ = toc.add(key_2(), Some(key_2_val));
1259
1260 _ = toc.track(key_1(), true, false);
1261
1262 assert_eq!(key_1_val, Toc::rem_actual(&mut toc));
1263 assert!(toc.acq(key_2()).is_ok());
1264 }
1265
1266 #[test]
1267 fn inner_entry() {
1268 let mut toc = Toc::new();
1269
1270 let outer = || "Keyword".chars();
1271 _ = toc.add(outer(), None);
1272
1273 let inner = || "Key".chars();
1274 _ = toc.add(inner(), None);
1275
1276 _ = toc.track(inner(), true, false);
1277
1278 assert_eq!(1, Toc::rem_actual(&mut toc));
1279 assert_eq!(Err(Unknown), toc.acq(inner()));
1280 assert_eq!(Ok(1), toc.acq(outer()));
1281 }
1282
1283 #[test]
1284 fn entry_with_peer_entry() {
1285 let mut toc = Toc::new();
1286
1287 let peer = || "Keyworder".chars();
1288 _ = toc.add(peer(), None);
1289
1290 let test = || "Keywordee".chars();
1291 _ = toc.add(test(), None);
1292
1293 _ = toc.track(test(), true, false);
1294
1295 assert_eq!(1, Toc::rem_actual(&mut toc));
1296 assert_eq!(Err(Unknown), toc.acq(test()));
1297 assert_eq!(Ok(1), toc.acq(peer()));
1298 }
1299
1300 #[test]
1301 fn entry_with_peer_with_alphabet() {
1302 let mut toc = Toc::new();
1303
1304 let peer = || "Keyworders".chars();
1305 _ = toc.add(peer(), None);
1306
1307 let test = || "Keywordee".chars();
1308 _ = toc.add(test(), None);
1309
1310 _ = toc.track(test(), true, false);
1311
1312 assert_eq!(1, Toc::rem_actual(&mut toc));
1313 assert_eq!(Err(Unknown), toc.acq(test()));
1314 assert_eq!(Ok(1), toc.acq(peer()));
1315 }
1316
1317 #[test]
1318 fn entry_under_entry() {
1319 let mut toc = Toc::new();
1320
1321 let above = || "Keyworder".chars();
1322 _ = toc.add(above(), None);
1323
1324 let under = || "Keyworders".chars();
1325 _ = toc.add(under(), None);
1326
1327 _ = toc.track(under(), true, false);
1328
1329 assert_eq!(1, Toc::rem_actual(&mut toc));
1330 assert_eq!(Err(Unknown), toc.acq(under()));
1331 assert_eq!(Ok(1), toc.acq(above()));
1332
1333 let res = toc.track(above(), false, false);
1334 if let TraRes::Ok(l) = res {
1335 #[cfg(feature = "test-ext")]
1336 assert_eq!('r', l.val);
1337 assert_eq!(false, l.ab());
1338 } else {
1339 panic!("TraRes::Ok(_) was expected, instead {:?}.", res);
1340 }
1341 }
1342 }
1343
1344 mod track {
1345 use crate::{Toc, TraRes};
1346
1347 #[test]
1348 fn zero_occurrent() {
1349 let toc = Toc::new();
1350 let res = toc.track("".chars(), false, false);
1351 assert_eq!(TraRes::ZeroLen, res);
1352 }
1353
1354 #[test]
1355 #[cfg(feature = "test-ext")]
1356 fn singular_occurrent() {
1357 let entry = || "A".chars();
1358
1359 let mut toc = Toc::new();
1360
1361 _ = toc.add(entry(), None);
1362 let res = toc.track(entry(), true, false);
1363
1364 if let TraRes::Ok(l) = res {
1365 let l_val = l.val;
1366 let tr = &toc.tr;
1367
1368 assert_eq!('A', l_val);
1369 assert_eq!(1, tr.len());
1370
1371 let l = unsafe { tr[0].as_ref() }.unwrap();
1372 assert_eq!('A', l.val)
1373 } else {
1374 panic!("TraRes::Ok(_) was expected, instead {:?}.", res);
1375 }
1376 }
1377
1378 #[test]
1379 #[cfg(feature = "test-ext")]
1380 fn tracing() {
1381 let entry = || "DictionaryLexicon".chars();
1382
1383 let mut toc = Toc::new();
1384 _ = toc.add(entry(), None);
1385 _ = toc.track(entry(), true, false);
1386
1387 let proof = entry().collect::<Vec<char>>();
1388 let tr = &toc.tr;
1389
1390 assert_eq!(proof.len(), tr.len());
1391
1392 for (x, &c) in proof.iter().enumerate() {
1393 let l = tr[x];
1394 let l = unsafe { l.as_ref() }.unwrap();
1395 assert_eq!(c, l.val);
1396 }
1397 }
1398
1399 #[test]
1400 #[cfg(feature = "test-ext")]
1401 fn ok_variants() {
1402 let entry = || "Wordbook".chars();
1403 let last = 'k';
1404
1405 let mut toc = Toc::new();
1406 _ = toc.add(entry(), None);
1407 let res = toc.track(entry(), false, false);
1408
1409 match res {
1410 | TraRes::Ok(l) => assert_eq!(last, l.val),
1411 | _ => panic!("TraRes::Ok(_) was expected, instead {:?}.", res),
1412 }
1413
1414 let res = toc.track(entry(), false, true);
1415 match res {
1416 | TraRes::OkMut(l) => assert_eq!(last, l.val),
1417 | _ => panic!("TraRes::OkMut(_) was expected, instead {:?}.", res),
1418 }
1419 }
1420
1421 #[test]
1422 fn unknown_not_path() {
1423 let key = || "Wordbook".chars();
1424 let bad_key = || "Wordbooks".chars();
1425
1426 let mut toc = Toc::new();
1427 _ = toc.add(key(), None);
1428 let res = toc.track(bad_key(), false, false);
1429 assert_eq!(TraRes::UnknownForAbsentPath, res);
1430 }
1431
1432 #[test]
1433 fn unknown_not_entry() {
1434 let key = || "Wordbooks".chars();
1435 let bad_key = || "Wordbook".chars();
1436
1437 let mut toc = Toc::new();
1438 _ = toc.add(key(), None);
1439 let res = toc.track(bad_key(), false, false);
1440 assert_eq!(TraRes::UnknownForNotEntry, res);
1441 }
1442 }
1443
1444 mod ext {
1445 use crate::Toc;
1446 use crate::english_letters::ix;
1447
1448 #[test]
1449 fn basic_test() {
1450 let proof = vec![
1451 (String::from("AA"), 13),
1452 (String::from("AzBq"), 11),
1453 (String::from("By"), 329),
1454 (String::from("ZaZazAzAzAbYyb"), 55),
1455 (String::from("yBC"), 7),
1456 (String::from("ybXr"), 53),
1457 (String::from("ybXrQUTmop"), 33),
1458 (String::from("ybXrQUTmopFVB"), 99),
1459 (String::from("ybXrQUTmopRFG"), 80),
1460 (String::from("zAzAZaZaZaByYB"), 44),
1461 ];
1462
1463 let mut toc = Toc::new();
1464 for p in proof.iter() {
1465 _ = toc.add(p.0.chars(), Some(p.1));
1466 }
1467
1468 let ext = toc.ext();
1469 assert_eq!(true, ext.is_some());
1470
1471 let ext = ext.unwrap();
1472 assert_eq!(proof.len(), ext.len());
1473 assert_eq!(proof, ext);
1474 assert_eq!(true, ext.capacity() >= 1000);
1475
1476 for p in proof.iter() {
1477 assert_eq!(Ok(p.1), toc.acq(p.0.chars()));
1478 }
1479 }
1480
1481 #[test]
1482 #[should_panic(
1483 expected = "This method is unsupported when `new_with` `re` parameter is provided with `None`."
1484 )]
1485 fn re_not_provided() {
1486 _ = Toc::new_with(ix, None, 0).ext()
1487 }
1488
1489 #[test]
1490 fn empty_tree() {
1491 let toc = Toc::new();
1492 assert_eq!(None, toc.ext());
1493 }
1494 }
1495
1496 use crate::KeyError::Unknown;
1497
1498 #[test]
1499 fn clr() {
1500 let key = || "abc".chars();
1501
1502 let mut toc = Toc::new();
1503 _ = toc.add(key(), None);
1504 assert_eq!(1, toc.clr());
1505
1506 assert_eq!(Err(Unknown), toc.acq(key()));
1507 assert_eq!(ab(ALPHABET_LEN), toc.rt);
1508 assert_eq!(0, toc.ct);
1509 }
1510
1511 #[test]
1512 fn ct() {
1513 let test = 3;
1514 let mut toc = Toc::new();
1515 assert_eq!(0, toc.ct());
1516 toc.ct = test;
1517 assert_eq!(test, toc.ct());
1518 }
1519 }
1520}
1521
1522