1#![deny(
174 missing_docs,
175 trivial_casts,
176 trivial_numeric_casts,
177 unsafe_code,
178 unused_import_braces,
179 unused_qualifications
180)]
181#![feature(test, try_trait_v2)]
182extern crate test;
183
184use smallvec::SmallVec;
185use std::{
186 collections::HashMap,
187 convert::Infallible,
188 ops::{ControlFlow, FromResidual, Try},
189};
190
191pub type SVec<A> = SmallVec<[A; 8]>;
195
196pub type Spec<'b, 'a, A, D, C> = (
198 &'b [(&'static str, Option<&'a Decider<A, D>>)],
199 Finalizer<A, C>,
200);
201
202pub type Finalizer<A, C> = fn(&mut C, &[A]) -> Result<String, String>;
205
206pub type FinWithArgs<'o, A, C> = (Finalizer<A, C>, SVec<A>);
208
209pub type MapOrDesc<'a, 'b, A, D, C> = Either<&'b Mapping<'a, A, D, C>, &'a str>;
211
212pub enum Either<L, R> {
216 Left(L),
218 Right(R),
220}
221
222impl<L, R> Either<L, R> {
223 pub fn left(self) -> Option<L> {
225 match self {
226 Either::Left(left) => Some(left),
227 Either::Right(_) => None,
228 }
229 }
230 pub fn right(self) -> Option<R> {
232 match self {
233 Either::Left(_) => None,
234 Either::Right(right) => Some(right),
235 }
236 }
237}
238
239#[derive(Debug, PartialEq)]
246pub enum Decision<D> {
247 Accept(usize),
249 Deny(D),
251}
252
253impl<R> FromResidual<Result<Infallible, R>> for Decision<R> {
254 fn from_residual(residual: Result<Infallible, R>) -> Self {
255 Decision::Deny(residual.err().unwrap())
256 }
257}
258
259impl<D> FromResidual<D> for Decision<D> {
260 fn from_residual(residual: D) -> Self {
261 Decision::Deny(residual)
262 }
263}
264
265impl<D> Try for Decision<D> {
266 type Output = usize;
267 type Residual = D;
268 fn from_output(output: Self::Output) -> Self {
269 Decision::Accept(output)
270 }
271
272 fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
273 match self {
274 Decision::Accept(value) => ControlFlow::Continue(value),
275 Decision::Deny(value) => ControlFlow::Break(value),
276 }
277 }
278}
279
280pub struct Decider<A, D> {
286 pub description: &'static str,
288 pub decider: fn(&[&str], &mut SVec<A>) -> Decision<D>,
292}
293
294#[derive(Debug, PartialEq)]
296pub enum RegError {
297 DeciderAlreadyExists,
299 FinalizerAlreadyExists,
301}
302
303#[derive(Debug, PartialEq)]
305pub enum LookError<D> {
306 DeciderAdvancedTooFar,
308 DeciderDenied(String, D),
310 FinalizerDoesNotExist,
312 UnknownMapping(String),
314}
315
316pub struct MappingEntry<'a, A, D, C> {
318 pub literal: &'a str,
320 pub decider: Option<&'a Decider<A, D>>,
322 pub finalizer: Option<Finalizer<A, C>>,
324 pub submap: &'a HashMap<&'a str, Mapping<'a, A, D, C>>,
326}
327
328pub struct Mapping<'a, A, D, C> {
336 map: HashMap<&'a str, Mapping<'a, A, D, C>>,
337 decider: Option<&'a Decider<A, D>>,
338 finalizer: Option<Finalizer<A, C>>,
339}
340
341impl<'a, A, D, C> Default for Mapping<'a, A, D, C> {
342 fn default() -> Self {
343 Mapping {
344 map: HashMap::new(),
345 decider: None,
346 finalizer: None,
347 }
348 }
349}
350
351impl<'a, A, D, C> Mapping<'a, A, D, C> {
352 pub fn register_many<'b>(&mut self, spec: &[Spec<'b, 'a, A, D, C>]) -> Result<(), RegError> {
354 for subspec in spec {
355 self.register(subspec.clone())?;
356 }
357 Ok(())
358 }
359
360 pub fn register<'b>(&mut self, spec: Spec<'b, 'a, A, D, C>) -> Result<(), RegError> {
366 if spec.0.is_empty() {
367 if self.finalizer.is_some() {
368 return Err(RegError::FinalizerAlreadyExists);
369 }
370 self.finalizer = Some(spec.1);
371 return Ok(());
372 }
373 let key = spec.0[0].0;
374 let decider = spec.0[0].1;
375 if let Some(ref mut entry) = self.map.get_mut(key) {
376 if decider.is_some() {
377 return Err(RegError::DeciderAlreadyExists);
378 }
379 entry.register((&spec.0[1..], spec.1))?;
380 } else {
381 let mut mapping = Mapping::<A, D, C> {
382 map: HashMap::new(),
383 decider,
384 finalizer: None,
385 };
386 mapping.register((&spec.0[1..], spec.1))?;
387 self.map.insert(key, mapping);
388 }
389 Ok(())
390 }
391
392 pub fn lookup(&self, input: &[&str]) -> Result<FinWithArgs<A, C>, LookError<D>> {
394 let mut output = SVec::<A>::new();
395 match self.lookup_internal(input, &mut output) {
396 Ok((finalizer, _advance)) => Ok((finalizer, output)),
397 Err(err) => Err(err),
398 }
399 }
400
401 fn lookup_internal(
403 &self,
404 input: &[&str],
405 output: &mut SVec<A>,
406 ) -> Result<(Finalizer<A, C>, usize), LookError<D>> {
407 if input.is_empty() {
408 if let Some(finalizer) = self.finalizer {
409 return Ok((finalizer, 0));
410 } else {
411 return Err(LookError::FinalizerDoesNotExist);
412 }
413 }
414 if let Some(handler) = self.map.get(&input[0]) {
415 let mut advance_output = 0;
416 if let Some(ref decider) = handler.decider {
417 match (decider.decider)(&input[1..], output) {
418 Decision::Accept(byte_count) => {
419 advance_output = byte_count;
420 }
421 Decision::Deny(res) => {
422 return Err(LookError::DeciderDenied(decider.description.into(), res));
423 }
424 }
425 }
426 if input.len() > advance_output {
427 let res = handler.lookup_internal(&input[1 + advance_output..], output);
428 if let Ok(mut res) = res {
429 res.1 += advance_output;
430 return Ok(res);
431 } else {
432 return res;
433 }
434 } else {
435 return Err(LookError::DeciderAdvancedTooFar);
436 }
437 }
438 Err(LookError::UnknownMapping(input[0].to_string()))
439 }
440
441 pub fn get_direct_keys(&self) -> impl Iterator<Item = MappingEntry<'_, A, D, C>> {
443 self.map.iter().map(|(k, v)| MappingEntry {
444 literal: *k,
445 decider: v.decider,
446 finalizer: v.finalizer,
447 submap: &v.map,
448 })
449 }
450
451 pub fn partial_lookup<'b>(
453 &'b self,
454 input: &'b [&str],
455 ) -> Result<MapOrDesc<'a, 'b, A, D, C>, LookError<D>> {
456 let mut output = SVec::<A>::new();
457 self.partial_lookup_internal(input, &mut output)
458 }
459
460 fn partial_lookup_internal<'b>(
465 &'b self,
466 input: &'b [&str],
467 output: &mut SVec<A>,
468 ) -> Result<MapOrDesc<'a, 'b, A, D, C>, LookError<D>> {
469 if input.is_empty() {
470 return Ok(Either::Left(self));
471 }
472 if let Some(handler) = self.map.get(&input[0]) {
473 let mut advance_output = 0;
474 if let Some(ref decider) = handler.decider {
475 if input.len() == 1 {
476 return Ok(Either::Right(decider.description));
477 }
478 match (decider.decider)(&input[1..], output) {
479 Decision::Accept(res) => {
480 advance_output = res;
481 }
482 Decision::Deny(res) => {
483 return Err(LookError::DeciderDenied(decider.description.into(), res));
484 }
485 }
486 }
487 if input.len() > advance_output {
488 return handler.partial_lookup_internal(&input[1 + advance_output..], output);
489 } else {
490 return Err(LookError::DeciderAdvancedTooFar);
491 }
492 }
493 Err(LookError::UnknownMapping(input[0].to_string()))
494 }
495
496 pub fn decider(&self) -> &Option<&'a Decider<A, D>> {
498 &self.decider
499 }
500
501 pub fn finalizer(&self) -> &Option<Finalizer<A, C>> {
503 &self.finalizer
504 }
505
506 pub fn iter(&self) -> impl Iterator<Item = (&&'a str, &Mapping<'a, A, D, C>)> {
508 self.map.iter()
509 }
510}
511
512#[cfg(test)]
515mod tests {
516 use super::*;
517 use test::{black_box, Bencher};
518
519 type Accept = bool;
522 type Context = u32;
523
524 fn add_one(ctx: &mut Context, _: &[Accept]) -> Result<String, String> {
525 *ctx += 1;
526 Ok("".into())
527 }
528
529 #[test]
532 fn single_mapping() {
533 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
534 mapping.register((&[("add-one", None)], add_one)).unwrap();
535 let handler = mapping.lookup(&["add-one"]).unwrap();
536 assert_eq!(0, handler.1.len());
537 let mut ctx = 123;
538 handler.0(&mut ctx, &handler.1).unwrap();
539 assert_eq!(124, ctx);
540 }
541
542 #[test]
543 fn mapping_does_not_exist() {
544 let mapping: Mapping<Accept, (), Context> = Mapping::default();
545 if let Err(err) = mapping.lookup(&["add-one"]) {
546 assert_eq!(LookError::UnknownMapping("add-one".into()), err);
547 } else {
548 assert!(false);
549 }
550 }
551
552 #[test]
553 fn overlapping_decider_fails() {
554 fn decide(_: &[&str], _: &mut SVec<Accept>) -> Decision<()> {
555 Decision::Deny(())
556 }
557
558 const DECIDE: Decider<Accept, ()> = Decider {
559 description: "",
560 decider: decide,
561 };
562
563 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
564 mapping.register((&[("add-one", None)], add_one)).unwrap();
565 assert_eq!(
566 Err(RegError::DeciderAlreadyExists),
567 mapping.register((&[("add-one", Some(&DECIDE))], add_one))
568 );
569 }
570
571 #[test]
572 fn sequences_decider_fails() {
573 fn decide(_: &[&str], _: &mut SVec<Accept>) -> Decision<()> {
574 Decision::Deny(())
575 }
576
577 const DECIDE: Decider<Accept, ()> = Decider {
578 description: "",
579 decider: decide,
580 };
581
582 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
583 mapping
584 .register((&[("add-one", Some(&DECIDE))], add_one))
585 .unwrap();
586 if let Err(err) = mapping.register((&[("add-one", None)], add_one)) {
587 assert_eq!(RegError::FinalizerAlreadyExists, err);
588 } else {
589 assert!(false);
590 }
591 }
592
593 #[test]
594 fn decider_of_one() {
595 fn decide(_: &[&str], out: &mut SVec<Accept>) -> Decision<()> {
596 out.push(true);
597 Decision::Accept(1)
598 }
599
600 const DECIDE: Decider<Accept, ()> = Decider {
601 description: "",
602 decider: decide,
603 };
604
605 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
606 mapping
607 .register((&[("add-one", Some(&DECIDE))], add_one))
608 .unwrap();
609
610 let out = mapping.lookup(&["add-one", "123"]).unwrap();
611 assert_eq!(1, out.1.len());
612 assert_eq!(true, out.1[0]);
613 }
614
615 #[test]
616 fn decider_of_two_overrun() {
617 fn decide(_: &[&str], out: &mut SVec<Accept>) -> Decision<()> {
618 out.push(true);
619 out.push(true);
620 Decision::Accept(2)
621 }
622
623 const DECIDE: Decider<Accept, ()> = Decider {
624 description: "",
625 decider: decide,
626 };
627
628 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
629 mapping
630 .register((&[("add-one", Some(&DECIDE))], add_one))
631 .unwrap();
632
633 if let Err(err) = mapping.lookup(&["add-one", "123"]) {
634 assert_eq!(LookError::DeciderAdvancedTooFar, err);
635 } else {
636 assert!(false);
637 }
638 }
639
640 #[test]
641 fn decider_of_two() {
642 fn decide(_: &[&str], out: &mut SVec<Accept>) -> Decision<()> {
643 out.push(true);
644 out.push(false);
645 Decision::Accept(2)
646 }
647
648 const DECIDE: Decider<Accept, ()> = Decider {
649 description: "",
650 decider: decide,
651 };
652
653 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
654 mapping
655 .register((&[("add-one", Some(&DECIDE))], add_one))
656 .unwrap();
657
658 let output = mapping.lookup(&["add-one", "123", "456"]).unwrap().1;
659 assert_eq!(2, output.len());
660 assert_eq!(true, output[0]);
661 assert_eq!(false, output[1]);
662 }
663
664 #[test]
665 fn decider_of_two_short_output() {
666 fn decide(_: &[&str], _: &mut SVec<Accept>) -> Decision<()> {
667 Decision::Accept(2)
668 }
669
670 const DECIDE: Decider<Accept, ()> = Decider {
671 description: "",
672 decider: decide,
673 };
674
675 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
676 mapping
677 .register((&[("add-one", Some(&DECIDE))], add_one))
678 .unwrap();
679
680 let output = mapping.lookup(&["add-one", "123", "456"]).unwrap();
681 assert_eq!(0, output.1.len());
682 }
683
684 #[test]
685 fn decider_of_many() {
686 fn decide(input: &[&str], out: &mut SVec<i32>) -> Decision<()> {
687 for i in input.iter() {
688 let number = i.parse::<i32>();
689 if let Ok(number) = number {
690 out.push(number);
691 } else {
692 return Decision::Deny(());
693 }
694 }
695 Decision::Accept(input.len())
696 }
697
698 const DECIDE: Decider<i32, ()> = Decider {
699 description: "",
700 decider: decide,
701 };
702
703 fn do_sum(ctx: &mut u32, out: &[i32]) -> Result<String, String> {
704 for i in out {
705 *ctx += *i as u32;
706 }
707 Ok("".into())
708 }
709 let mut mapping: Mapping<i32, (), Context> = Mapping::default();
710 mapping
711 .register((&[("sum", Some(&DECIDE))], do_sum))
712 .unwrap();
713
714 let handler = mapping.lookup(&["sum", "123", "456", "789"]).unwrap();
715 assert_eq!(3, handler.1.len());
716
717 let mut ctx = 0;
718 handler.0(&mut ctx, &handler.1).unwrap();
719 assert_eq!(1368, ctx);
720 }
721
722 #[test]
723 fn nested() {
724 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
725 mapping
726 .register((
727 &[("lorem", None), ("ipsum", None), ("dolor", None)],
728 add_one,
729 ))
730 .unwrap();
731
732 mapping.lookup(&["lorem", "ipsum", "dolor"]).unwrap();
733 if let Err(err) = mapping.lookup(&["lorem", "ipsum", "dolor", "exceed"]) {
734 assert_eq!(LookError::UnknownMapping("exceed".into()), err);
735 } else {
736 assert!(false);
737 }
738 if let Err(err) = mapping.lookup(&["lorem", "ipsum"]) {
739 assert_eq!(LookError::FinalizerDoesNotExist, err);
740 } else {
741 assert!(false);
742 }
743 }
744
745 #[test]
746 fn finalizer_at_multiple_levels() {
747 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
748 mapping
749 .register((
750 &[("lorem", None), ("ipsum", None), ("dolor", None)],
751 add_one,
752 ))
753 .unwrap();
754 mapping
755 .register((&[("lorem", None), ("ipsum", None)], add_one))
756 .unwrap();
757
758 mapping.lookup(&["lorem", "ipsum", "dolor"]).unwrap();
759 if let Err(err) = mapping.lookup(&["lorem", "ipsum", "dolor", "exceed"]) {
760 assert_eq!(LookError::UnknownMapping("exceed".into()), err);
761 } else {
762 assert!(false);
763 }
764 mapping.lookup(&["lorem", "ipsum"]).unwrap();
765 }
766
767 #[test]
768 fn partial_lookup() {
769 fn decide(_: &[&str], _: &mut SVec<Accept>) -> Decision<()> {
770 Decision::Accept(0)
771 }
772
773 const DECIDE: Decider<Accept, ()> = Decider {
774 description: "Do nothing",
775 decider: decide,
776 };
777
778 fn consume_decide(input: &[&str], _: &mut SVec<Accept>) -> Decision<()> {
779 if input.is_empty() {
780 Decision::Deny(())
781 } else {
782 Decision::Accept(1)
783 }
784 }
785
786 const CONSUME_DECIDE: Decider<Accept, ()> = Decider {
787 description: "Consume a single element, regardless of what it is",
788 decider: consume_decide,
789 };
790
791 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
792 mapping
793 .register((
794 &[("lorem", None), ("ipsum", None), ("dolor", None)],
795 add_one,
796 ))
797 .unwrap();
798 mapping
799 .register((&[("lorem", None), ("ipsum", None)], add_one))
800 .unwrap();
801 mapping
802 .register((&[("mirana", None), ("ipsum", Some(&DECIDE))], add_one))
803 .unwrap();
804 mapping
805 .register((
806 &[("consume", Some(&CONSUME_DECIDE)), ("dummy", None)],
807 add_one,
808 ))
809 .unwrap();
810
811 let part = mapping
812 .partial_lookup(&["lorem", "ipsum"])
813 .unwrap()
814 .left()
815 .unwrap();
816 let key = part.get_direct_keys().next().unwrap();
817 assert_eq!("dolor", key.literal);
818 assert!(key.decider.is_none());
819 assert!(key.finalizer.is_some());
820
821 let part = mapping.partial_lookup(&["lorem"]).unwrap().left().unwrap();
822 let key = part.get_direct_keys().next().unwrap();
823 assert_eq!("ipsum", key.literal);
824 assert!(key.decider.is_none());
825 assert!(key.finalizer.is_some());
826
827 let part = mapping.partial_lookup(&["mirana"]).unwrap().left().unwrap();
828 let key = part.get_direct_keys().next().unwrap();
829 assert_eq!("ipsum", key.literal);
830 assert!(key.decider.is_some());
831 assert_eq!("Do nothing", key.decider.unwrap().description);
832 assert!(key.finalizer.is_some());
833
834 let part = mapping
835 .partial_lookup(&["consume", "123"])
836 .unwrap()
837 .left()
838 .unwrap();
839 let key = part.get_direct_keys().next().unwrap();
840 assert_eq!("dummy", key.literal);
841 assert!(key.decider.is_none());
842 assert!(key.finalizer.is_some());
843
844 let part = mapping
845 .partial_lookup(&["consume"])
846 .unwrap()
847 .right()
848 .unwrap();
849 assert_eq!("Consume a single element, regardless of what it is", part);
850 }
851
852 #[quickcheck_macros::quickcheck]
855 fn default_contains_no_elements(strings: Vec<String>) -> bool {
856 type Accept = ();
857 type Deny = ();
858 type Context = ();
859 let strings_ref = strings.iter().map(|s| &s[..]).collect::<Vec<_>>();
860 let mapping: Mapping<Accept, Deny, Context> = Mapping::default();
861 match mapping.lookup(&strings_ref[..]) {
862 Err(LookError::UnknownMapping(string)) => string == strings[0],
863 Err(LookError::FinalizerDoesNotExist) => strings.is_empty(),
864 _ => false,
865 }
866 }
867
868 #[bench]
871 fn lookup_speed(b: &mut Bencher) {
872 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
873 mapping
874 .register((
875 &[("lorem", None), ("ipsum", None), ("dolor", None)],
876 add_one,
877 ))
878 .unwrap();
879 b.iter(|| {
880 black_box(mapping.lookup(black_box(&["lorem", "ipsum", "dolor"]))).unwrap();
881 });
882 }
883
884 #[bench]
885 fn partial_lookup_speed(b: &mut Bencher) {
886 let mut mapping: Mapping<Accept, (), Context> = Mapping::default();
887 mapping
888 .register((
889 &[("lorem", None), ("ipsum", None), ("dolor", None)],
890 add_one,
891 ))
892 .unwrap();
893 b.iter(|| {
894 mapping.partial_lookup(black_box(&["lorem"])).unwrap();
895 });
896 }
897}