use std::sync::{Arc, Mutex};
use wireframe::{
app::Envelope,
frame::FrameMetadata,
message::{DecodeWith, DeserializeContext, EncodeWith},
serializer::{BincodeSerializer, MessageCompatibilitySerializer, Serializer},
};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct CapturedDeserializeContext {
pub message_id: Option<u32>,
pub correlation_id: Option<u64>,
pub metadata_bytes_consumed: Option<usize>,
pub frame_metadata_len: Option<usize>,
}
impl CapturedDeserializeContext {
#[must_use]
pub fn from_context(context: &DeserializeContext<'_>) -> Self {
Self {
message_id: context.message_id,
correlation_id: context.correlation_id,
metadata_bytes_consumed: context.metadata_bytes_consumed,
frame_metadata_len: context.frame_metadata.map(<[u8]>::len),
}
}
}
#[derive(Default)]
pub struct ContextCapturingSerializer {
captured: Arc<Mutex<Option<CapturedDeserializeContext>>>,
}
impl ContextCapturingSerializer {
#[must_use]
pub fn new(captured: Arc<Mutex<Option<CapturedDeserializeContext>>>) -> Self {
Self { captured }
}
}
impl MessageCompatibilitySerializer for ContextCapturingSerializer {}
impl Serializer for ContextCapturingSerializer {
fn serialize<M>(&self, value: &M) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>>
where
M: EncodeWith<Self>,
{
value.encode_with(self)
}
fn deserialize<M>(
&self,
bytes: &[u8],
) -> Result<(M, usize), Box<dyn std::error::Error + Send + Sync>>
where
M: DecodeWith<Self>,
{
M::decode_with(self, bytes, &DeserializeContext::empty())
}
fn deserialize_with_context<M>(
&self,
bytes: &[u8],
context: &DeserializeContext<'_>,
) -> Result<(M, usize), Box<dyn std::error::Error + Send + Sync>>
where
M: DecodeWith<Self>,
{
let mut state = self.captured.lock().map_err(|_| {
"ContextCapturingSerializer::deserialize_with_context captured mutex poisoned"
})?;
*state = Some(CapturedDeserializeContext::from_context(context));
M::decode_with(self, bytes, context)
}
}
impl FrameMetadata for ContextCapturingSerializer {
type Frame = Envelope;
type Error = bincode::error::DecodeError;
fn parse(&self, src: &[u8]) -> Result<(Self::Frame, usize), Self::Error> {
BincodeSerializer.parse(src)
}
}