1use crate::{BitDecode, BitEncode, BitReader, BitWriter, ErrorKind};
37use bytes::{Buf, BytesMut};
38use core::marker::PhantomData;
39use std::io;
40use tokio_util::codec::{Decoder, Encoder};
41
42pub struct BinCodec<T>(PhantomData<T>);
45
46impl<T> BinCodec<T> {
47 #[must_use]
49 pub fn new() -> Self {
50 Self(PhantomData)
51 }
52}
53
54impl<T> Default for BinCodec<T> {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60impl<T: BitDecode + BitEncode> Decoder for BinCodec<T> {
65 type Item = T;
66 type Error = io::Error;
67
68 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<T>, io::Error> {
69 if src.is_empty() {
70 return Ok(None);
71 }
72 let mut reader = BitReader::with_layout(&src[..], <T as BitEncode>::LAYOUT);
73 match <T as BitDecode>::bit_decode(&mut reader) {
74 Ok(item) => {
75 let consumed = reader.bit_pos() / 8;
77 src.advance(consumed);
78 Ok(Some(item))
79 }
80 Err(e)
82 if matches!(
83 e.kind,
84 ErrorKind::UnexpectedEof { .. } | ErrorKind::Incomplete { .. }
85 ) =>
86 {
87 Ok(None)
88 }
89 Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e.to_string())),
91 }
92 }
93}
94
95impl<T: BitEncode> Encoder<T> for BinCodec<T> {
96 type Error = io::Error;
97
98 fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), io::Error> {
99 let mut w = BitWriter::with_layout(<T as BitEncode>::LAYOUT);
100 item.bit_encode(&mut w)
101 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?;
102 dst.extend_from_slice(&w.into_bytes());
103 Ok(())
104 }
105}
106
107#[cfg(test)]
108mod component {
109 use super::BinCodec;
112 use bnb::bin;
113 use bytes::BytesMut;
114 use tokio_util::codec::{Decoder, Encoder};
115
116 #[bin(big)]
118 #[derive(Debug, Clone, PartialEq, Eq)]
119 struct Msg {
120 a: u16,
121 b: u16,
122 }
123
124 #[bin(big, magic = 0xCAFEu16)]
126 #[derive(Debug, Clone, PartialEq, Eq)]
127 struct Magic {
128 v: u8,
129 }
130
131 #[bin(little)]
134 #[derive(Debug, Clone, PartialEq, Eq)]
135 struct LeMsg {
136 a: u16,
137 b: u32,
138 }
139
140 #[test]
141 fn little_endian_message_round_trips() {
142 let mut codec = BinCodec::<LeMsg>::new();
143 let mut buf = BytesMut::new();
144 let m = LeMsg {
145 a: 0x1234,
146 b: 0xAABB_CCDD,
147 };
148 codec.encode(m.clone(), &mut buf).unwrap();
149 assert_eq!(&buf[..], &[0x34, 0x12, 0xDD, 0xCC, 0xBB, 0xAA]);
151 assert_eq!(codec.decode(&mut buf).unwrap(), Some(m));
153 assert!(buf.is_empty());
154 }
155
156 #[test]
157 fn encoder_writes_exact_message_bytes() {
158 let mut codec = BinCodec::<Msg>::new();
159 let mut buf = BytesMut::new();
160 codec
161 .encode(
162 Msg {
163 a: 0x0102,
164 b: 0x0304,
165 },
166 &mut buf,
167 )
168 .unwrap();
169 assert_eq!(&buf[..], &[0x01, 0x02, 0x03, 0x04]);
170 }
171
172 #[test]
173 fn encode_then_decode_round_trips_and_drains() {
174 let mut codec = BinCodec::<Msg>::new();
175 let mut buf = BytesMut::new();
176 let m = Msg {
177 a: 0xAABB,
178 b: 0xCCDD,
179 };
180 codec.encode(m.clone(), &mut buf).unwrap();
181 assert_eq!(codec.decode(&mut buf).unwrap(), Some(m));
182 assert!(buf.is_empty(), "decode consumed exactly the one frame");
183 }
184
185 #[test]
186 fn decode_empty_buffer_is_none() {
187 let mut codec = BinCodec::<Msg>::new();
188 let mut buf = BytesMut::new();
189 assert_eq!(codec.decode(&mut buf).unwrap(), None);
190 }
191
192 #[test]
193 fn decode_partial_frame_is_none_and_keeps_bytes() {
194 let mut codec = BinCodec::<Msg>::new();
195 let mut buf = BytesMut::from(&[0x01, 0x02][..]); assert_eq!(codec.decode(&mut buf).unwrap(), None);
197 assert_eq!(
198 &buf[..],
199 &[0x01, 0x02],
200 "a partial frame is left for the next read"
201 );
202 }
203
204 #[test]
205 fn decode_consumes_one_message_and_leaves_the_tail() {
206 let mut codec = BinCodec::<Msg>::new();
207 let mut buf = BytesMut::from(&[0x01, 0x02, 0x03, 0x04, 0xEE, 0xFF][..]);
208 assert_eq!(
209 codec.decode(&mut buf).unwrap(),
210 Some(Msg {
211 a: 0x0102,
212 b: 0x0304
213 })
214 );
215 assert_eq!(
216 &buf[..],
217 &[0xEE, 0xFF],
218 "trailing bytes remain for the next frame"
219 );
220 }
221
222 #[test]
223 fn decode_walks_back_to_back_messages() {
224 let mut codec = BinCodec::<Msg>::new();
225 let mut buf = BytesMut::from(&[0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04][..]);
226 assert_eq!(codec.decode(&mut buf).unwrap(), Some(Msg { a: 1, b: 2 }));
227 assert_eq!(codec.decode(&mut buf).unwrap(), Some(Msg { a: 3, b: 4 }));
228 assert_eq!(codec.decode(&mut buf).unwrap(), None);
229 }
230
231 #[test]
232 fn decode_bad_magic_is_an_invalid_data_error() {
233 let mut codec = BinCodec::<Magic>::new();
234 let mut buf = BytesMut::from(&[0x00, 0x00, 0x07][..]); let err = codec.decode(&mut buf).unwrap_err();
236 assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
237 }
238
239 #[test]
240 fn default_constructs_a_codec() {
241 let _c: BinCodec<Msg> = BinCodec::default();
242 }
243}