hotfix_message/encoding/
buffer.rs

1/// Operations on a growable in-memory buffer.
2///
3/// This trait is intended to be used as a thin compatibility layer between
4/// [`Vec<u8>`] and
5/// [`bytes::BytesMut`](https://docs.rs/bytes/1.1.0/bytes/struct.BytesMut.html).
6/// By writing generic code that operates on [`Buffer`], HotFIX users can
7/// decide for themselves if they want to use `bytes` and still use most of the
8/// features.
9///
10/// It's important to note that, unlike [`std::io::Write`] which only allows
11/// sequential write operations, [`Buffer`] allows arbitrary data manipulation
12/// over the whole buffer.
13pub trait Buffer {
14    /// Returns an immutable reference to the whole contents of the buffer.
15    fn as_slice(&self) -> &[u8];
16
17    /// Returns a mutable reference to the whole contents of the buffer.
18    fn as_mut_slice(&mut self) -> &mut [u8];
19
20    /// Returns the length of the whole contents of the buffer.
21    #[inline]
22    fn len(&self) -> usize {
23        self.as_slice().len()
24    }
25
26    /// Returns `true` if the buffer is empty.
27    #[inline]
28    fn is_empty(&self) -> bool {
29        self.len() == 0
30    }
31
32    /// Returns the number of bytes that `self` can hold without reallocating.
33    fn capacity(&self) -> usize;
34
35    /// Completely erases the contents of `self`.
36    fn clear(&mut self);
37
38    /// Appends the contents of `extend` onto `self`, growing the buffer if
39    /// necessary.
40    fn extend_from_slice(&mut self, extend: &[u8]);
41
42    /// Resizes this [`Buffer`] in-place so that its new `len()` is equal to
43    /// `new_len`.
44    ///
45    /// If `new_len` is greater than [`Buffer::len()`], `self` is extended by
46    /// the difference, with each additional byte set as `filler`. If `new_len`
47    /// is less than [`Buffer::len()`], `self` is simply truncated.
48    #[inline]
49    fn resize(&mut self, new_len: usize, filler: u8) {
50        for _ in 0..new_len - self.as_slice().len() {
51            self.extend_from_slice(&[filler]);
52        }
53    }
54}
55
56impl Buffer for Vec<u8> {
57    #[inline]
58    fn as_slice(&self) -> &[u8] {
59        self.as_slice()
60    }
61
62    #[inline]
63    fn as_mut_slice(&mut self) -> &mut [u8] {
64        self.as_mut_slice()
65    }
66
67    #[inline]
68    fn capacity(&self) -> usize {
69        self.capacity()
70    }
71
72    #[inline]
73    fn clear(&mut self) {
74        self.clear()
75    }
76
77    #[inline]
78    fn extend_from_slice(&mut self, extend: &[u8]) {
79        self.extend_from_slice(extend)
80    }
81
82    #[inline]
83    fn resize(&mut self, new_len: usize, filler: u8) {
84        self.resize(new_len, filler)
85    }
86}
87
88/// A [`Buffer`] wrapper that implements [`std::fmt::Write`].
89#[allow(missing_debug_implementations)]
90pub struct BufferWriter<'a, B>(pub &'a mut B);
91
92impl<'a, B> std::fmt::Write for BufferWriter<'a, B>
93where
94    B: Buffer,
95{
96    fn write_str(&mut self, s: &str) -> std::fmt::Result {
97        self.0.extend_from_slice(s.as_bytes());
98        Ok(())
99    }
100}
101
102#[cfg(test)]
103mod test {
104    use super::*;
105    use quickcheck_macros::quickcheck;
106
107    #[quickcheck]
108    fn vec_slicing_is_consistent(mut vec: Vec<u8>) -> bool {
109        let buf_as_slice = Vec::from(Buffer::as_mut_slice(&mut vec));
110        let buf_as_mut_slice = Vec::from(Buffer::as_slice(&vec));
111        let buf_len = Buffer::len(&vec);
112        buf_as_slice == buf_as_mut_slice && buf_as_slice.len() == buf_len
113    }
114
115    #[quickcheck]
116    fn vec_clear_always_removes_content(mut vec: Vec<u8>) -> bool {
117        Buffer::clear(&mut vec);
118        vec.is_empty()
119    }
120}