compio_io/framed/
frame.rs1use compio_buf::{
4 IoBufMut,
5 bytes::{Buf, BufMut},
6};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Frame {
11 prefix: usize,
13
14 payload: usize,
16
17 suffix: usize,
19}
20
21impl Frame {
22 pub fn new(prefix: usize, payload: usize, suffix: usize) -> Self {
25 Self {
26 prefix,
27 payload,
28 suffix,
29 }
30 }
31
32 pub fn len(&self) -> usize {
34 self.prefix + self.payload + self.suffix
35 }
36
37 pub fn is_empty(&self) -> bool {
39 self.len() == 0
40 }
41
42 pub fn payload<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
44 &buf[self.prefix..self.prefix + self.payload]
45 }
46}
47
48pub trait Framer {
50 fn enclose(&mut self, buf: &mut Vec<u8>);
59
60 fn extract(&mut self, buf: &[u8]) -> Option<Frame>;
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub struct LengthDelimited {
74 length_field_len: usize,
75 length_field_is_big_endian: bool,
76}
77
78impl Default for LengthDelimited {
79 fn default() -> Self {
80 Self {
81 length_field_len: 4,
82 length_field_is_big_endian: true,
83 }
84 }
85}
86
87impl LengthDelimited {
88 pub fn new() -> Self {
90 Self::default()
91 }
92
93 pub fn length_field_len(&self) -> usize {
95 self.length_field_len
96 }
97
98 pub fn set_length_field_len(mut self, len_field_len: usize) -> Self {
100 self.length_field_len = len_field_len;
101 self
102 }
103
104 pub fn length_field_is_big_endian(&self) -> bool {
106 self.length_field_is_big_endian
107 }
108
109 pub fn set_length_field_is_big_endian(mut self, big_endian: bool) -> Self {
111 self.length_field_is_big_endian = big_endian;
112 self
113 }
114}
115
116impl Framer for LengthDelimited {
117 fn enclose(&mut self, buf: &mut Vec<u8>) {
118 let len = buf.len();
119
120 buf.reserve(self.length_field_len);
121 IoBufMut::as_mut_slice(buf).copy_within(0..len, self.length_field_len); unsafe { buf.set_len(len + self.length_field_len) };
123
124 if self.length_field_is_big_endian {
126 (&mut buf[0..self.length_field_len]).put_uint(len as _, self.length_field_len);
127 } else {
128 (&mut buf[0..self.length_field_len]).put_uint_le(len as _, self.length_field_len);
129 }
130 }
131
132 fn extract(&mut self, mut buf: &[u8]) -> Option<Frame> {
133 if buf.len() < self.length_field_len {
134 return None;
135 }
136
137 let len = if self.length_field_is_big_endian {
138 buf.get_uint(self.length_field_len)
139 } else {
140 buf.get_uint_le(self.length_field_len)
141 } as usize;
142
143 if buf.len() < len {
144 return None;
145 }
146
147 Some(Frame::new(self.length_field_len, len, 0))
148 }
149}
150
151#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct CharDelimited<const C: char> {}
154
155impl<const C: char> CharDelimited<C> {
156 pub fn new() -> Self {
158 Self {}
159 }
160}
161
162impl<const C: char> Framer for CharDelimited<C> {
163 fn enclose(&mut self, buf: &mut Vec<u8>) {
164 buf.push(C as u8);
165 }
166
167 fn extract(&mut self, buf: &[u8]) -> Option<Frame> {
168 if buf.is_empty() {
169 return None;
170 }
171
172 buf.iter()
173 .position(|&b| b == C as u8)
174 .map(|pos| Frame::new(0, pos, 1))
175 }
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
180pub struct AnyDelimited<'a> {
181 bytes: &'a [u8],
182}
183
184impl<'a> AnyDelimited<'a> {
185 pub fn new(bytes: &'a [u8]) -> Self {
187 Self { bytes }
188 }
189}
190
191impl Framer for AnyDelimited<'_> {
192 fn extract(&mut self, buf: &[u8]) -> Option<Frame> {
193 if buf.is_empty() {
194 return None;
195 }
196
197 if let Some(pos) = buf
200 .windows(self.bytes.len())
201 .position(|window| window == self.bytes)
202 {
203 Some(Frame::new(0, pos, self.bytes.len()))
204 } else {
205 None
206 }
207 }
208
209 fn enclose(&mut self, buf: &mut Vec<u8>) {
210 buf.extend_from_slice(self.bytes);
211 }
212}
213
214pub type LineDelimited = CharDelimited<'\n'>;