1use std::io;
4
5use compio_buf::{IoBuf, IoBufExt, IoBufMut, IoBufMutExt, SetLenExt, Slice};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Frame {
10 prefix: usize,
12
13 payload: usize,
15
16 suffix: usize,
18}
19
20impl Frame {
21 pub fn new(prefix: usize, payload: usize, suffix: usize) -> Self {
24 Self {
25 prefix,
26 payload,
27 suffix,
28 }
29 }
30
31 pub fn len(&self) -> usize {
33 self.prefix + self.payload + self.suffix
34 }
35
36 pub fn is_empty(&self) -> bool {
38 self.len() == 0
39 }
40
41 pub fn slice<B: IoBuf>(&self, buf: B) -> Slice<B> {
43 buf.slice(self.prefix..self.prefix + self.payload)
44 }
45}
46
47pub trait Framer<B: IoBufMut> {
49 fn enclose(&mut self, buf: &mut B);
58
59 fn extract(&mut self, buf: &Slice<B>) -> io::Result<Option<Frame>>;
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
72pub struct LengthDelimited {
73 length_field_len: usize,
74 length_field_is_big_endian: bool,
75}
76
77impl Default for LengthDelimited {
78 fn default() -> Self {
79 Self {
80 length_field_len: 4,
81 length_field_is_big_endian: true,
82 }
83 }
84}
85
86impl LengthDelimited {
87 const MAX_LFL: usize = 8;
89
90 pub fn new() -> Self {
92 Self::default()
93 }
94
95 pub fn length_field_len(&self) -> usize {
97 self.length_field_len
98 }
99
100 pub fn set_length_field_len(mut self, len_field_len: usize) -> Self {
107 assert!(
108 len_field_len <= Self::MAX_LFL,
109 "Length field cannot take over 8 bytes"
110 );
111 self.length_field_len = len_field_len;
112 self
113 }
114
115 pub fn length_field_is_big_endian(&self) -> bool {
117 self.length_field_is_big_endian
118 }
119
120 pub fn set_length_field_is_big_endian(mut self, big_endian: bool) -> Self {
122 self.length_field_is_big_endian = big_endian;
123 self
124 }
125}
126
127impl<B: IoBufMut> Framer<B> for LengthDelimited {
128 fn enclose(&mut self, buf: &mut B) {
129 let len = (*buf).buf_len();
130 let lfl = self.length_field_len;
131
132 buf.reserve(lfl).expect("Reserve failed");
133 unsafe { buf.copy_within(0..len, lfl) }; let len_u64 = len as u64;
138 let len_bytes = if self.length_field_is_big_endian {
139 &len_u64.to_be_bytes()[Self::MAX_LFL - lfl..]
140 } else {
141 &len_u64.to_le_bytes()[..lfl]
142 };
143 (unsafe { buf.as_uninit() })[..lfl].write_copy_of_slice(len_bytes);
145
146 unsafe { buf.advance_to(len + lfl) };
148 }
149
150 fn extract(&mut self, buf: &Slice<B>) -> io::Result<Option<Frame>> {
151 if buf.len() < self.length_field_len {
152 return Ok(None);
153 }
154
155 let buf = buf.as_init();
156 let lfl = self.length_field_len;
157 let mut len_bytes = [0; Self::MAX_LFL];
158
159 let len = if self.length_field_is_big_endian {
160 len_bytes[Self::MAX_LFL - lfl..].copy_from_slice(&buf[..lfl]);
161 u64::from_be_bytes(len_bytes)
162 } else {
163 len_bytes[..lfl].copy_from_slice(&buf[..lfl]);
164 u64::from_le_bytes(len_bytes)
165 } as usize;
166
167 if buf.len() < self.length_field_len + len {
168 return Ok(None);
169 }
170
171 Ok(Some(Frame::new(self.length_field_len, len, 0)))
172 }
173}
174
175#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
180pub struct CharDelimited<const C: char> {
181 char_buf: [u8; 4],
182}
183
184impl<const C: char> CharDelimited<C> {
185 pub fn new() -> Self {
187 Self { char_buf: [0; 4] }
188 }
189
190 fn as_any_delimited(&mut self) -> AnyDelimited<'_> {
191 let bytes = C.encode_utf8(&mut self.char_buf).as_bytes();
192
193 AnyDelimited::new(bytes)
194 }
195}
196
197impl<B: IoBufMut, const C: char> Framer<B> for CharDelimited<C> {
198 fn enclose(&mut self, buf: &mut B) {
199 self.as_any_delimited().enclose(buf);
200 }
201
202 fn extract(&mut self, buf: &Slice<B>) -> io::Result<Option<Frame>> {
203 self.as_any_delimited().extract(buf)
204 }
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
209pub struct AnyDelimited<'a> {
210 bytes: &'a [u8],
211}
212
213impl<'a> AnyDelimited<'a> {
214 pub fn new(bytes: &'a [u8]) -> Self {
216 Self { bytes }
217 }
218}
219
220impl<B: IoBufMut> Framer<B> for AnyDelimited<'_> {
221 fn extract(&mut self, buf: &Slice<B>) -> io::Result<Option<Frame>> {
222 if buf.is_empty() {
223 return Ok(None);
224 }
225
226 if let Some(pos) = buf
229 .windows(self.bytes.len())
230 .position(|window| window == self.bytes)
231 {
232 Ok(Some(Frame::new(0, pos, self.bytes.len())))
233 } else {
234 Ok(None)
235 }
236 }
237
238 fn enclose(&mut self, buf: &mut B) {
239 buf.extend_from_slice(self.bytes)
240 .expect("Failed to append delimiter");
241 }
242}
243
244pub type LineDelimited = CharDelimited<'\n'>;
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
251pub struct NoopFramer {
252 max_size: usize,
253}
254
255impl Default for NoopFramer {
256 fn default() -> Self {
257 Self { max_size: 4096 }
258 }
259}
260
261impl NoopFramer {
262 pub fn new() -> Self {
264 Self::default()
265 }
266
267 pub fn max_size(&self) -> usize {
269 self.max_size
270 }
271}
272
273impl<B: IoBufMut> Framer<B> for NoopFramer {
274 fn enclose(&mut self, _: &mut B) {}
275
276 fn extract(&mut self, buf: &Slice<B>) -> io::Result<Option<Frame>> {
277 if buf.is_empty() {
278 return Ok(None);
279 }
280
281 let len = if buf.len() < self.max_size {
282 buf.len()
283 } else {
284 self.max_size
285 };
286
287 Ok(Some(Frame::new(0, len, 0)))
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use compio_buf::IntoInner;
294
295 use super::*;
296
297 #[test]
298 fn test_length_delimited() {
299 let mut framer = LengthDelimited::new();
300
301 let mut buf = Vec::from(b"hello");
302 framer.enclose(&mut buf);
303 assert_eq!(&buf.as_slice()[..9], b"\x00\x00\x00\x05hello");
304
305 let buf = buf.slice(..);
306 let frame = framer.extract(&buf).unwrap().unwrap();
307 let buf = buf.into_inner();
308 assert_eq!(frame, Frame::new(4, 5, 0));
309 let payload = frame.slice(buf);
310 assert_eq!(payload.as_init(), b"hello");
311 }
312
313 #[test]
314 fn test_noop_framer() {
315 let mut framer = NoopFramer::new();
316
317 let mut buf = Vec::from(b"hello");
318 framer.enclose(&mut buf);
319 assert_eq!(&buf.as_slice()[..5], b"hello");
320
321 let buf = buf.slice(..);
322 let frame = framer.extract(&buf).unwrap().unwrap();
323 let buf = buf.into_inner();
324 assert_eq!(frame, Frame::new(0, 5, 0));
325 let payload = frame.slice(buf);
326 assert_eq!(payload.as_init(), b"hello");
327 }
328
329 #[test]
330 fn test_char_delimited() {
331 let mut framer = CharDelimited::<'ℝ'>::new();
332
333 let mut buf = Vec::new();
334 IoBufMutExt::extend_from_slice(&mut buf, b"hello").unwrap();
335 framer.enclose(&mut buf);
336 assert_eq!(buf.as_slice(), "helloℝ".as_init());
337
338 let buf = buf.slice(..);
339 let frame = framer.extract(&buf).unwrap().unwrap();
340 assert_eq!(frame, Frame::new(0, 5, 3));
341 let payload = frame.slice(buf);
342 assert_eq!(payload.as_init(), b"hello");
343 }
344}