use std::{fmt::Debug, marker::PhantomData};
use bytes::{BufMut, Bytes};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::header::IsHeader;
pub struct MessageWrapper<M, H>
where
M: Serialize,
{
inner: M,
_header_type: PhantomData<H>,
}
impl<M, H> MessageWrapper<M, H>
where
M: Serialize,
H: IsHeader,
{
pub fn new(msg: M) -> Self {
Self {
inner: msg,
_header_type: PhantomData,
}
}
pub fn header(&self, options: impl bincode::Options) -> Result<impl IsHeader, bincode::Error> {
Ok(H::new(options.serialized_size(&self.inner)?))
}
#[allow(clippy::missing_errors_doc)]
pub fn serialize_self(
&self,
options: impl bincode::Options,
) -> Result<Vec<u8>, bincode::Error> {
options.serialize(&self.inner)
}
#[allow(clippy::missing_errors_doc)]
pub fn serialize(
&self,
options: impl bincode::Options + Clone,
) -> Result<Bytes, bincode::Error> {
let mut header = self.header(options.clone())?.as_bytes_mut();
let serialized_self = self.serialize_self(options)?;
header.reserve(serialized_self.len());
header.put_slice(&serialized_self);
Ok(header.freeze())
}
pub fn into_message(self) -> M {
self.inner
}
pub fn message(&self) -> &M {
&self.inner
}
pub fn message_mut(&mut self) -> &mut M {
&mut self.inner
}
pub fn from_bytes<NH, NM>(
data: &Bytes,
options: impl bincode::Options,
) -> Result<MessageWrapper<NM, NH>, bincode::Error>
where
NH: IsHeader,
NM: Serialize + DeserializeOwned,
{
Ok(MessageWrapper::new(options.deserialize(data)?))
}
pub fn from_slice<'nde, NH, NM>(
data: &'nde &[u8],
options: impl bincode::Options,
) -> Result<MessageWrapper<NM, NH>, bincode::Error>
where
NH: IsHeader,
NM: Serialize + Deserialize<'nde>,
{
Ok(MessageWrapper::new(options.deserialize(data)?))
}
}
impl<M, H> Debug for MessageWrapper<M, H>
where
M: Serialize + Debug,
H: IsHeader + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MessageWrapper")
.field("message", &self.inner)
.finish()
}
}