asteroid_mq_model/codec/
bincode.rs1use std::borrow::Cow;
2
3use bytes::Bytes;
4
5use crate::{
6 EdgeError, EdgePayload, Interest, MaybeBase64Bytes, MessageDurableConfig, Subject, TopicCode,
7};
8
9use super::Codec;
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
11pub struct Bincode;
12
13pub const BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard();
14
15impl Codec for Bincode {
16 fn decode(&self, bytes: &[u8]) -> Result<EdgePayload, super::CodecError> {
17 Ok(bincode::decode_from_slice(bytes, BINCODE_CONFIG)
18 .map_err(super::CodecError::decode_error)?
19 .0)
20 }
21 fn encode(&self, value: &EdgePayload) -> Result<Vec<u8>, super::CodecError> {
22 bincode::encode_to_vec(value, BINCODE_CONFIG).map_err(super::CodecError::encode_error)
23 }
24 fn kind(&self) -> super::CodecKind {
25 super::CodecKind::BINCODE
26 }
27}
28
29impl bincode::Encode for EdgeError {
30 fn encode<W: bincode::enc::Encoder>(
31 &self,
32 writer: &mut W,
33 ) -> Result<(), bincode::error::EncodeError> {
34 self.context.encode(writer)?;
35 self.message.encode(writer)?;
36 self.kind.encode(writer)
37 }
38}
39
40impl<'de, C> bincode::BorrowDecode<'de, C> for EdgeError {
41 fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
42 decoder: &mut D,
43 ) -> Result<Self, bincode::error::DecodeError> {
44 Ok(Self {
45 context: Cow::Owned(String::borrow_decode(decoder)?),
46 message: <Option<String>>::borrow_decode(decoder)?.map(Cow::Owned),
47 kind: bincode::BorrowDecode::borrow_decode(decoder)?,
48 })
49 }
50}
51
52impl<C> bincode::Decode<C> for EdgeError {
53 fn decode<D: bincode::de::Decoder>(
54 decoder: &mut D,
55 ) -> Result<Self, bincode::error::DecodeError> {
56 Ok(Self {
57 context: bincode::Decode::decode(decoder)?,
58 message: bincode::Decode::decode(decoder)?,
59 kind: bincode::Decode::decode(decoder)?,
60 })
61 }
62}
63
64macro_rules! derive_bytes_wrapper {
65 ($T: ident) => {
66 impl bincode::Encode for $T {
67 fn encode<W: bincode::enc::Encoder>(
68 &self,
69 writer: &mut W,
70 ) -> Result<(), bincode::error::EncodeError> {
71 self.0.encode(writer)
72 }
73 }
74 impl<C> bincode::Decode<C> for $T {
75 fn decode<D: bincode::de::Decoder>(
76 decoder: &mut D,
77 ) -> Result<Self, bincode::error::DecodeError> {
78 Ok(Self(Bytes::from(<Vec<u8>>::decode(decoder)?)))
79 }
80 }
81 impl<'de, C> bincode::BorrowDecode<'de, C> for $T {
82 fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
83 decoder: &mut D,
84 ) -> Result<Self, bincode::error::DecodeError> {
85 Ok(Self(Bytes::from(<Vec<u8>>::borrow_decode(decoder)?)))
86 }
87 }
88 };
89}
90derive_bytes_wrapper!(MaybeBase64Bytes);
91derive_bytes_wrapper!(TopicCode);
92derive_bytes_wrapper!(Interest);
93derive_bytes_wrapper!(Subject);
94
95impl bincode::Encode for MessageDurableConfig {
96 fn encode<E: bincode::enc::Encoder>(
97 &self,
98 encoder: &mut E,
99 ) -> Result<(), bincode::error::EncodeError> {
100 self.expire.timestamp().encode(encoder)?;
101 self.max_receiver.encode(encoder)?;
102 Ok(())
103 }
104}
105
106impl<C> bincode::Decode<C> for MessageDurableConfig {
107 fn decode<D: bincode::de::Decoder>(
108 decoder: &mut D,
109 ) -> Result<Self, bincode::error::DecodeError> {
110 Ok(Self {
111 expire: chrono::DateTime::<chrono::Utc>::from_timestamp(i64::decode(decoder)?, 0)
112 .ok_or(bincode::error::DecodeError::Other("invalid timestamp"))?,
113 max_receiver: Option::<u32>::decode(decoder)?,
114 })
115 }
116}
117
118impl<'de, C> bincode::BorrowDecode<'de, C> for MessageDurableConfig {
119 fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
120 decoder: &mut D,
121 ) -> Result<Self, bincode::error::DecodeError> {
122 Ok(Self {
123 expire: chrono::DateTime::<chrono::Utc>::from_timestamp(
124 i64::borrow_decode(decoder)?,
125 0,
126 )
127 .ok_or(bincode::error::DecodeError::Other("invalid timestamp"))?,
128 max_receiver: Option::<u32>::borrow_decode(decoder)?,
129 })
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use bytes::Bytes;
136
137 use super::*;
138 use crate::{EdgePayload, Interest, TopicCode};
139
140 #[test]
141 fn test_bincode() {
142 let codec = Bincode;
143 let ep_online = EdgePayload::Request(crate::EdgeRequest {
144 seq_id: 1,
145 request: crate::EdgeRequestEnum::EndpointOnline(crate::EdgeEndpointOnline {
146 topic_code: TopicCode::const_new("test topic"),
147 interests: vec![Interest::new("test/interest")],
148 }),
149 });
150
151 let encoded = codec.encode(&ep_online).expect("encode failed");
152 println!("{:?}", Bytes::copy_from_slice(&encoded));
153
154 let decoded = codec.decode(&encoded).unwrap();
155 println!("{:?}", decoded);
156
157 let re_encoded = codec.encode(&decoded).expect("encode failed");
158 assert_eq!(encoded, re_encoded);
159 }
160}