ktls_core/
utils.rs

1//! Utilities
2
3use std::fmt;
4use std::mem::MaybeUninit;
5use std::num::NonZeroUsize;
6
7#[derive(Clone, Default)]
8/// A simple buffer with a read offset.
9pub struct Buffer {
10    /// The inner buffer data.
11    inner: Vec<u8>,
12
13    /// The number of initialized but unfilled bytes in the inner buffer.
14    unfilled_initialized: usize,
15
16    /// Read offset of the buffer.
17    offset: usize,
18}
19
20impl fmt::Debug for Buffer {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        f.debug_struct("Buffer")
23            .field("len", &self.inner.len())
24            .field("capacity", &self.inner.capacity())
25            .field("unfilled_initialized", &self.unfilled_initialized)
26            .field("offset", &self.offset)
27            .finish()
28    }
29}
30
31impl From<Vec<u8>> for Buffer {
32    #[inline]
33    fn from(buffer: Vec<u8>) -> Self {
34        Self::new(buffer)
35    }
36}
37
38impl Buffer {
39    #[inline]
40    #[must_use]
41    /// Creates a new [`Buffer`] from the given bytes slice.
42    pub fn new(buffer: Vec<u8>) -> Self {
43        Self {
44            inner: buffer,
45            unfilled_initialized: 0,
46            offset: 0,
47        }
48    }
49
50    #[inline]
51    #[must_use]
52    /// Creates an empty [`Buffer`].
53    pub const fn empty() -> Self {
54        Self {
55            inner: Vec::new(),
56            unfilled_initialized: 0,
57            offset: 0,
58        }
59    }
60
61    #[track_caller]
62    /// Reads the unread part of the buffer with the provided F, and advances
63    /// the read offset by the number of bytes read.
64    ///
65    /// Returns the number of bytes read by `f`.
66    ///
67    /// # Panics
68    ///
69    /// Panics if the closure returns an invalid read count.
70    pub fn read<F>(&mut self, f: F) -> Option<NonZeroUsize>
71    where
72        F: FnOnce(&[u8]) -> usize,
73    {
74        if self.inner.is_empty() {
75            // Empty buffer, nothing to read.
76
77            return None;
78        }
79
80        let Some((_, unread)) = self.inner.split_at_checked(self.offset) else {
81            unreachable!(
82                "The offset is always within the buffer length, but it is not: offset = {}, len = \
83                 {}",
84                self.offset,
85                self.inner.len()
86            );
87        };
88
89        if unread.is_empty() {
90            // All data has been read, reset the buffer.
91            self.reset();
92
93            return None;
94        }
95
96        let has_read = NonZeroUsize::new(f(unread));
97
98        match has_read {
99            Some(n) if n.get() <= unread.len() => {
100                // Advance the read offset, ensuring it does not exceed the buffer
101                // length.
102                self.offset = self.offset.saturating_add(n.get());
103            }
104            Some(n) => panic!(
105                "The closure read more bytes than available: read = {}, available = {}",
106                n,
107                unread.len()
108            ),
109            None => {}
110        }
111
112        has_read
113    }
114
115    #[inline]
116    #[must_use]
117    /// Returns the unread part of the buffer as a byte slice.
118    pub fn unread(&self) -> &[u8] {
119        &self.inner[self.offset..]
120    }
121
122    #[inline]
123    #[must_use]
124    /// Drains the inner buffer data, clearing the buffer but does not change
125    /// its capacity, and returns the drained data.
126    pub fn drain(&mut self) -> Option<Vec<u8>> {
127        if self.unread().is_empty() {
128            None
129        } else {
130            let drained = self.unread().to_vec();
131
132            // Reset the buffer after draining.
133            self.reset();
134
135            Some(drained)
136        }
137    }
138
139    #[inline]
140    /// Reserves capacity for at least `additional` more bytes.
141    pub(crate) fn reserve(&mut self, additional: usize) {
142        self.inner.reserve(additional);
143    }
144
145    #[inline]
146    /// Returns a mutable reference to the unfilled part of the buffer without
147    /// ensuring that it has been fully initialized.
148    pub(crate) fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
149        self.unfilled_initialized = 0;
150
151        self.inner.spare_capacity_mut()
152    }
153
154    #[inline]
155    /// Returns a reference to the unfilled but initialized part of the buffer.
156    pub(crate) fn unfilled_initialized(&self) -> &[u8] {
157        #[allow(unsafe_code)]
158        // SAFETY: We have ensured that the unfilled part is initialized.
159        unsafe {
160            std::slice::from_raw_parts(
161                self.inner
162                    .as_ptr()
163                    .add(self.inner.len()),
164                self.unfilled_initialized,
165            )
166        }
167    }
168
169    #[allow(unsafe_code)]
170    #[inline]
171    /// Marks additional `cnt` bytes of uninitialized part of the inner buffer
172    /// as initialized.
173    ///
174    /// # Safety
175    ///
176    /// The caller must ensure that the first `cnt` bytes of the spare capacity
177    /// have been initialized, and that `self.initialized + cnt` does not exceed
178    /// the capacity of the inner buffer.
179    ///
180    /// It is recommended to update the initialized bytes after acquiring (via
181    /// [`Spare::unfilled_mut`]) and writing to the unfilled part of the
182    /// buffer.
183    pub(crate) unsafe fn assume_init_additional(&mut self, cnt: usize) {
184        let unfilled_initialized = self.unfilled_initialized + cnt;
185
186        debug_assert!(self.inner.len() + unfilled_initialized <= self.inner.capacity());
187
188        self.unfilled_initialized = unfilled_initialized;
189    }
190
191    #[inline]
192    /// Marks all initialized spare capacity as filled.
193    pub(crate) fn set_filled_all(&mut self) {
194        let initialized = self.inner.len() + self.unfilled_initialized;
195
196        debug_assert!(initialized <= self.inner.capacity());
197
198        #[allow(unsafe_code)]
199        // SAFETY: We have ensured that the unfilled part is initialized, and the length is valid.
200        unsafe {
201            self.inner.set_len(initialized);
202        };
203
204        self.unfilled_initialized = 0;
205    }
206
207    #[inline]
208    /// Resets the buffer, clearing the inner data and resetting the read
209    /// offset.
210    fn reset(&mut self) {
211        self.inner.truncate(0);
212        self.inner.shrink_to(65536);
213        self.offset = 0;
214    }
215}
216
217#[cfg(test)]
218#[allow(unsafe_code)]
219#[allow(clippy::redundant_closure_for_method_calls)]
220mod tests {
221    use super::*;
222
223    #[test]
224    fn test_buffer_new() {
225        let data = vec![1, 2, 3, 4, 5];
226        let buffer = Buffer::new(data.clone());
227
228        assert_eq!(buffer.unread(), &data);
229        assert_eq!(buffer.offset, 0);
230        assert_eq!(buffer.unfilled_initialized, 0);
231    }
232
233    #[test]
234    fn test_buffer_empty() {
235        let buffer = Buffer::empty();
236
237        assert!(buffer.unread().is_empty());
238        assert_eq!(buffer.offset, 0);
239        assert_eq!(buffer.unfilled_initialized, 0);
240        assert_eq!(buffer.inner.capacity(), 0);
241    }
242
243    #[test]
244    fn test_buffer_from_vec() {
245        let data = vec![10, 20, 30];
246        let buffer: Buffer = data.clone().into();
247
248        assert_eq!(buffer.unread(), &data);
249        assert_eq!(buffer.offset, 0);
250    }
251
252    #[test]
253    fn test_buffer_read_empty() {
254        let mut buffer = Buffer::empty();
255
256        let result = buffer.read(|data| {
257            assert!(data.is_empty());
258            0
259        });
260
261        assert!(result.is_none());
262    }
263
264    #[test]
265    fn test_buffer_read_partial() {
266        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
267
268        // Read first 3 bytes
269        let result = buffer.read(|data| {
270            assert_eq!(data, &[1, 2, 3, 4, 5]);
271            3
272        });
273
274        assert_eq!(result.unwrap().get(), 3);
275        assert_eq!(buffer.unread(), &[4, 5]);
276        assert_eq!(buffer.offset, 3);
277    }
278
279    #[test]
280    fn test_buffer_read_full() {
281        let mut buffer = Buffer::new(vec![1, 2, 3]);
282
283        // Read all bytes
284        let result = buffer.read(|data| {
285            assert_eq!(data, &[1, 2, 3]);
286            3
287        });
288
289        assert_eq!(result.unwrap().get(), 3);
290        assert!(buffer.unread().is_empty());
291        assert_eq!(buffer.offset, 3);
292    }
293
294    #[test]
295    fn test_buffer_read_zero_bytes() {
296        let mut buffer = Buffer::new(vec![1, 2, 3]);
297
298        let result = buffer.read(|_data| 0);
299
300        assert!(result.is_none());
301        assert_eq!(buffer.unread(), &[1, 2, 3]);
302        assert_eq!(buffer.offset, 0);
303    }
304
305    #[test]
306    fn test_buffer_read_multiple_calls() {
307        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5, 6]);
308
309        // First read
310        let result1 = buffer.read(|data| {
311            assert_eq!(data, &[1, 2, 3, 4, 5, 6]);
312            2
313        });
314        assert_eq!(result1.unwrap().get(), 2);
315        assert_eq!(buffer.unread(), &[3, 4, 5, 6]);
316
317        // Second read
318        let result2 = buffer.read(|data| {
319            assert_eq!(data, &[3, 4, 5, 6]);
320            3
321        });
322        assert_eq!(result2.unwrap().get(), 3);
323        assert_eq!(buffer.unread(), &[6]);
324
325        // Third read (remaining)
326        let result3 = buffer.read(|data| {
327            assert_eq!(data, &[6]);
328            1
329        });
330        assert_eq!(result3.unwrap().get(), 1);
331        assert!(buffer.unread().is_empty());
332    }
333
334    #[test]
335    fn test_buffer_read_until_empty_resets() {
336        let mut buffer = Buffer::new(vec![1, 2, 3]);
337
338        // Read all data
339        let _ = buffer.read(|data| data.len());
340
341        // Buffer should still have offset set
342        assert_eq!(buffer.offset, 3);
343        assert!(buffer.unread().is_empty());
344
345        // Next read should reset and return None
346        let result = buffer.read(|_| 0);
347
348        assert!(result.is_none());
349        assert_eq!(buffer.offset, 0);
350        assert_eq!(buffer.inner.len(), 0); // Buffer is reset
351    }
352
353    #[test]
354    #[should_panic(expected = "The closure read more bytes than available")]
355    fn test_buffer_read_panic_read_too_much() {
356        let mut buffer = Buffer::new(vec![1, 2, 3]);
357
358        // Try to read more bytes than available
359        buffer.read(|data| {
360            assert_eq!(data.len(), 3);
361            4 // This should panic
362        });
363    }
364
365    #[test]
366    fn test_buffer_unread() {
367        let buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
368        assert_eq!(buffer.unread(), &[1, 2, 3, 4, 5]);
369    }
370
371    #[test]
372    fn test_buffer_unread_after_partial_read() {
373        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
374
375        // Read 2 bytes
376        let _ = buffer.read(|_| 2);
377
378        assert_eq!(buffer.unread(), &[3, 4, 5]);
379    }
380
381    #[test]
382    fn test_buffer_drain_empty() {
383        let mut buffer = Buffer::empty();
384
385        let drained = buffer.drain();
386        assert!(drained.is_none());
387    }
388
389    #[test]
390    fn test_buffer_drain_with_data() {
391        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
392
393        let drained = buffer.drain();
394        assert_eq!(drained.unwrap(), vec![1, 2, 3, 4, 5]);
395
396        // Buffer should be reset after drain
397        assert!(buffer.unread().is_empty());
398        assert_eq!(buffer.offset, 0);
399        assert_eq!(buffer.inner.len(), 0);
400    }
401
402    #[test]
403    fn test_buffer_drain_after_partial_read() {
404        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
405
406        // Read first 2 bytes
407        let _ = buffer.read(|_| 2);
408
409        let drained = buffer.drain();
410        assert_eq!(drained.unwrap(), vec![3, 4, 5]); // Only unread data
411
412        // Buffer should be reset
413        assert!(buffer.unread().is_empty());
414        assert_eq!(buffer.offset, 0);
415    }
416
417    #[test]
418    fn test_buffer_drain_fully_read() {
419        let mut buffer = Buffer::new(vec![1, 2, 3]);
420
421        // Read all data
422        let _ = buffer.read(|data| data.len());
423
424        let drained = buffer.drain();
425        assert!(drained.is_none()); // Nothing to drain
426    }
427
428    #[test]
429    fn test_buffer_reserve() {
430        let mut buffer = Buffer::empty();
431        let initial_capacity = buffer.inner.capacity();
432
433        buffer.reserve(100);
434        assert!(buffer.inner.capacity() >= initial_capacity + 100);
435    }
436
437    #[test]
438    fn test_buffer_unfilled_mut() {
439        let mut buffer = Buffer::empty();
440        buffer.reserve(10);
441
442        let unfilled = buffer.unfilled_mut();
443        assert_eq!(unfilled.len(), 10);
444        assert_eq!(buffer.unfilled_initialized, 0);
445
446        unsafe { buffer.assume_init_additional(5) };
447        assert_eq!(buffer.unfilled_initialized, 5);
448
449        let unfilled = buffer.unfilled_mut();
450        assert!(!unfilled.is_empty());
451        assert_eq!(buffer.unfilled_initialized, 0); // Should be reset to 0
452    }
453
454    #[test]
455    fn test_buffer_unfilled_initialized_empty() {
456        let buffer = Buffer::empty();
457        let unfilled_init = buffer.unfilled_initialized();
458        assert!(unfilled_init.is_empty());
459    }
460
461    #[test]
462    fn test_buffer_assume_init_additional() {
463        let mut buffer = Buffer::empty();
464        buffer.reserve(10);
465
466        // Simulate writing to unfilled part
467        unsafe {
468            buffer.assume_init_additional(5);
469        }
470
471        assert_eq!(buffer.unfilled_initialized, 5);
472
473        let unfilled_init = buffer.unfilled_initialized();
474        assert_eq!(unfilled_init.len(), 5);
475    }
476
477    #[test]
478    fn test_buffer_set_filled_all() {
479        let mut buffer = Buffer::empty();
480
481        buffer.reserve(10);
482
483        unsafe {
484            buffer.assume_init_additional(3);
485        }
486
487        assert_eq!(buffer.inner.len(), 0);
488
489        buffer.set_filled_all();
490
491        assert_eq!(buffer.inner.len(), 3);
492        assert_eq!(buffer.unfilled_initialized, 0);
493    }
494
495    #[test]
496    fn test_buffer_complex_workflow() {
497        // Test a complex workflow that uses multiple methods
498        let mut buffer = Buffer::new(vec![1, 2, 3, 4, 5]);
499
500        // Read some data
501        let _ = buffer.read(|_| 2);
502        assert_eq!(buffer.unread(), &[3, 4, 5]);
503
504        // Reserve more space
505        buffer.reserve(10);
506
507        // Get unfilled space and mark some as initialized
508        let _unfilled = buffer.unfilled_mut();
509        unsafe {
510            buffer.assume_init_additional(2);
511        }
512
513        // Set the initialized data as filled
514        buffer.set_filled_all();
515
516        // The buffer should now contain original unread data plus the new filled data
517        assert!(buffer.unread().len() >= 3); // At least the original unread data
518
519        // Drain everything
520        let drained = buffer.drain();
521        assert!(drained.is_some());
522        assert!(buffer.unread().is_empty());
523    }
524}