hoy_protocol/
frame_buffer.rs1use serde::de::DeserializeOwned;
4
5use crate::codec::try_decode_frame;
6use crate::error::ProtocolError;
7
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
10pub struct FrameBuffer {
11 bytes: Vec<u8>,
13}
14
15impl FrameBuffer {
16 #[must_use]
18 pub const fn new() -> Self {
19 Self { bytes: Vec::new() }
20 }
21
22 #[must_use]
24 pub fn with_capacity(capacity: usize) -> Self {
25 Self {
26 bytes: Vec::with_capacity(capacity),
27 }
28 }
29
30 pub fn append(&mut self, chunk: &[u8]) -> Result<(), ProtocolError> {
43 let _new_len: usize = self
44 .bytes
45 .len()
46 .checked_add(chunk.len())
47 .ok_or(ProtocolError::CapacityOverflow)?;
48
49 self.bytes.extend_from_slice(chunk);
50 Ok(())
51 }
52
53 pub fn try_decode<T>(&mut self) -> Result<Option<T>, ProtocolError>
72 where
73 T: DeserializeOwned,
74 {
75 let Some((value, consumed)) = try_decode_frame::<T>(&self.bytes)? else {
76 return Ok(None);
77 };
78
79 self.discard_prefix(consumed)?;
80 Ok(Some(value))
81 }
82
83 #[must_use]
85 pub fn len(&self) -> usize {
86 self.bytes.len()
87 }
88
89 #[must_use]
91 pub fn is_empty(&self) -> bool {
92 self.bytes.is_empty()
93 }
94
95 pub fn clear(&mut self) {
97 self.bytes.clear();
98 }
99
100 #[must_use]
102 pub fn as_slice(&self) -> &[u8] {
103 &self.bytes
104 }
105
106 fn discard_prefix(&mut self, count: usize) -> Result<(), ProtocolError> {
119 if count > self.len() {
120 return Err(ProtocolError::InvalidDiscard {
121 count,
122 buffer_len: self.len(),
123 });
124 }
125
126 if count == 0 {
127 return Ok(());
128 }
129
130 if count == self.len() {
131 self.bytes.clear();
132 return Ok(());
133 }
134
135 self.bytes.copy_within(count.., 0);
136
137 let new_len: usize = self
138 .bytes
139 .len()
140 .checked_sub(count)
141 .ok_or(ProtocolError::CapacityOverflow)?;
142
143 self.bytes.truncate(new_len);
144 Ok(())
145 }
146}
147
148#[cfg(test)]
149#[allow(dead_code, unused)]
150mod tests {
151 use hoy_test::assert_err;
152 use serde::de::DeserializeOwned;
153
154 use crate::codec::encode_frame;
155 use crate::error::ProtocolError;
156 use crate::frame_buffer::FrameBuffer;
157 use crate::packet::ClientPacket;
158
159 fn encode_ok(value: &impl serde::Serialize) -> Vec<u8> {
160 encode_frame(value).expect("Frame encoding failed unexpectedly.")
161 }
162
163 fn append_ok(buffer: &mut FrameBuffer, chunk: &[u8]) {
164 let len_og = buffer.len();
165 buffer.append(chunk).expect("Append failed unexpectedly.");
166 assert!(!buffer.is_empty());
167 assert_eq!(
168 buffer.len(),
169 chunk
170 .len()
171 .checked_add(len_og)
172 .expect("Unexpected buffer length overflow.")
173 );
174 }
175
176 fn try_decode_ok<T>(buffer: &mut FrameBuffer) -> T
177 where
178 T: DeserializeOwned,
179 {
180 buffer
181 .try_decode::<T>()
182 .expect("Decoding failed unexpectedly.")
183 .expect("Decoded frame should not be None.")
184 }
185
186 fn try_decode_none<T>(buffer: &mut FrameBuffer) -> Option<T>
187 where
188 T: DeserializeOwned + std::fmt::Debug + PartialEq,
189 {
190 let result = buffer
191 .try_decode::<T>()
192 .expect("Decoding failed unexpectedly.");
193 assert_eq!(result, None);
194 result
195 }
196
197 fn try_decode_err<T>(buffer: &mut FrameBuffer, error: &str) -> ProtocolError
198 where
199 T: DeserializeOwned + std::fmt::Debug,
200 {
201 buffer
202 .try_decode::<T>()
203 .expect_err(&format!("Decoding should return error: {error}"))
204 }
205
206 #[test]
207 fn new_buffer_is_empty() {
208 let buffer = FrameBuffer::new();
209
210 assert!(buffer.is_empty());
211 assert_eq!(buffer.len(), 0);
212 }
213
214 #[test]
215 fn append_adds_bytes_to_buffer() {
216 let mut buffer = FrameBuffer::new();
217
218 append_ok(&mut buffer, b"abcd");
219
220 assert_eq!(buffer.len(), 4);
221 assert_eq!(buffer.as_slice(), b"abcd");
222 }
223
224 #[test]
225 fn try_decode_returns_none_for_incomplete_frame() {
226 let mut buffer = FrameBuffer::new();
227
228 buffer
229 .append(&[0, 0, 0])
230 .expect("Append failed unexpectedly.");
231
232 let decoded = buffer
233 .try_decode::<ClientPacket>()
234 .expect("Decoding failed unexpectedly");
235 assert_eq!(decoded, None);
236 assert_eq!(buffer.as_slice(), &[0, 0, 0]);
237 }
238
239 #[test]
240 fn try_decode_returns_complete_frame_and_consumes_it() {
241 let mut buffer = FrameBuffer::new();
242 let packet = ClientPacket::Ping;
243 let frame = encode_ok(&packet);
244
245 append_ok(&mut buffer, &frame);
246
247 let decoded = try_decode_ok::<ClientPacket>(&mut buffer);
248 assert_eq!(decoded, packet);
249 assert!(buffer.is_empty());
250 }
251
252 #[test]
253 fn try_decode_keeps_trailing_bytes_for_next_frame() {
254 let mut buffer = FrameBuffer::new();
255
256 let packet1 = ClientPacket::Ping;
257 let packet2 = ClientPacket::Hello {
258 username: String::from("bruce_lee"),
259 };
260
261 let frame1 = encode_ok(&packet1);
262 let frame2 = encode_ok(&packet2);
263
264 append_ok(&mut buffer, &frame1);
265 append_ok(&mut buffer, &frame2);
266
267 let decoded1 = try_decode_ok::<ClientPacket>(&mut buffer);
268 assert_eq!(decoded1, packet1);
269 assert!(!buffer.is_empty());
270 assert_eq!(buffer.len(), frame2.len());
271
272 let decoded2 = try_decode_ok::<ClientPacket>(&mut buffer);
273 assert_eq!(decoded2, packet2);
274 assert!(buffer.is_empty());
275 }
276
277 #[test]
278 fn try_decode_returns_error_for_malformed_complete_frame() {
279 let mut buffer = FrameBuffer::new();
280
281 append_ok(&mut buffer, &[0, 0, 0, 4, b'b', b'a', b'd', b'!']);
282
283 let error = try_decode_err::<ClientPacket>(&mut buffer, "Serde error");
284 assert_err!(error, ProtocolError::Serde(_));
285 }
286
287 #[test]
288 fn clear_removes_all_buffered_data() {
289 let mut buffer = FrameBuffer::with_capacity(16);
290
291 append_ok(&mut buffer, b"1234567890123456");
292
293 buffer.clear();
294
295 assert!(buffer.is_empty());
296 assert_eq!(buffer.len(), 0);
297 }
298}