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::new();
65 ab.reserve_exact(len);
66
67 #[cfg(test)]
68 #[cfg(feature = "test-ext")]
69 let mut c = 'A' as u8;
70
71 let sc = ab.spare_capacity_mut();
72 for ix in 0..len {
73 let mut _letter = sc[ix].write(Letter::new());
74
75 #[cfg(test)]
76 #[cfg(feature = "test-ext")]
77 {
78 _letter.val = c as char;
79
80 const Z: u8 = 'Z' as u8;
81 c = if c == Z { 'a' as u8 } else { c + 1 }
82 }
83 }
84
85 unsafe { ab.set_len(len) };
86
87 ab.into_boxed_slice()
88}
89
90pub mod english_letters {
94
95 pub const BASE_ALPHABET_LEN: usize = 26;
97 pub const ALPHABET_LEN: usize = BASE_ALPHABET_LEN * 2;
99
100 const A: usize = 'A' as usize;
101 #[allow(non_upper_case_globals)]
102 const a: usize = 'a' as usize;
103
104 pub fn ix(c: char) -> usize {
106 let code_point = c as usize;
107
108 match code_point {
109 | c if c > 64 && c < 91 => c - A,
110 | c if c > 96 && c < 123 => c - a + BASE_ALPHABET_LEN,
111 | _ => {
112 panic!("Index conversion failed because code point `{code_point}` is unsupported.")
113 },
114 }
115 }
116
117 pub fn re(i: usize) -> char {
119 let code_point = match i {
120 | i if i < 26 => i + A,
121 | i if i > 25 && i < 52 => i + a - BASE_ALPHABET_LEN,
122 | _ => {
123 panic!("Char conversion failed because index `{i}` conversion is not supported.")
124 },
125 };
126
127 code_point as u8 as char
128 }
129}
130
131#[derive(Debug, PartialEq, Eq, Clone)]
133pub enum KeyError {
134 ZeroLen,
136 Unknown,
138}
139
140#[cfg_attr(test, derive(PartialEq, Debug))]
141enum TraRes<'a> {
142 Ok(&'a Letter),
143 OkMut(&'a mut Letter),
144 ZeroLen,
145 UnknownForNotEntry,
146 UnknownForAbsentPath,
147}
148
149impl<'a> TraRes<'a> {
150 fn ver_res(&self) -> KeyError {
151 let p = || panic!("Unsupported");
152
153 return match self {
154 | TraRes::ZeroLen => KeyError::ZeroLen,
155 | TraRes::UnknownForNotEntry | TraRes::UnknownForAbsentPath => KeyError::Unknown,
156 | TraRes::Ok(_) => p(),
157 | TraRes::OkMut(_) => p(),
158 };
159 }
160}
161
162fn ext(ab: &Alphabet, buff: &mut String, re: Re, o: &mut Vec<(String, usize)>) {
167 for ix in 0..ab.len() {
168 buff.push(re(ix));
169
170 let letter = &ab[ix];
171
172 if let Some(ct) = letter.ct {
173 let key = buff.clone();
174 o.push((key, ct));
175 }
176
177 if let Some(ab) = letter.ab.as_ref() {
178 ext(ab, buff, re, o);
179 }
180
181 _ = buff.pop();
182 }
183}
184
185pub struct Toc {
211 rt: Alphabet,
213 ix: Ix,
215 re: Option<Re>,
217 al: usize,
219 tr: UC<Vec<*mut Letter>>,
221 ct: usize,
223}
224
225impl Toc {
226 pub fn new() -> Self {
229 Self::new_with(
230 english_letters::ix,
231 Some(english_letters::re),
232 english_letters::ALPHABET_LEN,
233 )
234 }
235
236 pub fn new_with(ix: Ix, re: Option<Re>, ab_len: usize) -> Self {
271 Self {
272 rt: ab(ab_len),
273 ix,
274 re,
275 al: ab_len,
276 tr: UC::new(Vec::new()),
277 ct: 0,
278 }
279 }
280
281 pub fn put_trace_cap(&mut self, approx_cap: usize) -> usize {
310 let tr = &mut self.tr;
311 let cp = tr.capacity();
312
313 if cp < approx_cap {
314 tr.reserve(approx_cap);
315 } else if cp > approx_cap {
316 *tr.aq_mut() = Vec::with_capacity(approx_cap);
317 }
318
319 tr.capacity()
320 }
321
322 pub fn acq_trace_cap(&self) -> usize {
326 self.tr.capacity()
327 }
328
329 pub fn add(&mut self, mut occurrent: impl Iterator<Item = char>, val: Option<usize>) -> AddRes {
341 let c = occurrent.next();
342
343 if c.is_none() {
344 return Err(KeyError::ZeroLen);
345 }
346
347 let c = unsafe { c.unwrap_unchecked() };
348
349 let ix = self.ix;
350 let al = self.al;
351
352 let mut letter = &mut self.rt[ix(c)];
353
354 while let Some(c) = occurrent.next() {
355 let alphabet = letter.ab.get_or_insert_with(|| ab(al));
356 letter = &mut alphabet[ix(c)];
357 }
358
359 let ct = letter.ct;
360
361 let ct_none = ct.is_none();
362 if ct_none {
363 self.ct += 1;
364 }
365
366 letter.ct = Some(if let Some(v) = val {
367 v
368 } else {
369 if ct_none {
370 1
371 } else {
372 unsafe { ct.unwrap_unchecked() }.wrapping_add(1)
373 }
374 });
375
376 Ok(ct)
377 }
378
379 pub fn acq(&self, occurrent: impl Iterator<Item = char>) -> VerRes {
383 let track_res = self.track(occurrent, false, false);
384 if let TraRes::Ok(l) = track_res {
385 let ct = l.ct;
386 let ct = unsafe { ct.unwrap_unchecked() };
387 Ok(ct)
388 } else {
389 Err(track_res.ver_res())
390 }
391 }
392
393 pub fn put(&mut self, occurrent: impl Iterator<Item = char>, val: usize) -> VerRes {
397 let track_res = self.track(occurrent, false, true);
398
399 if let TraRes::OkMut(l) = track_res {
400 let old = l.ct.replace(val);
401 let old = unsafe { old.unwrap_unchecked() };
402 Ok(old)
403 } else {
404 Err(track_res.ver_res())
405 }
406 }
407
408 pub fn rem(&mut self, occurrent: impl Iterator<Item = char>) -> VerRes {
418 let track_res = self.track(occurrent, true, false);
419 let res = if let TraRes::Ok(_) = track_res {
420 let ct = Self::rem_actual(self);
421 self.ct -= 1;
422 Ok(ct)
423 } else {
424 Err(track_res.ver_res())
425 };
426
427 self.tr.clear();
428 res
429 }
430
431 fn rem_actual(&mut self) -> usize {
432 let mut trace = self.tr.iter().map(|x| unsafe { x.as_mut() }.unwrap());
433 let entry = unsafe { trace.next_back().unwrap_unchecked() };
434
435 let ct = entry.ct.take();
436
437 if !entry.ab() {
438 while let Some(l) = trace.next_back() {
439 let alphabet = l.ab.as_ref().unwrap();
440 let mut remove_alphab = true;
441
442 for ix in 0..self.al {
443 let letter = &alphabet[ix];
444
445 if letter.ab() || letter.ct() {
446 remove_alphab = false;
447 break;
448 }
449 }
450
451 if remove_alphab {
452 l.ab = None;
453 } else {
454 break;
455 }
456
457 if l.ct() {
458 break;
459 }
460 }
461 }
462
463 unsafe { ct.unwrap_unchecked() }
464 }
465
466 fn track(
470 &self,
471 mut occurrent: impl Iterator<Item = char>,
472 tracing: bool,
473 okmut: bool,
474 ) -> TraRes {
475 let c = occurrent.next();
476
477 if c.is_none() {
478 return TraRes::ZeroLen;
479 }
480
481 let c = unsafe { c.unwrap_unchecked() };
482
483 let ix = &self.ix;
484 let tr = self.tr.uplift();
485
486 let mut letter = &self.rt[ix(c)];
487
488 loop {
489 if tracing {
490 tr.push(letter.to_mut_ptr())
491 }
492
493 if let Some(c) = occurrent.next() {
494 if let Some(ab) = letter.ab.as_ref() {
495 letter = &ab[ix(c)];
496 } else {
497 return TraRes::UnknownForAbsentPath;
498 }
499 } else {
500 break;
501 }
502 }
503
504 if letter.ct() {
505 if okmut {
506 let l_mut = unsafe { letter.to_mut_ptr().as_mut().unwrap_unchecked() };
507 TraRes::OkMut(l_mut)
508 } else {
509 TraRes::Ok(letter)
510 }
511 } else {
512 TraRes::UnknownForNotEntry
513 }
514 }
515
516 pub fn ext(&self) -> Option<Vec<(String, usize)>> {
528 if let Some(re) = self.re {
529 if self.ct == 0 {
530 return None;
531 }
532
533 let mut buff = String::with_capacity(1000);
535
536 let mut res = Vec::with_capacity(1000);
538
539 ext(&self.rt, &mut buff, re, &mut res);
540 Some(res)
541 } else {
542 panic!("This method is unsupported when `new_with` `re` parameter is provided with `None`.");
543 }
544 }
545
546 pub fn clr(&mut self) -> usize {
552 self.rt = ab(self.al);
553 let ct = self.ct;
554 self.ct = 0;
555 ct
556 }
557
558 pub const fn ct(&self) -> usize {
560 self.ct
561 }
562}
563
564#[cfg(test)]
565mod tests_of_units {
566
567 use crate::Letter;
568 use std::fmt::{Debug, Formatter};
569
570 impl Debug for Letter {
571 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
572 let ab = some_none(self.ab.as_ref());
573
574 return f.write_fmt(format_args!(
575 "Letter {{\n val: {}\n ab: {}\n ct: {:?}\n}}",
576 self.val, ab, self.ct
577 ));
578
579 fn some_none<T>(val: Option<&T>) -> &'static str {
580 if val.is_some() {
581 "Some"
582 } else {
583 "None"
584 }
585 }
586 }
587 }
588
589 mod letter {
590
591 use crate::{Letter, ab as ab_fn};
592
593 #[test]
594 fn new() {
595 let letter = Letter::new();
596
597 assert_eq!('💚', letter.val);
598 assert!(letter.ab.is_none());
599 assert!(letter.ct.is_none());
600 }
601
602 #[test]
603 fn ab() {
604 let mut letter = Letter::new();
605 assert_eq!(false, letter.ab());
606
607 letter.ab = Some(ab_fn(0));
608 assert_eq!(true, letter.ab());
609 }
610
611 #[test]
612 fn ct() {
613 let mut letter = Letter::new();
614 assert_eq!(false, letter.ct());
615
616 letter.ct = Some(0);
617 assert_eq!(true, letter.ct());
618 }
619 }
620
621 mod ab {
622
623 use crate::english_letters::ALPHABET_LEN;
624 use crate::ab as ab_fn;
625
626 #[test]
627 fn ab() {
628 let ab = ab_fn(ALPHABET_LEN);
629 assert_eq!(ALPHABET_LEN, ab.len());
630
631 #[cfg(feature = "test-ext")]
632 {
633 let chain = ('A'..='Z').chain('a'..='z');
634
635 for (ix, c) in chain.enumerate() {
636 let letter = &ab[ix];
637
638 assert_eq!(c, letter.val);
639 assert!(letter.ab.is_none());
640 assert!(letter.ct.is_none());
641 }
642 }
643 }
644
645 #[test]
646 fn zero_len() {
647 let ab = ab_fn(0);
648 assert_eq!(0, ab.len());
649 }
650 }
651
652 mod english_letters {
653
654 use crate::english_letters::{ALPHABET_LEN, BASE_ALPHABET_LEN};
655
656 #[test]
657 fn consts() {
658 assert_eq!(26, BASE_ALPHABET_LEN);
659 assert_eq!(52, ALPHABET_LEN);
660 }
661
662 mod ix {
663 use crate::english_letters::ix;
664 use std::panic::catch_unwind;
665
666 #[test]
667 fn ixes() {
668 assert_eq!(0, ix('A'));
669 assert_eq!(25, ix('Z'));
670 assert_eq!(26, ix('a'));
671 assert_eq!(51, ix('z'));
672 }
673
674 #[test]
675 fn unsupported_char() {
676 let ucs = unsupported_chars();
677
678 for (c, cp) in ucs.map(|x| (x as char, x)) {
679 let result = catch_unwind(|| ix(c));
680 assert!(result.is_err());
681
682 let err = unsafe { result.unwrap_err_unchecked() };
683 let downcast = err.downcast_ref::<String>().unwrap();
684 let proof = format!(
685 "Index conversion failed because code point `{cp}` is unsupported."
686 );
687 assert_eq!(&proof, downcast);
688 }
689 }
690
691 fn unsupported_chars() -> [u8; 4] {
692 #[rustfmt::skip] let ucs =
693 [
694 'A' as u8 -1, 'Z' as u8 +1, 'a' as u8 -1, 'z' as u8 +1, ];
697 ucs
698 }
699 }
700
701 mod re {
702 use crate::english_letters::re;
703
704 #[test]
705 fn ixes() {
706 assert_eq!('A', re(0));
707 assert_eq!('Z', re(25));
708 assert_eq!('a', re(26));
709 assert_eq!('z', re(51));
710 }
711
712 #[test]
713 #[should_panic(
714 expected = "Char conversion failed because index `52` conversion is not supported."
715 )]
716 fn unsupported_ix() {
717 _ = re(52)
718 }
719 }
720 }
721
722 mod ext {
723
724 type Nest = (char, usize);
725
726 use crate::{ab as ab_ctor, ext, Alphabet};
727 use crate::english_letters::{ALPHABET_LEN, ix, re};
728
729 fn ab_fn() -> Alphabet {
730 ab_ctor(ALPHABET_LEN)
731 }
732
733 #[test]
734 fn basic_test() {
735 let mut ab = ab_fn();
736
737 ab[ix('A')].ct = Some(1);
738 ab[ix('z')].ct = Some(2);
739
740 let mut buff = String::new();
741 let mut test = Vec::new();
742
743 ext(&ab, &mut buff, re, &mut test);
744
745 let proof = vec![(String::from("A"), 1), (String::from("z"), 2)];
746 assert_eq!(proof, test);
747 }
748
749 #[test]
750 fn nesting() {
751 let mut root = ab_fn();
752
753 let nesting = [
754 (('A', 3), ('z', 5)),
755 (('B', 5), ('y', 8)),
756 (('y', 10), ('B', 12)),
757 (('z', 99), ('A', 103)),
758 ];
759
760 for n in nesting {
761 prep(&mut root, n);
762 }
763
764 let mut buff = String::new();
765 let mut test = Vec::new();
766
767 ext(&root, &mut buff, re, &mut test);
768
769 let proof = vec![
770 (String::from("A"), 3),
771 (String::from("Az"), 5),
772 (String::from("B"), 5),
773 (String::from("By"), 8),
774 (String::from("y"), 10),
775 (String::from("yB"), 12),
776 (String::from("z"), 99),
777 (String::from("zA"), 103),
778 ];
779
780 assert_eq!(proof, test);
781
782 fn prep(ab: &mut Alphabet, n: (Nest, Nest)) {
783 let ultra = n.0;
784 let infra = n.1;
785
786 let u_l = &mut ab[ix(ultra.0)];
787 let mut ul_ab = ab_fn();
788
789 let i_l = &mut ul_ab[ix(infra.0)];
790 i_l.ct = Some(infra.1);
791
792 u_l.ab = Some(ul_ab);
793 u_l.ct = Some(ultra.1);
794 }
795 }
796
797 #[test]
798 fn in_depth_recursion() {
799 let mut root = ab_fn();
800
801 let paths = [
802 ("AA", 13),
803 ("AzBq", 11),
804 ("By", 329),
805 ("ZaZazAzAzAbYyb", 55),
806 ("yBC", 7),
807 ("ybXr", 53),
808 ("ybXrQUTmop", 33),
809 ("ybXrQUTmopFVB", 99),
810 ("ybXrQUTmopRFG", 80),
811 ("zAzAZaZaZaByYB", 44),
812 ];
813
814 for p in paths {
815 let mut chars = p.0.chars();
816 let mut le = &mut root[ix(chars.next().unwrap())];
817
818 while let Some(c) = chars.next() {
819 let ab = le.ab.get_or_insert_with(|| ab_fn());
820 le = &mut ab[ix(c)];
821 }
822
823 le.ct = Some(p.1)
824 }
825
826 let mut buff = String::new();
827 let mut test = Vec::new();
828
829 ext(&root, &mut buff, re, &mut test);
830
831 let proof = vec![
832 (String::from("AA"), 13),
833 (String::from("AzBq"), 11),
834 (String::from("By"), 329),
835 (String::from("ZaZazAzAzAbYyb"), 55),
836 (String::from("yBC"), 7),
837 (String::from("ybXr"), 53),
838 (String::from("ybXrQUTmop"), 33),
839 (String::from("ybXrQUTmopFVB"), 99),
840 (String::from("ybXrQUTmopRFG"), 80),
841 (String::from("zAzAZaZaZaByYB"), 44),
842 ];
843
844 assert_eq!(proof, test);
845 }
846 }
847
848 mod track_res {
849 use crate::{TraRes, Letter};
850 use crate::KeyError::{ZeroLen, Unknown};
851
852 #[test]
853 fn ver_res_convertible() {
854 assert_eq!(ZeroLen, TraRes::ZeroLen.ver_res());
855 assert_eq!(Unknown, TraRes::UnknownForAbsentPath.ver_res());
856 assert_eq!(Unknown, TraRes::UnknownForNotEntry.ver_res());
857 }
858
859 use std::{ops::Deref, panic::catch_unwind};
860 #[test]
861 fn ver_res_nonconvertible() {
862 let err = catch_unwind(|| TraRes::Ok(&Letter::new()).ver_res());
863
864 assert_eq!(true, err.is_err());
865 assert_eq!(
866 &"Unsupported",
867 err.unwrap_err().downcast::<&str>().unwrap().deref()
868 );
869
870 let err = catch_unwind(|| TraRes::OkMut(&mut Letter::new()).ver_res());
871
872 assert_eq!(true, err.is_err());
873 assert_eq!(
874 &"Unsupported",
875 err.unwrap_err().downcast::<&str>().unwrap().deref()
876 );
877 }
878 }
879
880 mod toc {
881 use crate::{Toc, ab};
882 use crate::english_letters::{ix, re, ALPHABET_LEN};
883
884 #[test]
885 fn new() {
886 let toc = Toc::new();
887 assert_eq!(ALPHABET_LEN, toc.al);
888 assert_eq!(ix as usize, toc.ix as usize);
889 assert_eq!(re as usize, toc.re.unwrap() as usize);
890 }
891
892 #[test]
893 fn new_with() {
894 fn test_ix(_c: char) -> usize {
895 0
896 }
897
898 fn test_re(_i: usize) -> char {
899 '\0'
900 }
901
902 let ab_len = 10;
903 let toc = Toc::new_with(test_ix, Some(test_re), ab_len);
904
905 assert_eq!(ab(ab_len), toc.rt);
906 assert_eq!(ab_len, toc.al);
907 assert_eq!(test_ix as usize, toc.ix as usize);
908 assert_eq!(test_re as usize, toc.re.unwrap() as usize);
909 assert_eq!(0, toc.tr.capacity());
910 assert_eq!(0, toc.ct);
911 }
912
913 mod put_trace_cap {
914 use crate::Toc;
915
916 #[test]
917 fn extend() {
918 const NEW_CAP: usize = 10;
919
920 let mut toc = Toc::new();
921 assert!(toc.tr.capacity() < NEW_CAP);
922
923 let size = toc.put_trace_cap(NEW_CAP);
924 assert!(size >= NEW_CAP);
925 assert!(toc.tr.capacity() >= NEW_CAP);
926 }
927
928 #[test]
929 fn shrink() {
930 const NEW_CAP: usize = 10;
931 const OLD_CAP: usize = 50;
932
933 let mut toc = Toc::new();
934 *toc.tr = Vec::with_capacity(OLD_CAP);
935
936 let size = toc.put_trace_cap(NEW_CAP);
937 assert!(size >= NEW_CAP && size < OLD_CAP);
938 let cap = toc.tr.capacity();
939 assert!(cap >= NEW_CAP && cap < OLD_CAP);
940 }
941
942 #[test]
943 fn same() {
944 let mut toc = Toc::new();
945 let cap = toc.tr.capacity();
946
947 let size = toc.put_trace_cap(cap);
948 assert_eq!(cap, size);
949 assert_eq!(cap, toc.tr.capacity());
950 }
951 }
952
953 #[test]
954 fn acq_trace_cap() {
955 const VAL: usize = 10;
956
957 let mut toc = Toc::new();
958 let tr = &mut toc.tr;
959
960 assert!(tr.capacity() < VAL);
961 tr.reserve_exact(VAL);
962 assert_eq!(VAL, 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