use erased_serde::{Deserializer, Serializer};
use http::HeaderValue;
use mediatype::MediaType;
use sealed::sealed;
use std::fmt::{self, Debug, Formatter};
use super::{Format, MatchSpecificity, OwnedDeserializer, OwnedSerializer as _};
#[sealed]
pub trait ErasedFormat: Send + Sync {
fn supported_media_types(&self) -> &'static [MediaType<'static>] {
&[]
}
fn primary_media_type(&self) -> MediaType<'static>;
fn content_type_header(&self) -> HeaderValue;
fn match_specificity(&self, requested: &MediaType<'_>) -> Option<MatchSpecificity>;
fn serialize(
&self,
bytes: &mut Vec<u8>,
body: &mut dyn FnMut(&mut dyn Serializer) -> erased_serde::Result<()>,
) -> erased_serde::Result<()>;
fn deserialize(
&self,
bytes: &[u8],
body: &mut dyn FnMut(&mut dyn Deserializer<'_>) -> erased_serde::Result<()>,
) -> erased_serde::Result<()>;
}
#[sealed]
impl<F> ErasedFormat for F
where
F: Format + Send + Sync,
{
fn supported_media_types(&self) -> &'static [MediaType<'static>] {
<F as Format>::media_types(self)
}
fn primary_media_type(&self) -> MediaType<'static> {
self.supported_media_types()
.first()
.cloned()
.unwrap_or(mediatype::media_type!(APPLICATION / OCTET_STREAM))
}
fn content_type_header(&self) -> HeaderValue {
<F as Format>::content_type_header(self)
}
fn match_specificity(&self, requested: &MediaType<'_>) -> Option<MatchSpecificity> {
super::match_specificity(self, requested)
}
fn serialize(
&self,
bytes: &mut Vec<u8>,
body: &mut dyn FnMut(&mut dyn Serializer) -> erased_serde::Result<()>,
) -> erased_serde::Result<()> {
let serializer = <F as Format>::serializer(self, bytes)?;
serializer.with_erased(body)
}
fn deserialize(
&self,
bytes: &[u8],
body: &mut dyn FnMut(&mut dyn Deserializer<'_>) -> erased_serde::Result<()>,
) -> erased_serde::Result<()> {
let deserializer = <F as Format>::deserializer(self, bytes)?;
let mut erased = <dyn Deserializer<'_>>::erase(deserializer.into_deserializer());
body(&mut erased)
}
}
impl Debug for dyn ErasedFormat {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "ErasedFormat({})", self.primary_media_type())
}
}