use super::node::*;
use std::cell::RefCell;
use std::clone::Clone;
use std::fmt::Debug;
#[derive(Debug)]
pub struct Error {
pub label: String,
pub msg: Vec<String>,
pub tree: String,
}
pub type Result<T> = std::result::Result<Cherry<T>, Error>;
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
(self.label == other.label) && (self.msg == other.msg)
}
}
pub struct ValidateChain<T: Clone + Debug> {
pub cherry: Cherry<T>,
pub errors: RefCell<Vec<String>>,
}
impl<T: Clone + Debug> ValidateChain<T> {
pub fn into_result(self) -> Result<T> {
if self.errors.borrow().is_empty() {
Ok(self.cherry.to_owned())
} else {
Err(Error {
label: self.cherry.name().to_owned(),
msg: self.errors.into_inner(),
tree: self.cherry.to_json(),
})
}
}
}
pub trait Validate<T: Clone + Debug> {
fn validate<IntoString, Predicate>(
self,
msg: IntoString,
predicate: Predicate,
) -> ValidateChain<T>
where
IntoString: Into<String>,
Predicate: FnOnce(&T) -> bool;
}
impl<T: Clone + Debug> Validate<T> for Cherry<T> {
fn validate<IntoString, Predicate>(
self,
msg: IntoString,
predicate: Predicate,
) -> ValidateChain<T>
where
IntoString: Into<String>,
Predicate: FnOnce(&T) -> bool,
{
if predicate(&self.quantity()) {
ValidateChain {
cherry: self,
errors: RefCell::new(vec![]),
}
} else {
ValidateChain {
cherry: self,
errors: RefCell::new(vec![msg.into()]),
}
}
}
}
impl<T: Clone + Debug> Validate<T> for ValidateChain<T> {
fn validate<IntoString, Predicate>(
self,
msg: IntoString,
predicate: Predicate,
) -> ValidateChain<T>
where
IntoString: Into<String>,
Predicate: FnOnce(&T) -> bool,
{
if predicate(&self.cherry.quantity()) {
self
} else {
self.errors.borrow_mut().push(msg.into());
self
}
}
}