commonware_utils/
stable_buf.rs

1//! # Acknowledgements
2//!
3//! This code is inspired by [tokio-uring](https://github.com/tokio-rs/tokio-uring>) at commit 7761222.
4
5#[cfg(not(feature = "std"))]
6use alloc::vec::Vec;
7use bytes::Bytes;
8use core::ops::Index;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11/// A buffer whose memory is stable as long as its not reallocated.
12pub enum StableBuf {
13    Vec(Vec<u8>),
14    BytesMut(bytes::BytesMut),
15}
16
17impl Default for StableBuf {
18    fn default() -> Self {
19        Self::Vec(Vec::new())
20    }
21}
22
23impl From<Vec<u8>> for StableBuf {
24    fn from(v: Vec<u8>) -> Self {
25        Self::Vec(v)
26    }
27}
28
29impl From<bytes::BytesMut> for StableBuf {
30    fn from(b: bytes::BytesMut) -> Self {
31        Self::BytesMut(b)
32    }
33}
34
35impl From<StableBuf> for Bytes {
36    fn from(buf: StableBuf) -> Self {
37        match buf {
38            StableBuf::Vec(v) => Self::from(v),
39            StableBuf::BytesMut(b) => b.freeze(),
40        }
41    }
42}
43
44impl From<StableBuf> for Vec<u8> {
45    fn from(buf: StableBuf) -> Self {
46        match buf {
47            StableBuf::Vec(v) => v,
48            StableBuf::BytesMut(b) => b.to_vec(),
49        }
50    }
51}
52
53impl Index<usize> for StableBuf {
54    type Output = u8;
55
56    fn index(&self, index: usize) -> &Self::Output {
57        match self {
58            Self::Vec(v) => &v[index],
59            Self::BytesMut(b) => &b[index],
60        }
61    }
62}
63
64impl StableBuf {
65    /// Returns a raw pointer to this buffer.
66    pub fn as_mut_ptr(&mut self) -> *mut u8 {
67        match self {
68            Self::Vec(v) => v.as_mut_ptr(),
69            Self::BytesMut(b) => b.as_mut_ptr(),
70        }
71    }
72
73    /// Returns the length of the buffer.
74    pub fn len(&self) -> usize {
75        match self {
76            Self::Vec(v) => v.len(),
77            Self::BytesMut(b) => b.len(),
78        }
79    }
80
81    /// Returns whether this buffer is empty.
82    pub fn is_empty(&self) -> bool {
83        match self {
84            Self::Vec(v) => v.is_empty(),
85            Self::BytesMut(b) => b.is_empty(),
86        }
87    }
88
89    /// Copies the given byte slice into this buffer.
90    /// `src` must not overlap with this buffer.
91    /// Panics if `src` exceeds this buffer's length.
92    pub fn put_slice(&mut self, src: &[u8]) {
93        let dst = self.as_mut_ptr();
94        // SAFETY: Caller guarantees no overlap and sufficient length.
95        unsafe {
96            core::ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
97        }
98    }
99
100    /// Truncates the buffer to the specified length.
101    pub fn truncate(&mut self, len: usize) {
102        match self {
103            Self::Vec(v) => v.truncate(len),
104            Self::BytesMut(b) => b.truncate(len),
105        }
106    }
107}
108
109impl AsRef<[u8]> for StableBuf {
110    fn as_ref(&self) -> &[u8] {
111        match self {
112            Self::Vec(v) => v.as_ref(),
113            Self::BytesMut(b) => b.as_ref(),
114        }
115    }
116}
117
118impl AsMut<[u8]> for StableBuf {
119    fn as_mut(&mut self) -> &mut [u8] {
120        match self {
121            Self::Vec(v) => v.as_mut(),
122            Self::BytesMut(b) => b.as_mut(),
123        }
124    }
125}