Browse Source

Matchers and value types

master
Lev 2 years ago
parent
commit
85f30a5eec
  1. 3
      agorata_contracts/src/lib.rs
  2. 1
      agorata_contracts/src/message.rs
  3. 97
      agorata_contracts/src/templates.rs

3
agorata_contracts/src/lib.rs

@ -1,6 +1,9 @@
extern crate serde; extern crate serde;
/// Message and Address types
pub mod message; pub mod message;
/// Templating variables.
pub mod templates;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

1
agorata_contracts/src/message.rs

@ -46,5 +46,4 @@ pub struct Message {
pub amount: i64, pub amount: i64,
/// Other currencies. /// Other currencies.
pub amounts: Vec<(String, i64)>, pub amounts: Vec<(String, i64)>,
} }

97
agorata_contracts/src/templates.rs

@ -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…
Cancel
Save