1use super::context::*;
2use super::value::*;
3use super::value_raw::*;
4use num_bigint::BigUint;
5use std::fmt;
6
7pub trait Checkable<V> {
8 fn check(&self, value: V) -> bool;
9}
10
11impl Checkable<&[u8]> for BytesValue {
12 fn check(&self, value: &[u8]) -> bool {
13 self.value.as_slice() == value
14 }
15}
16
17impl Checkable<&BigUint> for BigUintValue {
18 fn check(&self, value: &BigUint) -> bool {
19 &self.value == value
20 }
21}
22
23impl Checkable<u64> for U64Value {
24 fn check(&self, value: u64) -> bool {
25 self.value == value
26 }
27}
28
29#[derive(Debug)]
30pub enum CheckValue<T> {
31 DefaultStar,
32 Star,
33 Equal(T),
34}
35
36impl<T: InterpretableFrom<ValueSubTree>> CheckValue<T> {
37 pub fn is_star(&self) -> bool {
38 matches!(self, CheckValue::Star | CheckValue::DefaultStar)
39 }
40
41 pub fn is_default_star(&self) -> bool {
42 matches!(self, CheckValue::DefaultStar)
43 }
44}
45
46impl<T: InterpretableFrom<ValueSubTree>> Default for CheckValue<T> {
47 fn default() -> Self {
48 CheckValue::DefaultStar
49 }
50}
51
52impl<T: InterpretableFrom<ValueSubTree>> InterpretableFrom<ValueSubTree> for CheckValue<T> {
53 fn interpret_from(from: ValueSubTree, context: &InterpreterContext) -> Self {
54 if let ValueSubTree::Str(s) = &from {
55 if s.is_empty() {
56 return CheckValue::DefaultStar;
57 } else if s == "*" {
58 return CheckValue::Star;
59 }
60 }
61
62 CheckValue::Equal(T::interpret_from(from, context))
63 }
64}
65
66impl<T: fmt::Display> fmt::Display for CheckValue<T> {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 match self {
69 CheckValue::Star | CheckValue::DefaultStar => write!(f, "*"),
70 CheckValue::Equal(eq_value) => eq_value.fmt(f),
71 }
72 }
73}
74
75impl<V, T> Checkable<V> for CheckValue<T>
76where
77 T: Checkable<V>,
78{
79 fn check(&self, value: V) -> bool {
80 match self {
81 CheckValue::DefaultStar | CheckValue::Star => true,
82 CheckValue::Equal(eq) => eq.check(value),
83 }
84 }
85}
86
87impl Checkable<&[Vec<u8>]> for Vec<CheckValue<BytesValue>> {
88 fn check(&self, values: &[Vec<u8>]) -> bool {
89 if self.len() != values.len() {
90 return false;
91 }
92 for (i, cv) in self.iter().enumerate() {
93 if !cv.check(values[i].as_slice()) {
94 return false;
95 }
96 }
97 true
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn check_bytes() {
107 let bv = BytesValue {
108 value: b"abc".to_vec(),
109 original: ValueSubTree::Str("abc".to_string()),
110 };
111 assert!(bv.check(&b"abc"[..]));
112
113 let cb_eq = CheckValue::Equal(bv);
114 assert!(cb_eq.check(&b"abc"[..]));
115
116 let cb_star: CheckValue<BytesValue> = CheckValue::Star;
117 assert!(cb_star.check(&b"anything_really"[..]));
118 }
119
120 #[test]
121 fn check_u64() {
122 let u64v = U64Value {
123 value: 123,
124 original: ValueSubTree::Str("123".to_string()),
125 };
126 assert!(u64v.check(123u64));
127
128 let cb_eq = CheckValue::Equal(u64v);
129 assert!(cb_eq.check(123u64));
130
131 let cb_star: CheckValue<U64Value> = CheckValue::Star;
132 assert!(cb_star.check(1234567890));
133 }
134}