use std::marker::PhantomData;
use serde::de::DeserializeOwned;
use crate::codec::{Codec, CodecError};
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a handler input kind",
note = "the `#[subscriber]` macro selects `Decoded<T>` for a typed `&T` parameter and `RawBytes` for a raw `&[u8]` one"
)]
pub trait InputKind: Send + Sync + 'static {
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 raw `&[u8]` input decodes with any codec"
)]
pub trait DecodeWith<DecodeCodec>: InputKind {
fn decode(codec: &DecodeCodec, payload: &[u8]) -> 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>
{
fn decode(codec: &DecodeCodec, payload: &[u8]) -> Result<T, CodecError> {
codec.decode(payload)
}
}
#[derive(Debug, Clone, Copy)]
pub struct RawBytes;
impl InputKind for RawBytes {
type Owned = ();
type Target = [u8];
fn view<'a>(_owned: &'a (), payload: &'a [u8]) -> &'a [u8] {
payload
}
fn input_label() -> &'static str {
"bytes"
}
}
impl<DecodeCodec> DecodeWith<DecodeCodec> for RawBytes {
fn decode(_codec: &DecodeCodec, _payload: &[u8]) -> Result<(), CodecError> {
Ok(())
}
}