Lev
2 years ago
3 changed files with 100 additions and 1 deletions
@ -0,0 +1,97 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use crate::message::Address; |
||||
|
||||
/// Values used for variables in templates.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
||||
pub enum Value { |
||||
Int(i64), |
||||
Bool(bool), |
||||
Address(Address), |
||||
Token(Address), |
||||
Data(Vec<u8>), |
||||
String(String), |
||||
} |
||||
|
||||
/// Types for variable values.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] |
||||
pub enum Type { |
||||
Int, |
||||
Bool, |
||||
Address, |
||||
Token, |
||||
Data, |
||||
String, |
||||
} |
||||
|
||||
impl Value { |
||||
/// Returns the type of the value.
|
||||
pub fn var_type(&self) -> Type { |
||||
match self { |
||||
Value::Int(_) => Type::Int, |
||||
Value::Bool(_) => Type::Bool, |
||||
Value::Address(_) => Type::Address, |
||||
Value::Token(_) => Type::Token, |
||||
Value::Data(_) => Type::Data, |
||||
Value::String(_) => Type::String, |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Matchers of values
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
||||
pub enum Matcher { |
||||
Any, |
||||
Fixed(Value), |
||||
NotEqual(Value), |
||||
Whitelist(Vec<Value>), |
||||
Blacklist(Vec<Value>), |
||||
IntRange(i64, i64), |
||||
Regexp(String), |
||||
} |
||||
|
||||
impl Matcher { |
||||
/// Check if this is a valid matcher for a given type.
|
||||
pub fn check_correctness_for_type(&self, type_: Type) -> bool { |
||||
match self { |
||||
Matcher::Any => true, |
||||
Matcher::Fixed(v) => v.var_type() == type_, |
||||
Matcher::NotEqual(v) => v.var_type() == type_, |
||||
Matcher::Whitelist(v) | Matcher::Blacklist(v) => { |
||||
if v.is_empty() { |
||||
return false; |
||||
} |
||||
// Check that all values are of the same type and that there are no duplicates.
|
||||
if v.iter().any(|v| v.var_type() != type_) { |
||||
return false; |
||||
} |
||||
let mut v_clone = v.clone(); |
||||
v_clone.dedup(); |
||||
v_clone.len() == v.len() |
||||
}, |
||||
Matcher::IntRange(i1, i2) => i1 <= i2 && type_ == Type::Int, |
||||
Matcher::Regexp(_) => type_ == Type::String, |
||||
} |
||||
} |
||||
|
||||
/// Match a value
|
||||
pub fn match_value(&self, value: &Value) -> bool { |
||||
if !self.check_correctness_for_type(value.var_type()) { |
||||
return false; |
||||
} |
||||
match self { |
||||
Matcher::Any => true, |
||||
Matcher::Fixed(v) => v == value, |
||||
Matcher::NotEqual(v) => v != value, |
||||
Matcher::Whitelist(v) => v.contains(value), |
||||
Matcher::Blacklist(v) => !v.contains(value), |
||||
Matcher::IntRange(i1, i2) => match value { |
||||
Value::Int(i) => i >= i1 && i <= i2, |
||||
_ => false, |
||||
}, |
||||
Matcher::Regexp(_regexp) => match value { |
||||
Value::String(_s) => todo!(), |
||||
_ => false, |
||||
}, |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue