use std::fmt::Debug;
use crate::Error;
pub fn infallible<A, B, F>(f: F) -> impl Fn(&A) -> Result<B, std::convert::Infallible> + Send + Sync + 'static
where
F: Fn(&A) -> B + Send + Sync + 'static,
{
move |a| Ok(f(a))
}
pub fn infallible_owned<A, B, F>(f: F) -> impl Fn(A) -> Result<B, std::convert::Infallible> + Send + Sync + 'static
where
F: Fn(A) -> B + Send + Sync + 'static,
{
move |a| Ok(f(a))
}
pub trait Encoder<From, To>: Send + Sync {
fn encode(&self, value: &From) -> Result<To, Error>;
}
#[derive(Debug)]
pub enum DecodeOutcome<T> {
Value(T),
SoftFailure(&'static str),
}
pub trait Codec<A, B>: Encoder<A, B> {
fn decode(&self, value: B) -> Result<DecodeOutcome<A>, Error>;
}
type EncodeFn<A, B> = Box<dyn Fn(&A) -> Result<B, Error> + Send + Sync>;
type DecodeFn<A, B> = Box<dyn Fn(A) -> Result<DecodeOutcome<B>, Error> + Send + Sync>;
pub struct TransformEncoder<A, B> {
encode_fn: EncodeFn<A, B>,
}
impl<A, B> TransformEncoder<A, B> {
pub fn new<EncodeError>(encode_fn: impl Fn(&A) -> Result<B, EncodeError> + Send + Sync + 'static) -> Self
where
EncodeError: std::error::Error + Send + Sync + 'static,
{
Self {
encode_fn: Box::new(move |a| encode_fn(a).map_err(Error::from_source)),
}
}
pub fn infallible(encode_fn: impl Fn(&A) -> B + Send + Sync + 'static) -> Self {
Self {
encode_fn: Box::new(move |a| Ok(encode_fn(a))),
}
}
}
impl<A, B> Encoder<A, B> for TransformEncoder<A, B> {
fn encode(&self, value: &A) -> Result<B, Error> {
(self.encode_fn)(value)
}
}
impl<A, B> Debug for TransformEncoder<A, B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TransformEncoder")
.field("A", &std::any::type_name::<A>())
.field("B", &std::any::type_name::<B>())
.finish()
}
}
pub struct TransformCodec<A, B> {
encode_fn: EncodeFn<A, B>,
decode_fn: DecodeFn<B, A>,
}
impl<A, B> TransformCodec<A, B> {
pub fn new<EncodeError, DecodeError>(
encode_fn: impl Fn(&A) -> Result<B, EncodeError> + Send + Sync + 'static,
decode_fn: impl Fn(B) -> Result<A, DecodeError> + Send + Sync + 'static,
) -> Self
where
EncodeError: std::error::Error + Send + Sync + 'static,
DecodeError: std::error::Error + Send + Sync + 'static,
{
Self {
encode_fn: Box::new(move |a| encode_fn(a).map_err(|e| Error::from_source(e))),
decode_fn: Box::new(move |b| decode_fn(b).map(DecodeOutcome::Value).map_err(|e| Error::from_source(e))),
}
}
}
impl<A, B> Encoder<A, B> for TransformCodec<A, B> {
fn encode(&self, value: &A) -> Result<B, Error> {
(self.encode_fn)(value)
}
}
impl<A, B> Codec<A, B> for TransformCodec<A, B> {
fn decode(&self, value: B) -> Result<DecodeOutcome<A>, Error> {
(self.decode_fn)(value)
}
}
impl<A, B> Debug for TransformCodec<A, B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TransformCodec")
.field("A", &std::any::type_name::<A>())
.field("B", &std::any::type_name::<B>())
.finish()
}
}