pub mod elements;
pub mod from_form;
#[cfg(feature = "multipart")]
pub mod multipart;
pub mod selectable;
#[cfg(feature = "urlencoded")]
pub mod urlencoded;
pub mod validation_value;
pub trait Intermediate: Sized {
fn has_value(&self) -> bool;
}
impl<T> Intermediate for Option<T> {
fn has_value(&self) -> bool {
self.is_some()
}
}
impl<T> Intermediate for validation_value::Value<T> {
fn has_value(&self) -> bool {
!self.is_none()
}
}
impl<T> Intermediate for Vec<T> {
fn has_value(&self) -> bool {
!self.is_empty()
}
}
pub trait Descriptor: Sized {
type Value;
type Intermediate: Intermediate;
fn render(field: &FormField<Self>) -> maud::Markup;
fn parse(&self, value: &str, intermediate: &mut Self::Intermediate);
fn validate(&self, intermediate: &Self::Intermediate) -> Result<Self::Value, &'_ str>;
fn load(&self, value: Self::Value) -> Self::Intermediate;
}
#[derive(Debug, Default)]
pub struct FormField<T: Descriptor> {
pub display_name: &'static str,
pub field_name: &'static str,
pub descriptor: T,
pub intermediate: T::Intermediate,
pub required: bool,
pub error: Option<String>,
pub help_text: Option<&'static str>,
}
impl<T: Descriptor> maud::Render for FormField<T> {
fn render(&self) -> maud::Markup {
maud::html! {
div class="form-group" {
(T::render(&self))
@if let Some(help) = &self.help_text {
div class="help-text" { (help) }
}
(self.render_error())
}
}
}
}
impl<T: Descriptor> FormField<T> {
pub fn set_error(&mut self, error: String) {
self.error = Some(error);
}
fn render_error(&self) -> maud::Markup {
if let Some(ref error) = self.error {
maud::html! {
div class="error" { (error) }
}
} else {
maud::html! {}
}
}
}
#[cfg(feature = "derive")]
extern crate form_fields_macro;
#[cfg(feature = "derive")]
pub use form_fields_macro::{FromForm, Selectable};