use rkt::data::{Data, FromData, Outcome, Transform, Transformed};
use rkt::http::Status;
use rkt::request::Request;
use std::ops::Deref;
use std::ops::DerefMut;
pub struct Valid<T> {
data: T,
}
impl<T: crate::Validate> Valid<T> {
fn new(t: T) -> Self {
Self {
data: t,
}
}
pub fn into_inner(self) -> T {
self.data
}
}
impl<T: crate::Validate> Deref for Valid<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T: crate::Validate> DerefMut for Valid<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
pub enum ValidationError<T> {
FromDataError(T),
ValidationError(Vec<String>),
}
impl<'a, T> From<Vec<String>> for ValidationError<T> {
fn from(s: Vec<String>) -> Self {
Self::ValidationError(s)
}
}
impl<T> ValidationError<T> {
fn from_data_error(t: T) -> Self {
Self::FromDataError(t)
}
fn get_t(self) -> T {
match self {
Self::FromDataError(t) => t,
Self::ValidationError(_) => panic!("Called `get_t` on `ValidationError::FromDataError`"),
}
}
}
impl<'a, T: 'a> FromData<'a> for Valid<T>
where
T: FromData<'a> + crate::Validate
{
type Error = ValidationError<T::Error>;
type Owned = T::Owned;
type Borrowed = T::Borrowed;
fn transform(r: &Request, d: Data) -> Transform<Outcome<Self::Owned, Self::Error>> {
match T::transform(r, d) {
Transform::Owned(out) => Transform::Owned(out.map_failure(|(s, f)| (s, Self::Error::from_data_error(f)))),
Transform::Borrowed(out) => {
Transform::Borrowed(out.map_failure(|(s, f)| (s, Self::Error::from_data_error(f))))
}
}
}
fn from_data(r: &Request, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
let outcome = match o {
Transform::Owned(o) => {
Transform::Owned(o.map_failure(|(s, f)| (s, f.get_t())))
}
Transform::Borrowed(o) => {
Transform::Borrowed(o.map_failure(|(s, f)| (s, f.get_t())))
}
};
let mut inner = match T::from_data(r, outcome) {
Outcome::Success(s) => s,
Outcome::Failure((s, f)) => return Outcome::Failure((s, Self::Error::from_data_error(f))),
Outcome::Forward(f) => return Outcome::Forward(f),
};
if let Err(msg) = inner.validate() {
return Outcome::Failure((Status::BadRequest, msg.into()));
}
Outcome::Success(Valid::new(inner))
}
}
impl<T, U> crate::Validate for U
where
U: Deref<Target=T> + DerefMut,
T: crate::Validate,
{
fn validate(&mut self) -> Result<(), Vec<String>> {
let t: &mut T = self.deref_mut();
t.validate()
}
}