use core::marker::PhantomData;
pub trait OutputAlg<From> {
type Output;
fn output(from: From) -> Self::Output;
}
pub trait OutputKindAlg<Interpreter: ?Sized, From> {
type Transform;
}
macro_rules! output_kinds {
($($declaration:ident => $kind:ident, $alg:ident, $selected:ident, $meaning:literal),+ $(,)?) => {
$(
#[doc = concat!("Selects the converter used for ", $meaning, " API outputs.")]
pub trait $alg {
#[doc = concat!("The ", $meaning, " converter selected for `From`.")]
type $selected<From>;
}
#[doc = concat!("Selects ", $meaning, " output semantics.")]
#[derive(Debug, Default)]
pub struct $kind;
impl<Interpreter, From> OutputKindAlg<Interpreter, From> for $kind
where
Interpreter: $alg + ?Sized,
{
type Transform = Interpreter::$selected<From>;
}
)+
};
}
with_output_kinds!(output_kinds);
pub trait StatusOutAlg {
type Status<Inner, const CODE: u16>;
}
#[derive(Debug, Default)]
pub struct StatusOut<Kind, const CODE: u16>(PhantomData<Kind>);
impl<Interpreter, From, Kind, const CODE: u16> OutputKindAlg<Interpreter, From> for StatusOut<Kind, CODE>
where
Interpreter: StatusOutAlg + ?Sized,
Kind: OutputKindAlg<Interpreter, From>,
{
type Transform = Interpreter::Status<Kind::Transform, CODE>;
}
pub trait HeaderOutAlg {
type Header<Inner, Name>;
}
#[derive(Debug, Default)]
pub struct HeaderOut<Kind, Name>(PhantomData<fn(Kind, Name)>);
impl<Interpreter, Value, Rest, Kind, Name> OutputKindAlg<Interpreter, (Value, Rest)> for HeaderOut<Kind, Name>
where
Interpreter: HeaderOutAlg + ?Sized,
Kind: OutputKindAlg<Interpreter, Rest>,
{
type Transform = Interpreter::Header<Kind::Transform, Name>;
}
pub trait ResultOutAlg {
type Result<Inner, Error>;
}
#[derive(Debug, Default)]
pub struct ResultOut<Kind>(PhantomData<Kind>);
impl<Interpreter, Kind, Value, Error> OutputKindAlg<Interpreter, Result<Value, Error>> for ResultOut<Kind>
where
Interpreter: ResultOutAlg + ?Sized,
Kind: OutputKindAlg<Interpreter, Value>,
{
type Transform = Interpreter::Result<Kind::Transform, Error>;
}