ipfrs_interface/
zerocopy.rs

1//! Zero-copy buffer management
2//!
3//! Provides efficient buffer management with zero-copy semantics using Bytes.
4
5use bytes::Bytes;
6
7/// Zero-copy buffer for efficient data transfer
8///
9/// Uses `Bytes` internally which provides reference-counted, immutable byte buffers
10/// that can be sliced without copying.
11#[derive(Debug, Clone)]
12pub struct ZeroCopyBuffer {
13    data: Bytes,
14}
15
16impl ZeroCopyBuffer {
17    /// Create a new zero-copy buffer from Bytes
18    pub fn new(data: Bytes) -> Self {
19        Self { data }
20    }
21
22    /// Create from a vector (takes ownership)
23    pub fn from_vec(vec: Vec<u8>) -> Self {
24        Self {
25            data: Bytes::from(vec),
26        }
27    }
28
29    /// Create from a static byte slice
30    pub fn from_static(bytes: &'static [u8]) -> Self {
31        Self {
32            data: Bytes::from_static(bytes),
33        }
34    }
35
36    /// Get a reference to the underlying data
37    pub fn as_slice(&self) -> &[u8] {
38        &self.data
39    }
40
41    /// Get the length of the buffer
42    pub fn len(&self) -> usize {
43        self.data.len()
44    }
45
46    /// Check if the buffer is empty
47    pub fn is_empty(&self) -> bool {
48        self.data.is_empty()
49    }
50
51    /// Create a zero-copy slice of this buffer
52    ///
53    /// This operation is very efficient as it only increments a reference count
54    /// and doesn't copy any data.
55    pub fn slice(&self, range: std::ops::Range<usize>) -> Self {
56        Self {
57            data: self.data.slice(range),
58        }
59    }
60
61    /// Get the underlying Bytes
62    pub fn into_bytes(self) -> Bytes {
63        self.data
64    }
65
66    /// Get a reference to the underlying Bytes
67    pub fn bytes(&self) -> &Bytes {
68        &self.data
69    }
70
71    /// Split the buffer at an index
72    ///
73    /// Returns two zero-copy buffers: [0, at) and [at, len).
74    /// This is a zero-copy operation.
75    pub fn split_at(&self, at: usize) -> (Self, Self) {
76        let left = self.data.slice(0..at);
77        let right = self.data.slice(at..);
78        (Self { data: left }, Self { data: right })
79    }
80
81    /// Split off the first n bytes
82    pub fn split_to(&self, at: usize) -> Self {
83        Self {
84            data: self.data.slice(0..at),
85        }
86    }
87
88    /// Split off the last n bytes
89    pub fn split_from(&self, at: usize) -> Self {
90        Self {
91            data: self.data.slice(at..),
92        }
93    }
94}
95
96impl From<Vec<u8>> for ZeroCopyBuffer {
97    fn from(vec: Vec<u8>) -> Self {
98        Self::from_vec(vec)
99    }
100}
101
102impl From<Bytes> for ZeroCopyBuffer {
103    fn from(bytes: Bytes) -> Self {
104        Self::new(bytes)
105    }
106}
107
108impl From<&'static [u8]> for ZeroCopyBuffer {
109    fn from(bytes: &'static [u8]) -> Self {
110        Self::from_static(bytes)
111    }
112}
113
114impl AsRef<[u8]> for ZeroCopyBuffer {
115    fn as_ref(&self) -> &[u8] {
116        self.as_slice()
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn test_zero_copy_buffer_basic() {
126        let data = vec![1, 2, 3, 4, 5];
127        let buf = ZeroCopyBuffer::from_vec(data);
128
129        assert_eq!(buf.len(), 5);
130        assert!(!buf.is_empty());
131        assert_eq!(buf.as_slice(), &[1, 2, 3, 4, 5]);
132    }
133
134    #[test]
135    fn test_zero_copy_slice() {
136        let buf = ZeroCopyBuffer::from_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
137        let slice = buf.slice(2..7);
138
139        assert_eq!(slice.len(), 5);
140        assert_eq!(slice.as_slice(), &[2, 3, 4, 5, 6]);
141    }
142
143    #[test]
144    fn test_zero_copy_split_at() {
145        let buf = ZeroCopyBuffer::from_vec(vec![1, 2, 3, 4, 5]);
146        let (left, right) = buf.split_at(3);
147
148        assert_eq!(left.as_slice(), &[1, 2, 3]);
149        assert_eq!(right.as_slice(), &[4, 5]);
150    }
151
152    #[test]
153    fn test_zero_copy_split_to() {
154        let buf = ZeroCopyBuffer::from_vec(vec![1, 2, 3, 4, 5]);
155        let first = buf.split_to(3);
156
157        assert_eq!(first.as_slice(), &[1, 2, 3]);
158    }
159
160    #[test]
161    fn test_zero_copy_split_from() {
162        let buf = ZeroCopyBuffer::from_vec(vec![1, 2, 3, 4, 5]);
163        let last = buf.split_from(3);
164
165        assert_eq!(last.as_slice(), &[4, 5]);
166    }
167
168    #[test]
169    fn test_zero_copy_from_static() {
170        let buf = ZeroCopyBuffer::from_static(b"hello world");
171
172        assert_eq!(buf.len(), 11);
173        assert_eq!(buf.as_slice(), b"hello world");
174    }
175
176    #[test]
177    fn test_zero_copy_empty() {
178        let buf = ZeroCopyBuffer::from_vec(vec![]);
179
180        assert_eq!(buf.len(), 0);
181        assert!(buf.is_empty());
182    }
183}