use std::fmt::{self,Display,Formatter};
#[cfg(test)] mod tst;
use super::ArgsError;
pub trait Validation {
type T;
fn error(&self, value: &Self::T) -> ArgsError;
fn is_valid(&self, value: &Self::T) -> bool;
fn is_invalid(&self, value: &Self::T) -> bool { !self.is_valid(value) }
}
pub enum Order {
GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqual
}
impl Order {
pub fn compare<T: PartialOrd>(&self, bound: &T, value: &T) -> bool {
match *self {
Order::GreaterThan => { value > bound },
Order::GreaterThanOrEqual => { value >= bound },
Order::LessThan => { value < bound },
Order::LessThanOrEqual => { value <= bound }
}
}
}
impl Display for Order {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let display = match *self {
Order::GreaterThan => { "greater than" },
Order::GreaterThanOrEqual => { "greater than or equal to" },
Order::LessThan => { "less than" },
Order::LessThanOrEqual => { "less than or equal to" }
};
write!(f, "{}", display)
}
}
pub struct OrderValidation<O: Clone + Display + PartialOrd> {
bound: O,
order: Order
}
impl<O: Clone + Display + PartialOrd> OrderValidation<O> {
pub fn new(order: Order, bound: O) -> OrderValidation<O> {
OrderValidation { bound: bound.clone(), order: order }
}
}
impl<O: Clone + Display + PartialOrd> Validation for OrderValidation<O> {
type T = O;
fn error(&self, value: &O) -> ArgsError {
ArgsError::new("order invalid", &format!("{} is not {} {}", value, self.order, self.bound))
}
fn is_valid(&self, value: &O) -> bool {
self.order.compare(&self.bound, value)
}
}