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