use crate::combinator::{AndThen, Map, Pipe, Recover, Refine, WithDefault};
use crate::issue::Issues;
use crate::path::Path;
use std::borrow::Cow;
pub trait Decoder<I: ?Sized> {
type Output;
fn decode_at(&self, input: &I, path: &Path<'_>) -> Result<Self::Output, Issues>;
fn decode(&self, input: &I) -> Result<Self::Output, Issues> {
self.decode_at(input, &Path::ROOT)
}
fn map<F, U>(self, f: F) -> Map<Self, F>
where
Self: Sized,
F: Fn(Self::Output) -> U,
{
Map::new(self, f)
}
fn and_then<F, U, E>(self, f: F) -> AndThen<Self, F>
where
Self: Sized,
F: Fn(Self::Output) -> Result<U, E>,
E: Into<Issues>,
{
AndThen::new(self, f)
}
fn pipe<D>(self, next: D) -> Pipe<Self, D>
where
Self: Sized,
D: Decoder<Self::Output>,
{
Pipe::new(self, next)
}
fn refine<P>(
self,
predicate: P,
code: impl Into<Cow<'static, str>>,
message: impl Into<String>,
) -> Refine<Self, P>
where
Self: Sized,
P: Fn(&Self::Output) -> bool,
{
Refine::new(self, predicate, code.into(), message.into())
}
fn with_default(self, value: Self::Output) -> WithDefault<Self, Self::Output>
where
Self: Sized,
Self::Output: Clone,
{
WithDefault::new(self, value)
}
fn recover(self, value: Self::Output) -> Recover<Self, Self::Output>
where
Self: Sized,
Self::Output: Clone,
{
Recover::new(self, value)
}
fn boxed(self) -> BoxDecoder<I, Self::Output>
where
Self: Sized + Send + Sync + 'static,
{
Box::new(self)
}
}
pub type BoxDecoder<I, O> = Box<dyn Decoder<I, Output = O> + Send + Sync>;
impl<I: ?Sized, D: Decoder<I> + ?Sized> Decoder<I> for &D {
type Output = D::Output;
fn decode_at(&self, input: &I, path: &Path<'_>) -> Result<Self::Output, Issues> {
(**self).decode_at(input, path)
}
}
impl<I: ?Sized, D: Decoder<I> + ?Sized> Decoder<I> for Box<D> {
type Output = D::Output;
fn decode_at(&self, input: &I, path: &Path<'_>) -> Result<Self::Output, Issues> {
(**self).decode_at(input, path)
}
}
impl<I: ?Sized, D: Decoder<I> + ?Sized> Decoder<I> for std::sync::Arc<D> {
type Output = D::Output;
fn decode_at(&self, input: &I, path: &Path<'_>) -> Result<Self::Output, Issues> {
(**self).decode_at(input, path)
}
}
pub fn decoder_fn<I, O, F>(f: F) -> FnDecoder<F>
where
I: ?Sized,
F: Fn(&I, &Path<'_>) -> Result<O, Issues>,
{
FnDecoder(f)
}
#[derive(Clone, Copy, Debug)]
pub struct FnDecoder<F>(F);
impl<I: ?Sized, O, F> Decoder<I> for FnDecoder<F>
where
F: Fn(&I, &Path<'_>) -> Result<O, Issues>,
{
type Output = O;
fn decode_at(&self, input: &I, path: &Path<'_>) -> Result<O, Issues> {
(self.0)(input, path)
}
}