formbeam 0.0.5

Form system for the Hornbeam template engine (derive macros)
Documentation
use async_trait::async_trait;

use crate::errors::FieldErrors;

#[async_trait]
pub trait FormValidator<F: Form, C: Send + 'static> {
    type Error: Send + 'static;

    async fn validate(&self, form: &mut F, context: &mut C) -> Result<(), Self::Error>;
}

#[async_trait]
pub trait FieldValidator<C: Send + 'static> {
    type Error: Send + 'static;

    async fn validate(
        &self,
        value: &str,
        errors: &mut FieldErrors,
        context: &mut C,
    ) -> Result<(), Self::Error>;
}

/// The type of a realised, fully validated and populated, form.
pub trait Form: Sized + 'static {
    type Partial: FormPartial<Form = Self>;
}

/// The type of a partially populated and as-yet-unvalidated form.
/// Structs for and implementations of this trait can be generated via derive macro.
#[async_trait]
pub trait FormPartial {
    type Form: Form<Partial = Self>;
    type Validation: FormValidation<Partial = Self>;
    type Error: Send + 'static;

    /// Converts the partial into a form.
    ///
    /// # Preconditions
    ///
    /// - The form should already have been validated.
    ///
    /// # Errors
    ///
    /// Only structural/type errors will be returned here, with only the name of the field
    /// to be returned.
    ///
    /// No other validation is performed here.
    fn form(&self) -> Result<Self::Form, &'static str>
    where
        Self: Sized;

    /// Runs all the validators on the form and calculates errors.
    ///
    /// Should only be called once.
    ///
    /// # Errors
    ///
    /// Returns direct errors from validators if one was thrown.
    async fn validate(&self) -> Result<Self::Validation, Self::Error>
    where
        Self: Sized;

    const INFO: &'static FormPartialInfo;

    fn validator_info(&self) -> &'static FormPartialInfo {
        Self::INFO
    }
}

/// The result of validation.
pub trait FormValidation {
    type Partial: FormPartial<Validation = Self>;

    /// Returns true if the form is valid.
    fn is_valid(&self) -> bool;
}

pub struct FormPartialInfo {
    pub form_validators: &'static [&'static str],
    pub fields: &'static [FieldInfo],
}

pub struct FieldInfo {
    pub name: &'static str,
    pub validators: &'static [FieldValidatorInfo],
}

pub enum FieldValidatorInfo {
    MinLength(u32),
    MaxLength(u32),
    MinValue(i64),
    MaxValue(i64),
    Required,
    Email,
    Regex(&'static str),
    Custom(&'static str),
}