use std::marker::PhantomData;
use serde::de::DeserializeOwned;
use crate::IncomingMessage;
use crate::codec::{Codec, CodecError};
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a handler input kind",
note = "the input type selects its kind: `Decoded<T>` for a `serde` type, `Provided<F>` for \
a `Deserialized` one"
)]
pub trait InputKind: Send + Sync + 'static {
const DESERIALIZED: bool = false;
type Owned: Send + Sync;
type Target: ?Sized + Sync;
fn view<'a>(owned: &'a Self::Owned, payload: &'a [u8]) -> &'a Self::Target;
fn input_label() -> &'static str;
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be decoded with the codec `{DecodeCodec}`",
note = "a typed input needs `serde::de::DeserializeOwned`; a `Deserialized` input decodes \
with any codec (it never calls one)"
)]
pub trait DecodeWith<DecodeCodec>: InputKind {
const CONTENT_TYPE: Option<&'static str> = None;
fn decode<M: IncomingMessage>(codec: &DecodeCodec, msg: &M) -> Result<Self::Owned, CodecError>;
}
pub struct Decoded<T>(PhantomData<T>);
impl<T> std::fmt::Debug for Decoded<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Decoded").finish_non_exhaustive()
}
}
impl<T: Send + Sync + 'static> InputKind for Decoded<T> {
type Owned = T;
type Target = T;
fn view<'a>(owned: &'a T, _payload: &'a [u8]) -> &'a T {
owned
}
fn input_label() -> &'static str {
std::any::type_name::<T>()
}
}
impl<DecodeCodec: Codec, T: DeserializeOwned + Send + Sync + 'static> DecodeWith<DecodeCodec>
for Decoded<T>
{
const CONTENT_TYPE: Option<&'static str> = Some(DecodeCodec::CONTENT_TYPE);
fn decode<M: IncomingMessage>(codec: &DecodeCodec, msg: &M) -> Result<T, CodecError> {
codec.decode(msg.payload())
}
}
pub struct Provided<F>(PhantomData<F>);
impl<F> std::fmt::Debug for Provided<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Provided").finish_non_exhaustive()
}
}
impl<F: Send + Sync + 'static> InputKind for Provided<F> {
const DESERIALIZED: bool = true;
type Owned = ();
type Target = [u8];
fn view<'a>(_owned: &'a (), payload: &'a [u8]) -> &'a [u8] {
payload
}
fn input_label() -> &'static str {
std::any::type_name::<F>()
}
}
impl<DecodeCodec, F: Send + Sync + 'static> DecodeWith<DecodeCodec> for Provided<F> {
fn decode<M: IncomingMessage>(_codec: &DecodeCodec, _msg: &M) -> Result<(), CodecError> {
Ok(())
}
}
pub struct DecodedPair<H, P>(PhantomData<(H, P)>);
impl<H, P> std::fmt::Debug for DecodedPair<H, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DecodedPair").finish_non_exhaustive()
}
}
impl<H, P> InputKind for DecodedPair<H, P>
where
H: Send + Sync + 'static,
P: Send + Sync + 'static,
{
type Owned = crate::runtime::Message<H, P>;
type Target = crate::runtime::Message<H, P>;
fn view<'a>(owned: &'a Self::Owned, _payload: &'a [u8]) -> &'a Self::Target {
owned
}
fn input_label() -> &'static str {
std::any::type_name::<P>()
}
}
impl<DecodeCodec: Codec, H, P> DecodeWith<DecodeCodec> for DecodedPair<H, P>
where
H: DeserializeOwned + Send + Sync + 'static,
P: DeserializeOwned + Send + Sync + 'static,
{
const CONTENT_TYPE: Option<&'static str> = Some(DecodeCodec::CONTENT_TYPE);
fn decode<M: IncomingMessage>(codec: &DecodeCodec, msg: &M) -> Result<Self::Owned, CodecError> {
let contract: H = msg
.headers()
.to_typed()
.map_err(|err| CodecError::Decode(Box::from(err.to_string())))?;
let body: P = codec.decode(msg.payload())?;
Ok(crate::runtime::Message::new(contract, body))
}
}