compio_io\framed/
frame.rs1use std::io;
4
5use compio_buf::{
6 IoBufMut,
7 bytes::{Buf, BufMut},
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Frame {
13 prefix: usize,
15
16 payload: usize,
18
19 suffix: usize,
21}
22
23impl Frame {
24 pub fn new(prefix: usize, payload: usize, suffix: usize) -> Self {
27 Self {
28 prefix,
29 payload,
30 suffix,
31 }
32 }
33
34 pub fn len(&self) -> usize {
36 self.prefix + self.payload + self.suffix
37 }
38
39 pub fn is_empty(&self) -> bool {
41 self.len() == 0
42 }
43
44 pub fn payload<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
46 &buf[self.prefix..self.prefix + self.payload]
47 }
48}
49
50pub trait Framer {
52 fn enclose(&mut self, buf: &mut Vec<u8>);
61
62 fn extract(&mut self, buf: &[u8]) -> io::Result<Option<Frame>>;
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
75pub struct LengthDelimited {
76 length_field_len: usize,
77 length_field_is_big_endian: bool,
78}
79
80impl Default for LengthDelimited {
81 fn default() -> Self {
82 Self {
83 length_field_len: 4,
84 length_field_is_big_endian: true,
85 }
86 }
87}
88
89impl LengthDelimited {
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 {
102 self.length_field_len = len_field_len;
103 self
104 }
105
106 pub fn length_field_is_big_endian(&self) -> bool {
108 self.length_field_is_big_endian
109 }
110
111 pub fn set_length_field_is_big_endian(mut self, big_endian: bool) -> Self {
113 self.length_field_is_big_endian = big_endian;
114 self
115 }
116}
117
118impl Framer for LengthDelimited {
119 fn enclose(&mut self, buf: &mut Vec<u8>) {
120 let len = buf.len();
121
122 buf.reserve(self.length_field_len);
123 IoBufMut::as_uninit(buf).copy_within(0..len, self.length_field_len); unsafe { buf.set_len(len + self.length_field_len) };
125
126 if self.length_field_is_big_endian {
128 (&mut buf[0..self.length_field_len]).put_uint(len as _, self.length_field_len);
129 } else {
130 (&mut buf[0..self.length_field_len]).put_uint_le(len as _, self.length_field_len);
131 }
132 }
133
134 fn extract(&mut self, mut buf: &[u8]) -> io::Result<Option<Frame>> {
135 if buf.len() < self.length_field_len {
136 return Ok(None);
137 }
138
139 let len = if self.length_field_is_big_endian {
140 buf.get_uint(self.length_field_len)
141 } else {
142 buf.get_uint_le(self.length_field_len)
143 } as usize;
144
145 if buf.len() < len {
146 return Ok(None);
147 }
148
149 Ok(Some(Frame::new(self.length_field_len, len, 0)))
150 }
151}
152
153#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
155pub struct CharDelimited<const C: char> {}
156
157impl<const C: char> CharDelimited<C> {
158 pub fn new() -> Self {
160 Self {}
161 }
162}
163
164impl<const C: char> Framer for CharDelimited<C> {
165 fn enclose(&mut self, buf: &mut Vec<u8>) {
166 buf.push(C as u8);
167 }
168
169 fn extract(&mut self, buf: &[u8]) -> io::Result<Option<Frame>> {
170 if buf.is_empty() {
171 return Ok(None);
172 }
173
174 Ok(buf
175 .iter()
176 .position(|&b| b == C as u8)
177 .map(|pos| Frame::new(0, pos, 1)))
178 }
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
183pub struct AnyDelimited<'a> {
184 bytes: &'a [u8],
185}
186
187impl<'a> AnyDelimited<'a> {
188 pub fn new(bytes: &'a [u8]) -> Self {
190 Self { bytes }
191 }
192}
193
194impl Framer for AnyDelimited<'_> {
195 fn extract(&mut self, buf: &[u8]) -> io::Result<Option<Frame>> {
196 if buf.is_empty() {
197 return Ok(None);
198 }
199
200 if let Some(pos) = buf
203 .windows(self.bytes.len())
204 .position(|window| window == self.bytes)
205 {
206 Ok(Some(Frame::new(0, pos, self.bytes.len())))
207 } else {
208 Ok(None)
209 }
210 }
211
212 fn enclose(&mut self, buf: &mut Vec<u8>) {
213 buf.extend_from_slice(self.bytes);
214 }
215}
216
217pub type LineDelimited = CharDelimited<'\n'>;