denali/
value_check.rs

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}