use tokio::sync::RwLock;
use crate::{field::*, traits::*};
use std::{cell::RefCell, error::Error, ops::Deref, rc::Rc, sync::Arc};
#[derive(Clone)]
pub struct Validator<TFieldValue: FieldValue, TFieldError: FieldError> {
pub(crate) validator: Rc<RefCell<dyn FnMut(&TFieldValue) -> Result<(), TFieldError>>>,
pub(crate) id: u8,
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> Validator<TFieldValue, TFieldError> {
pub fn new<Validator>(validator: Validator, id: u8) -> Self
where
Validator: FnMut(&TFieldValue) -> Result<(), TFieldError> + 'static,
{
Self {
validator: Rc::new(RefCell::new(validator)),
id,
}
}
pub(crate) fn validate(&self, value: &TFieldValue) -> Result<(), TFieldError> {
self.validator.borrow_mut()(value)
}
}
#[derive(Clone)]
pub struct AsyncValidator<TFieldValue: FieldValue, TFieldError: FieldError> {
pub(crate) validator: Rc<
RefCell<
dyn FnMut(
&TFieldValue,
)
-> std::pin::Pin<Box<dyn Future<Output = Result<(), TFieldError>>>>,
>,
>,
pub(crate) id: u8,
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> AsyncValidator<TFieldValue, TFieldError> {
pub fn new<Validator>(validator: Validator, id: u8) -> Self
where
Validator: FnMut(&TFieldValue) -> std::pin::Pin<Box<dyn Future<Output = Result<(), TFieldError>>>>
+ 'static,
{
Self {
validator: Rc::new(RefCell::new(validator)),
id,
}
}
pub(crate) async fn validate(&self, value: &TFieldValue) -> Result<(), TFieldError> {
(self.validator.borrow_mut())(value).await
}
}
pub type Validators<TFieldValue: FieldValue, TFieldError: FieldError> =
Vec<Validator<TFieldValue, TFieldError>>;
pub type AsyncValidators<TFieldValue: FieldValue, TFieldError: FieldError> =
Vec<AsyncValidator<TFieldValue, TFieldError>>;
#[derive(Debug, PartialEq, Clone, Default, Copy)]
pub enum ValidateOn {
Input,
Blur,
#[default]
All,
Submit,
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> PartialEq
for Validator<TFieldValue, TFieldError>
{
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id)
}
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> Eq for Validator<TFieldValue, TFieldError> {}
impl<TFieldValue: FieldValue, TFieldError: FieldError> PartialOrd
for Validator<TFieldValue, TFieldError>
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> Ord for Validator<TFieldValue, TFieldError> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> PartialEq
for AsyncValidator<TFieldValue, TFieldError>
{
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id)
}
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> Eq
for AsyncValidator<TFieldValue, TFieldError>
{
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> PartialOrd
for AsyncValidator<TFieldValue, TFieldError>
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}
impl<TFieldValue: FieldValue, TFieldError: FieldError> Ord
for AsyncValidator<TFieldValue, TFieldError>
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}