Skip to main content

karyon_net/
buffer.rs

1use bytes::{Buf, BytesMut};
2
3/// Back-compat alias used as the wire type in `Codec<W>` for byte-stream
4/// framing.
5pub type ByteBuffer = Buffer;
6
7/// Mutable, growable byte container. Used by codecs to build and consume
8/// framed payloads, and as an owned container for transport-level payloads.
9#[derive(Debug, Default)]
10pub struct Buffer {
11    inner: BytesMut,
12}
13
14impl Buffer {
15    /// Constructs a new, empty `Buffer`.
16    pub fn new() -> Self {
17        Self {
18            inner: BytesMut::new(),
19        }
20    }
21
22    /// Build a `Buffer` from a slice (copies).
23    pub fn from_slice(data: &[u8]) -> Self {
24        let mut b = Self::new();
25        b.extend_from_slice(data);
26        b
27    }
28
29    /// Number of bytes in the buffer.
30    pub fn len(&self) -> usize {
31        self.inner.len()
32    }
33
34    /// Resize the buffer in-place to `new_size` (filling with zeros if growing).
35    pub fn resize(&mut self, new_size: usize) {
36        self.inner.resize(new_size, 0u8);
37    }
38
39    /// Append a slice.
40    pub fn extend_from_slice(&mut self, bytes: &[u8]) {
41        self.inner.extend_from_slice(bytes);
42    }
43
44    /// Append bytes from another `Buffer`.
45    pub fn extend(&mut self, other: &Buffer) {
46        self.inner.extend(other.as_ref());
47    }
48
49    /// Drop the first `cnt` bytes, keeping the rest.
50    pub fn advance(&mut self, cnt: usize) {
51        self.inner.advance(cnt);
52    }
53
54    /// Returns `true` if the buffer is empty.
55    pub fn is_empty(&self) -> bool {
56        self.inner.is_empty()
57    }
58
59    /// Freeze into an immutable `Bytes`. Zero-copy — transfers ownership of
60    /// the underlying allocation.
61    pub fn freeze(self) -> Bytes {
62        Bytes {
63            inner: self.inner.freeze(),
64        }
65    }
66}
67
68impl AsMut<[u8]> for Buffer {
69    fn as_mut(&mut self) -> &mut [u8] {
70        self.inner.as_mut()
71    }
72}
73
74impl AsRef<[u8]> for Buffer {
75    fn as_ref(&self) -> &[u8] {
76        self.inner.as_ref()
77    }
78}
79
80/// Immutable, cheaply cloneable byte container. .
81#[derive(Debug, Clone, Default)]
82pub struct Bytes {
83    inner: bytes::Bytes,
84}
85
86impl Bytes {
87    /// Build from a slice (copies).
88    pub fn from_slice(data: &[u8]) -> Self {
89        Self {
90            inner: bytes::Bytes::copy_from_slice(data),
91        }
92    }
93
94    /// Number of bytes.
95    pub fn len(&self) -> usize {
96        self.inner.len()
97    }
98
99    /// Returns `true` if empty.
100    pub fn is_empty(&self) -> bool {
101        self.inner.is_empty()
102    }
103
104    /// Consume into the underlying `bytes::Bytes`. For interop with crates
105    /// that speak the `bytes` API natively.
106    #[cfg(feature = "quic")]
107    pub(crate) fn into_inner(self) -> bytes::Bytes {
108        self.inner
109    }
110
111    /// Wrap an existing `bytes::Bytes` without copying.
112    #[cfg(feature = "quic")]
113    pub(crate) fn from_inner(inner: bytes::Bytes) -> Self {
114        Self { inner }
115    }
116}
117
118impl AsRef<[u8]> for Bytes {
119    fn as_ref(&self) -> &[u8] {
120        self.inner.as_ref()
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[test]
129    fn test_buffer() {
130        let mut buf = Buffer::new();
131        assert_eq!(&[] as &[u8], buf.as_ref());
132        assert_eq!(0, buf.len());
133        assert!(buf.is_empty());
134
135        buf.extend_from_slice(&[1, 2, 3, 4, 5]);
136        assert_eq!(&[1, 2, 3, 4, 5], buf.as_ref());
137        assert_eq!(5, buf.len());
138
139        buf.advance(2);
140        assert_eq!(&[3, 4, 5], buf.as_ref());
141
142        buf.extend_from_slice(&[6, 7, 8]);
143        assert_eq!(&[3, 4, 5, 6, 7, 8], buf.as_ref());
144
145        buf.advance(4);
146        assert_eq!(&[7, 8], buf.as_ref());
147
148        buf.advance(2);
149        assert!(buf.is_empty());
150    }
151
152    #[test]
153    fn test_freeze_and_bytes() {
154        let mut buf = Buffer::new();
155        buf.extend_from_slice(b"hello");
156        let frozen = buf.freeze();
157        assert_eq!(frozen.as_ref(), b"hello");
158        assert_eq!(frozen.len(), 5);
159        assert!(!frozen.is_empty());
160
161        let b = Bytes::from_slice(b"world");
162        assert_eq!(b.as_ref(), b"world");
163    }
164}