You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.4 KiB
88 lines
2.4 KiB
use std::fmt::Debug;
|
|
use crate::util::form::field_error::FieldError;
|
|
|
|
/**
|
|
A sum type that contains a value and possibly an error. Used for form validation.
|
|
This isn't exactly like a sum type like Result as even in the error case, we want
|
|
to keep the value intact. It can't be just an either/or situation. For instance,
|
|
when doing form validation, in most cases, we would want to preserve the value
|
|
sent to us through the form, but inform the user of why it was rejected through an
|
|
error message.
|
|
*/
|
|
|
|
pub struct FieldValue<Value, Error> {
|
|
pub value: Value,
|
|
pub error: Option<Error>,
|
|
}
|
|
|
|
pub type StringField = FieldValue<String, FieldError>;
|
|
pub type BoolField = FieldValue<bool, FieldError>;
|
|
pub type FloatField = FieldValue<f64, FieldError>;
|
|
|
|
impl<Value, Error> FieldValue<Value, Error>
|
|
where Value: Default
|
|
{
|
|
pub fn new(value: Value) -> Self {
|
|
Self { value, error: None }
|
|
}
|
|
|
|
pub fn set_error(&mut self, error: Error) {
|
|
self.error = Some(error);
|
|
}
|
|
|
|
pub fn is_error(&self) -> bool {
|
|
self.error.is_some()
|
|
}
|
|
|
|
pub fn invalid_if<I>(mut self, is_invalid: I, err: Error ) -> Self
|
|
where I: FnOnce(&Value) -> bool {
|
|
if is_invalid(&self.value) {
|
|
self.set_error(err);
|
|
}
|
|
self
|
|
}
|
|
|
|
pub fn invalid_if_then<I, E>(mut self, is_invalid: I, err_if: E ) -> Self
|
|
where I: FnOnce(&Value) -> bool, E: FnOnce() -> Error {
|
|
if is_invalid(&self.value) {
|
|
self.set_error(err_if());
|
|
}
|
|
self
|
|
}
|
|
|
|
pub fn clear_value(mut self) -> Self {
|
|
self.value = Default::default();
|
|
self
|
|
}
|
|
|
|
pub fn clear_value_if_error(mut self) -> Self {
|
|
if self.is_error() { self.clear_value() } else { self }
|
|
}
|
|
|
|
pub fn map<F, V>(self, f: F) -> FieldValue<V, Error>
|
|
where F: FnOnce(Value) -> V {
|
|
FieldValue::<V, Error> {
|
|
value: f(self.value),
|
|
error: self.error,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<Value, Error> Default for FieldValue<Value, Error>
|
|
where Value: Default,
|
|
{
|
|
fn default() -> Self {
|
|
Self::new(Value::default())
|
|
}
|
|
}
|
|
|
|
impl<Value, Error> Debug for FieldValue<Value, Error>
|
|
where Value: Debug,
|
|
Error: Debug {
|
|
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
|
fmt.debug_struct("FieldValue")
|
|
.field("value", &self.value)
|
|
.field("error", &self.error)
|
|
.finish()
|
|
}
|
|
} |