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        StableBuf::Vec(Vec::new())
20    }
21}
22
23impl From<Vec<u8>> for StableBuf {
24    fn from(v: Vec<u8>) -> Self {
25        StableBuf::Vec(v)
26    }
27}
28
29impl From<bytes::BytesMut> for StableBuf {
30    fn from(b: bytes::BytesMut) -> Self {
31        StableBuf::BytesMut(b)
32    }
33}
34
35impl From<StableBuf> for Bytes {
36    fn from(buf: StableBuf) -> Self {
37        match buf {
38            StableBuf::Vec(v) => Bytes::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            StableBuf::Vec(v) => &v[index],
59            StableBuf::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            StableBuf::Vec(v) => v.as_mut_ptr(),
69            StableBuf::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            StableBuf::Vec(v) => v.len(),
77            StableBuf::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            StableBuf::Vec(v) => v.is_empty(),
85            StableBuf::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        unsafe {
95            core::ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
96        }
97    }
98
99    /// Truncates the buffer to the specified length.
100    pub fn truncate(&mut self, len: usize) {
101        match self {
102            StableBuf::Vec(v) => v.truncate(len),
103            StableBuf::BytesMut(b) => b.truncate(len),
104        }
105    }
106}
107
108impl AsRef<[u8]> for StableBuf {
109    fn as_ref(&self) -> &[u8] {
110        match self {
111            StableBuf::Vec(v) => v.as_ref(),
112            StableBuf::BytesMut(b) => b.as_ref(),
113        }
114    }
115}
116
117impl AsMut<[u8]> for StableBuf {
118    fn as_mut(&mut self) -> &mut [u8] {
119        match self {
120            StableBuf::Vec(v) => v.as_mut(),
121            StableBuf::BytesMut(b) => b.as_mut(),
122        }
123    }
124}