1use std::borrow::Borrow;
7use std::fmt;
8use std::marker::PhantomData;
9
10#[doc(inline)]
13pub use crate::all_of;
14#[doc(inline)]
15pub use crate::any_of;
16
17pub mod request;
18
19pub struct ExecutionContext {
24 stack_depth: usize,
26}
27
28impl ExecutionContext {
29 pub fn evaluate<M, I>(matcher: &mut M, input: &I) -> bool
31 where
32 M: Matcher<I> + ?Sized,
33 I: fmt::Debug + ?Sized,
34 {
35 let mut ctx = ExecutionContext { stack_depth: 0 };
36 log::debug!(
37 "Matching {:?} with input: {:?}",
38 matcher_name(matcher),
39 input
40 );
41 let x = matcher.matches(input, &mut ctx);
42 log::debug!(
43 "┗━ {}",
44 if x {
45 "✅ matches"
46 } else {
47 "❌ does not match"
48 }
49 );
50 x
51 }
52
53 pub fn chain<M, I>(&mut self, matcher: &mut M, input: &I) -> bool
58 where
59 M: Matcher<I> + ?Sized,
60 I: fmt::Debug + ?Sized,
61 {
62 self.stack_depth += 1;
63 log::debug!(
64 "{}Matching {:?} with input: {:?}",
65 VerticalLines {
66 num_lines: self.stack_depth
67 },
68 matcher_name(matcher),
69 input
70 );
71 let x = matcher.matches(input, self);
72 log::debug!(
73 "{}┗━ {}",
74 VerticalLines {
75 num_lines: self.stack_depth
76 },
77 x
78 );
79 self.stack_depth -= 1;
80 x
81 }
82}
83
84struct VerticalLines {
85 num_lines: usize,
86}
87
88impl fmt::Display for VerticalLines {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 for _ in 0..self.num_lines {
91 write!(f, "┃ ")?;
92 }
93 Ok(())
94 }
95}
96
97pub trait Matcher<IN>: Send
101where
102 IN: ?Sized,
103{
104 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool;
106
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
110}
111
112pub(crate) fn matcher_name<M, IN>(mapper: &M) -> MatcherName<'_, M, IN>
115where
116 M: ?Sized,
117 IN: ?Sized,
118{
119 MatcherName(mapper, PhantomData)
120}
121pub(crate) struct MatcherName<'a, M, IN>(&'a M, PhantomData<&'a IN>)
122where
123 M: ?Sized,
124 IN: ?Sized;
125impl<'a, M, IN> fmt::Debug for MatcherName<'a, M, IN>
126where
127 M: Matcher<IN> + ?Sized,
128 IN: ?Sized,
129{
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 self.0.fmt(f)
132 }
133}
134
135pub fn any() -> Any {
146 Any
147}
148#[derive(Debug)]
150pub struct Any;
151impl<IN> Matcher<IN> for Any
152where
153 IN: ?Sized,
154{
155 fn matches(&mut self, _input: &IN, _ctx: &mut ExecutionContext) -> bool {
156 true
157 }
158
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 <Self as fmt::Debug>::fmt(self, f)
161 }
162}
163
164pub fn eq<T>(value: T) -> Eq<T> {
176 Eq(value)
177}
178pub struct Eq<T>(T)
180where
181 T: ?Sized;
182impl<IN, T> Matcher<IN> for Eq<T>
183where
184 T: Borrow<IN> + fmt::Debug + Send + ?Sized,
185 IN: PartialEq + ?Sized,
186{
187 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
188 self.0.borrow() == input
189 }
190
191 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192 <Self as fmt::Debug>::fmt(self, f)
193 }
194}
195impl<T> fmt::Debug for Eq<T>
196where
197 T: fmt::Debug + ?Sized,
198{
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 write!(f, "Eq({:?})", &self.0)
201 }
202}
203
204impl<IN> Matcher<IN> for &str
206where
207 IN: AsRef<[u8]> + ?Sized,
208{
209 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
210 self.as_bytes() == input.as_ref()
211 }
212
213 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214 <Self as fmt::Debug>::fmt(self, f)
215 }
216}
217
218impl<IN> Matcher<IN> for String
220where
221 IN: AsRef<[u8]> + ?Sized,
222{
223 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
224 self.as_bytes() == input.as_ref()
225 }
226
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 <Self as fmt::Debug>::fmt(self, f)
229 }
230}
231
232impl<IN> Matcher<IN> for &[u8]
234where
235 IN: AsRef<[u8]> + ?Sized,
236{
237 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
238 *self == input.as_ref()
239 }
240
241 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242 <Self as fmt::Debug>::fmt(self, f)
243 }
244}
245
246impl<IN> Matcher<IN> for Vec<u8>
248where
249 IN: AsRef<[u8]> + ?Sized,
250{
251 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
252 self.as_slice() == input.as_ref()
253 }
254
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 <Self as fmt::Debug>::fmt(self, f)
257 }
258}
259
260pub trait IntoRegex {
264 fn into_regex(self) -> regex::bytes::Regex;
266}
267impl IntoRegex for &str {
268 fn into_regex(self) -> regex::bytes::Regex {
269 regex::bytes::Regex::new(self).expect("failed to create regex")
270 }
271}
272impl IntoRegex for String {
273 fn into_regex(self) -> regex::bytes::Regex {
274 regex::bytes::Regex::new(&self).expect("failed to create regex")
275 }
276}
277impl IntoRegex for &mut regex::bytes::RegexBuilder {
278 fn into_regex(self) -> regex::bytes::Regex {
279 self.build().expect("failed to create regex")
280 }
281}
282impl IntoRegex for regex::bytes::Regex {
283 fn into_regex(self) -> regex::bytes::Regex {
284 self
285 }
286}
287
288pub fn matches(value: impl IntoRegex) -> Matches {
299 Matches(value.into_regex())
301}
302#[derive(Debug)]
304pub struct Matches(regex::bytes::Regex);
305impl<IN> Matcher<IN> for Matches
306where
307 IN: AsRef<[u8]> + ?Sized,
308{
309 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
310 self.0.is_match(input.as_ref())
311 }
312
313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314 <Self as fmt::Debug>::fmt(self, f)
315 }
316}
317
318pub fn not<M>(inner: M) -> Not<M> {
329 Not(inner)
330}
331pub struct Not<M>(M);
333impl<M, IN> Matcher<IN> for Not<M>
334where
335 M: Matcher<IN>,
336 IN: fmt::Debug + ?Sized,
337{
338 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
339 !ctx.chain(&mut self.0, input)
340 }
341
342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343 f.debug_tuple("Not").field(&matcher_name(&self.0)).finish()
344 }
345}
346
347pub fn all_of<IN>(inner: Vec<Box<dyn Matcher<IN>>>) -> AllOf<IN>
363where
364 IN: ?Sized,
365{
366 AllOf(inner)
367}
368
369pub struct AllOf<IN>(Vec<Box<dyn Matcher<IN>>>)
371where
372 IN: ?Sized;
373impl<IN> Matcher<IN> for AllOf<IN>
374where
375 IN: fmt::Debug + ?Sized,
376{
377 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
378 self.0
379 .iter_mut()
380 .all(|mapper| ctx.chain(mapper.as_mut(), input))
381 }
382
383 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
384 <Self as fmt::Debug>::fmt(self, f)
385 }
386}
387
388impl<IN> fmt::Debug for AllOf<IN>
389where
390 IN: ?Sized,
391{
392 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
393 f.write_str("AllOf")?;
394 f.debug_list()
395 .entries(self.0.iter().map(|x| matcher_name(&**x)))
396 .finish()
397 }
398}
399
400pub fn any_of<IN>(inner: Vec<Box<dyn Matcher<IN>>>) -> AnyOf<IN>
419where
420 IN: ?Sized,
421{
422 AnyOf(inner)
423}
424pub struct AnyOf<IN>(Vec<Box<dyn Matcher<IN>>>)
426where
427 IN: ?Sized;
428impl<IN> Matcher<IN> for AnyOf<IN>
429where
430 IN: fmt::Debug + ?Sized,
431{
432 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
433 self.0
434 .iter_mut()
435 .any(|mapper| ctx.chain(mapper.as_mut(), input))
436 }
437
438 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439 <Self as fmt::Debug>::fmt(self, f)
440 }
441}
442
443impl<IN> fmt::Debug for AnyOf<IN>
444where
445 IN: ?Sized,
446{
447 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448 f.write_str("AnyOf")?;
449 f.debug_list()
450 .entries(self.0.iter().map(|x| matcher_name(&**x)))
451 .finish()
452 }
453}
454
455#[derive(Debug, PartialEq, PartialOrd)]
457pub struct KV<K, V>
458where
459 Self: Sized,
460 K: ToOwned + ?Sized,
461 V: ToOwned + ?Sized,
462{
463 pub k: K::Owned,
465 pub v: V::Owned,
467}
468
469impl<K, V> KV<K, V>
470where
471 K: ToOwned + ?Sized,
472 V: ToOwned + ?Sized,
473{
474 pub fn new(k: &K, v: &V) -> Self {
476 KV {
477 k: k.to_owned(),
478 v: v.to_owned(),
479 }
480 }
481}
482
483pub fn url_decoded<M>(inner: M) -> UrlDecoded<M> {
497 UrlDecoded(inner)
498}
499#[derive(Debug)]
501pub struct UrlDecoded<M>(M);
502impl<IN, M> Matcher<IN> for UrlDecoded<M>
503where
504 IN: AsRef<[u8]> + ?Sized,
505 M: Matcher<[KV<str, str>]>,
506{
507 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
508 let decoded: Vec<KV<str, str>> = form_urlencoded::parse(input.as_ref())
509 .into_owned()
510 .map(|(k, v)| KV { k, v })
511 .collect();
512 ctx.chain(&mut self.0, &decoded)
513 }
514
515 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
516 f.debug_tuple("UrlDecoded")
517 .field(&matcher_name(&self.0))
518 .finish()
519 }
520}
521
522pub fn json_decoded<T, M>(inner: M) -> JsonDecoded<T, M>
537where
538 M: Matcher<T>,
539{
540 JsonDecoded(PhantomData, inner)
541}
542#[derive(Debug)]
544pub struct JsonDecoded<T, M>(PhantomData<T>, M);
545impl<IN, T, M> Matcher<IN> for JsonDecoded<T, M>
546where
547 IN: AsRef<[u8]> + ?Sized,
548 M: Matcher<T>,
549 T: serde::de::DeserializeOwned + fmt::Debug + Send,
550{
551 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
552 let value: T = match serde_json::from_slice(input.as_ref()) {
553 Ok(value) => value,
554 Err(_) => return false,
555 };
556 ctx.chain(&mut self.1, &value)
557 }
558
559 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
560 f.debug_tuple("JsonDecoded")
561 .field(&matcher_name(&self.1))
562 .finish()
563 }
564}
565
566pub fn lowercase<M>(inner: M) -> Lowercase<M> {
577 Lowercase(inner)
578}
579#[derive(Debug)]
581pub struct Lowercase<M>(M);
582impl<IN, M> Matcher<IN> for Lowercase<M>
583where
584 IN: AsRef<[u8]> + ?Sized,
585 M: Matcher<[u8]>,
586{
587 fn matches(&mut self, input: &IN, ctx: &mut ExecutionContext) -> bool {
588 use bstr::ByteSlice;
589 ctx.chain(&mut self.0, &input.as_ref().to_lowercase())
590 }
591
592 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593 f.debug_tuple("Lowercase")
594 .field(&matcher_name(&self.0))
595 .finish()
596 }
597}
598
599impl<IN, F> Matcher<IN> for F
601where
602 F: Fn(&IN) -> bool + Send,
603{
604 fn matches(&mut self, input: &IN, _ctx: &mut ExecutionContext) -> bool {
605 self(input)
606 }
607
608 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609 write!(f, "fn(&{}) -> bool", std::any::type_name::<IN>())
610 }
611}
612
613pub fn contains<M>(inner: M) -> Contains<M> {
637 Contains(inner)
638}
639#[derive(Debug)]
641pub struct Contains<M>(M);
642impl<M, E> Matcher<[E]> for Contains<M>
643where
644 M: Matcher<E>,
645 E: fmt::Debug,
646{
647 fn matches(&mut self, input: &[E], ctx: &mut ExecutionContext) -> bool {
648 input.iter().any(|x| ctx.chain(&mut self.0, x))
649 }
650
651 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
652 f.debug_tuple("Contains")
653 .field(&matcher_name(&self.0))
654 .finish()
655 }
656}
657
658pub fn key<M>(inner: M) -> Key<M> {
672 Key(inner)
673}
674#[derive(Debug)]
676pub struct Key<M>(M);
677impl<M, K, V> Matcher<KV<K, V>> for Key<M>
678where
679 K: ToOwned + fmt::Debug + ?Sized,
680 V: ToOwned + ?Sized,
681 M: Matcher<K>,
682{
683 fn matches(&mut self, input: &KV<K, V>, ctx: &mut ExecutionContext) -> bool {
684 ctx.chain(&mut self.0, input.k.borrow())
685 }
686
687 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
688 f.debug_tuple("Key").field(&matcher_name(&self.0)).finish()
689 }
690}
691
692pub fn value<M>(inner: M) -> Value<M> {
703 Value(inner)
704}
705#[derive(Debug)]
707pub struct Value<M>(M);
708impl<M, K, V> Matcher<KV<K, V>> for Value<M>
709where
710 K: ToOwned + ?Sized,
711 V: ToOwned + fmt::Debug + ?Sized,
712 M: Matcher<V>,
713{
714 fn matches(&mut self, input: &KV<K, V>, ctx: &mut ExecutionContext) -> bool {
715 ctx.chain(&mut self.0, input.v.borrow())
716 }
717
718 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719 f.debug_tuple("Value")
720 .field(&matcher_name(&self.0))
721 .finish()
722 }
723}
724
725impl<K, V, KMatcher, VMatcher> Matcher<KV<K, V>> for (KMatcher, VMatcher)
726where
727 K: ToOwned + fmt::Debug + ?Sized,
728 V: ToOwned + fmt::Debug + ?Sized,
729 KMatcher: Matcher<K>,
730 VMatcher: Matcher<V>,
731{
732 fn matches(&mut self, input: &KV<K, V>, ctx: &mut ExecutionContext) -> bool {
733 ctx.chain(&mut self.0, input.k.borrow()) && ctx.chain(&mut self.1, input.v.borrow())
734 }
735
736 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737 f.debug_tuple("")
738 .field(&matcher_name(&self.0))
739 .field(&matcher_name(&self.1))
740 .finish()
741 }
742}
743
744pub fn len<M>(inner: M) -> Len<M> {
761 Len(inner)
762}
763#[derive(Debug)]
765pub struct Len<M>(M);
766impl<M, T> Matcher<[T]> for Len<M>
767where
768 M: Matcher<usize>,
769{
770 fn matches(&mut self, input: &[T], ctx: &mut ExecutionContext) -> bool {
771 ctx.chain(&mut self.0, &input.len())
772 }
773
774 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
775 f.debug_tuple("Len").field(&matcher_name(&self.0)).finish()
776 }
777}
778
779impl<M> Matcher<str> for Len<M>
780where
781 M: Matcher<usize>,
782{
783 fn matches(&mut self, input: &str, ctx: &mut ExecutionContext) -> bool {
784 ctx.chain(&mut self.0, &input.len())
785 }
786
787 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
788 f.debug_tuple("Len").field(&matcher_name(&self.0)).finish()
789 }
790}
791
792impl<M> Matcher<bstr::BStr> for Len<M>
793where
794 M: Matcher<usize>,
795{
796 fn matches(&mut self, input: &bstr::BStr, ctx: &mut ExecutionContext) -> bool {
797 ctx.chain(&mut self.0, &input.len())
798 }
799
800 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
801 f.debug_tuple("Len").field(&matcher_name(&self.0)).finish()
802 }
803}
804
805#[cfg(test)]
806mod tests {
807 use super::*;
808
809 fn eval<M, I>(matcher: &mut M, input: &I) -> bool
810 where
811 M: Matcher<I> + ?Sized,
812 I: fmt::Debug + ?Sized,
813 {
814 ExecutionContext::evaluate(matcher, input)
815 }
816
817 #[test]
818 fn test_eq() {
819 let mut c = eq("foo");
820 assert_eq!(false, eval(&mut c, "foobar"));
821 assert_eq!(false, eval(&mut c, "bazfoobar"));
822 assert_eq!(false, eval(&mut c, "bar"));
823 assert_eq!(true, eval(&mut c, "foo"));
824 }
825
826 #[test]
827 fn test_matches() {
828 let mut c = matches(r#"^foo\d*bar$"#);
830 assert_eq!(true, eval(&mut c, "foobar"));
831 assert_eq!(true, eval(&mut c, "foo99bar"));
832 assert_eq!(false, eval(&mut c, "foo99barz"));
833 assert_eq!(false, eval(&mut c, "bat"));
834
835 let mut c = matches(r#"^foo\d*bar$"#.to_owned());
837 assert_eq!(true, eval(&mut c, "foobar"));
838 assert_eq!(true, eval(&mut c, "foo99bar"));
839 assert_eq!(false, eval(&mut c, "foo99barz"));
840 assert_eq!(false, eval(&mut c, "bat"));
841
842 let mut c = matches(regex::bytes::RegexBuilder::new("foobar").case_insensitive(true));
844 assert_eq!(true, eval(&mut c, "foobar"));
845 assert_eq!(true, eval(&mut c, "FOOBAR"));
846 assert_eq!(false, eval(&mut c, "FOO99BAR"));
847
848 let mut c = matches(
850 regex::bytes::RegexBuilder::new("foobar")
851 .case_insensitive(true)
852 .build()
853 .unwrap(),
854 );
855 assert_eq!(true, eval(&mut c, "foobar"));
856 assert_eq!(true, eval(&mut c, "FOOBAR"));
857 assert_eq!(false, eval(&mut c, "FOO99BAR"));
858 }
859
860 #[test]
861 fn test_not() {
862 let mut c = not(matches(r#"^foo\d*bar$"#));
863 assert_eq!(false, eval(&mut c, "foobar"));
864 assert_eq!(false, eval(&mut c, "foo99bar"));
865 assert_eq!(true, eval(&mut c, "foo99barz"));
866 assert_eq!(true, eval(&mut c, "bat"));
867 }
868
869 #[test]
870 fn test_all_of() {
871 let mut c = all_of![matches("foo"), matches("bar")];
872 assert_eq!(true, eval(&mut c, "foobar"));
873 assert_eq!(true, eval(&mut c, "barfoo"));
874 assert_eq!(false, eval(&mut c, "foo"));
875 assert_eq!(false, eval(&mut c, "bar"));
876 }
877
878 #[test]
879 fn test_any_of() {
880 let mut c = any_of![matches("foo"), matches("bar")];
881 assert_eq!(true, eval(&mut c, "foobar"));
882 assert_eq!(true, eval(&mut c, "barfoo"));
883 assert_eq!(true, eval(&mut c, "foo"));
884 assert_eq!(true, eval(&mut c, "bar"));
885 assert_eq!(false, eval(&mut c, "baz"));
886 }
887
888 #[test]
889 fn test_url_decoded() {
890 let expected = vec![KV::new("key 1", "value 1"), KV::new("key2", "")];
891 let mut c = request::query(url_decoded(eq(expected)));
892 let req = http::Request::get("https://example.com/path?key%201=value%201&key2")
893 .body("")
894 .unwrap();
895
896 assert_eq!(true, eval(&mut c, &req));
897 }
898
899 #[test]
900 fn test_json_decoded() {
901 let mut c = json_decoded(eq(serde_json::json!({
902 "foo": 1,
903 "bar": 99,
904 })));
905 assert_eq!(true, eval(&mut c, r#"{"foo": 1, "bar": 99}"#));
906 assert_eq!(true, eval(&mut c, r#"{"bar": 99, "foo": 1}"#));
907 assert_eq!(false, eval(&mut c, r#"{"foo": 1, "bar": 100}"#));
908 }
909
910 #[test]
911 fn test_lowercase() {
912 let mut c = lowercase(matches("foo"));
913 assert_eq!(true, eval(&mut c, "FOO"));
914 assert_eq!(true, eval(&mut c, "FoOBar"));
915 assert_eq!(true, eval(&mut c, "foobar"));
916 assert_eq!(false, eval(&mut c, "bar"));
917 }
918
919 #[test]
920 fn test_fn_mapper() {
921 let mut c = |input: &u64| input % 2 == 0;
922 assert_eq!(true, eval(&mut c, &6));
923 assert_eq!(true, eval(&mut c, &20));
924 assert_eq!(true, eval(&mut c, &0));
925 assert_eq!(false, eval(&mut c, &11));
926 }
927
928 #[test]
929 fn test_contains() {
930 let mut c = contains(eq(100));
931 assert_eq!(true, eval(&mut c, vec![100, 200, 300].as_slice()));
932 assert_eq!(false, eval(&mut c, vec![99, 200, 300].as_slice()));
933 }
934
935 #[test]
936 fn test_key() {
937 let kv = KV::new("key1", "value1");
938 assert_eq!(true, eval(&mut key("key1"), &kv));
939 assert_eq!(false, eval(&mut key("key2"), &kv));
940 }
941
942 #[test]
943 fn test_value() {
944 let kv = KV::new("key1", "value1");
945 assert_eq!(true, eval(&mut value("value1"), &kv));
946 assert_eq!(false, eval(&mut value("value2"), &kv));
947 }
948
949 #[test]
950 fn test_tuple() {
951 let kv = KV::new("key1", "value1");
952 assert_eq!(true, eval(&mut ("key1", any()), &kv));
953 assert_eq!(true, eval(&mut ("key1", "value1"), &kv));
954 assert_eq!(false, eval(&mut ("key1", "value2"), &kv));
955 assert_eq!(false, eval(&mut ("key2", "value1"), &kv));
956 }
957
958 #[test]
959 fn test_len() {
960 let mut c = len(eq(3));
961 assert_eq!(true, eval(&mut c, "foo"));
962 assert_eq!(false, eval(&mut c, "foobar"));
963 assert_eq!(true, eval(&mut c, &b"foo"[..]));
964 assert_eq!(false, eval(&mut c, &b"foobar"[..]));
965
966 let req = http::Request::get("/test?foo=bar").body("foobar").unwrap();
967 assert!(eval(&mut request::body(len(eq(6))), &req));
968 }
969
970 #[test]
971 fn test_fn() {
972 let mut c = len(|&len: &usize| len <= 3);
973 assert_eq!(true, eval(&mut c, "f"));
974 assert_eq!(true, eval(&mut c, "fo"));
975 assert_eq!(true, eval(&mut c, "foo"));
976 assert_eq!(false, eval(&mut c, "foob"));
977 assert_eq!(false, eval(&mut c, "fooba"));
978 assert_eq!(false, eval(&mut c, "foobar"));
979 }
980}