1use std::vec::Vec;
6
7pub type VerRes = Result<usize, KeyError>;
9pub 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#[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
113type Alphabet = Box<[Letter]>;
115pub type Ix = fn(char) -> usize;
120
121pub type Re = fn(usize) -> char;
125
126fn 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
154pub mod english_letters {
158
159 pub const BASE_ALPHABET_LEN: usize = 26;
161 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 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 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#[derive(Debug, PartialEq, Eq, Clone)]
197pub enum KeyError {
198 ZeroLen,
200 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
226fn 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
249pub struct Toc {
275 rt: Alphabet,
277 ix: Ix,
279 re: Option<Re>,
281 al: usize,
283 tr: UC<Vec<*mut Letter>>,
285 ct: usize,
287}
288
289impl Toc {
290 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 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 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 pub fn acq_trace_cap(&self) -> usize {
390 self.tr.capacity()
391 }
392
393 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 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 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 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 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 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 let mut buff = String::with_capacity(1000);
599
600 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 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 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, 'a' as u8 -1, 'z' as u8 +1, ];
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