use crate::util::unwrap_some;
use crate::{MimeTypeWithCharset, TiiResult};
use std::any::Any;
use std::fmt::{Debug, Formatter};
pub trait EntitySerializer<T: Any + Debug + 'static>: Any + Send {
fn serialize(&self, mime: &MimeTypeWithCharset, data: T) -> TiiResult<Vec<u8>>;
}
impl<F, T> EntitySerializer<T> for F
where
T: Any + Debug + Send + 'static,
F: Fn(&MimeTypeWithCharset, T) -> TiiResult<Vec<u8>> + Send + 'static,
{
fn serialize(&self, mime: &MimeTypeWithCharset, data: T) -> TiiResult<Vec<u8>> {
self(mime, data)
}
}
trait DynResponseEntityInner: Debug + Send {
fn serialize(&mut self, mime: &MimeTypeWithCharset) -> TiiResult<Vec<u8>>;
fn get_serializer(&self) -> &dyn Any;
fn get_serializer_mut(&mut self) -> &mut dyn Any;
fn get_entity(&self) -> &dyn Any;
fn get_entity_mut(&mut self) -> &mut dyn Any;
fn take_inner(&mut self) -> (Box<dyn Any>, Box<dyn Any>);
}
struct ResponseEntityInner<T: Any + Debug + Send + 'static> {
entity: Option<T>,
serializer: Option<Box<dyn EntitySerializer<T>>>,
}
impl<T: Any + Debug + Send + 'static> Debug for ResponseEntityInner<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.entity, f)
}
}
impl<T: Any + Debug + Send + 'static> DynResponseEntityInner for ResponseEntityInner<T> {
fn serialize(&mut self, mime: &MimeTypeWithCharset) -> TiiResult<Vec<u8>> {
unwrap_some(self.serializer.as_ref()).serialize(mime, unwrap_some(self.entity.take()))
}
fn get_serializer(&self) -> &dyn Any {
unwrap_some(self.serializer.as_ref()) as &dyn Any
}
fn get_serializer_mut(&mut self) -> &mut dyn Any {
unwrap_some(self.serializer.as_mut()) as &mut dyn Any
}
fn get_entity(&self) -> &dyn Any {
unwrap_some(self.entity.as_ref()) as &dyn Any
}
fn get_entity_mut(&mut self) -> &mut dyn Any {
unwrap_some(self.entity.as_mut()) as &mut dyn Any
}
fn take_inner(&mut self) -> (Box<dyn Any>, Box<dyn Any>) {
(
Box::new(unwrap_some(self.entity.take())) as Box<dyn Any>,
unwrap_some(self.serializer.take()) as Box<dyn Any>,
)
}
}
#[derive(Debug)]
#[repr(transparent)]
pub(crate) struct ResponseEntity(Box<dyn DynResponseEntityInner>);
impl ResponseEntity {
pub fn new<T: Any + Send + Debug + 'static>(
entity: T,
serializer: impl EntitySerializer<T> + 'static,
) -> Self {
Self(Box::new(ResponseEntityInner {
entity: Some(entity),
serializer: Some(Box::new(serializer) as Box<dyn EntitySerializer<T>>),
}) as Box<dyn DynResponseEntityInner>)
}
pub fn serialize(mut self, mime: &MimeTypeWithCharset) -> TiiResult<Vec<u8>> {
self.0.serialize(mime)
}
pub fn into_inner(mut self) -> (Box<dyn Any>, Box<dyn Any>) {
self.0.take_inner()
}
pub fn get_serializer(&self) -> &dyn Any {
self.0.get_serializer()
}
pub fn get_serializer_mut(&mut self) -> &mut dyn Any {
self.0.get_serializer_mut()
}
pub fn get_entity(&self) -> &dyn Any {
self.0.get_entity()
}
pub fn get_entity_mut(&mut self) -> &mut dyn Any {
self.0.get_entity_mut()
}
}