pkts_common/
lib.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// Copyright (c) 2024 Nathaniel Bennett <me[at]nathanielbennett[dotcom]>
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#![forbid(unsafe_code)]
12
13use std::array;
14use std::ops::{Index, Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
15
16#[derive(Clone, Debug)]
17pub struct Buffer<T: Copy, const N: usize> {
18    buf: [T; N],
19    buf_len: usize,
20}
21
22impl<T: Copy + Default, const N: usize> Buffer<T, N> {
23    #[inline]
24    pub fn new() -> Self {
25        Self::default()
26    }
27}
28
29impl<T: Copy, const N: usize> Buffer<T, N> {
30    #[inline]
31    pub fn as_slice(&self) -> &[T] {
32        &self.buf[..self.buf_len]
33    }
34
35    #[inline]
36    pub fn as_mut_slice(&mut self) -> &mut [T] {
37        &mut self.buf[..self.buf_len]
38    }
39
40    /// Appends the provided bytes to the buffer, panicking if insufficient space is available in
41    /// the buffer.
42    #[inline]
43    pub fn append(&mut self, slice: &[T]) {
44        self.buf[self.buf_len..self.buf_len + slice.len()].copy_from_slice(slice);
45        self.buf_len += slice.len();
46    }
47
48    /// Truncates the buffer to the specified position.
49    pub fn truncate(&mut self, pos: usize) {
50        assert!(self.buf_len >= pos);
51        self.buf_len = pos;
52    }
53
54    #[inline]
55    pub fn into_parts(self) -> ([T; N], usize) {
56        (self.buf, self.buf_len)
57    }
58
59    /// The length of the stored buffer.
60    #[inline]
61    pub fn len(&self) -> usize {
62        self.buf_len
63    }
64
65    #[inline]
66    pub fn is_empty(&self) -> bool {
67        self.buf_len == 0
68    }
69
70    /// The number of unused bytes in the buffer.
71    #[inline]
72    pub fn remaining(&self) -> usize {
73        N - self.buf_len
74    }
75}
76
77impl<T: Copy + Default, const N: usize> Default for Buffer<T, N> {
78    #[inline]
79    fn default() -> Self {
80        Self {
81            buf: array::from_fn(|_| T::default()),
82            buf_len: 0,
83        }
84    }
85}
86
87impl<T: Copy, const N: usize> Index<usize> for Buffer<T, N> {
88    type Output = T;
89
90    #[inline]
91    fn index(&self, index: usize) -> &Self::Output {
92        self.as_slice().index(index)
93    }
94}
95
96impl<T: Copy, const N: usize> Index<Range<usize>> for Buffer<T, N> {
97    type Output = [T];
98
99    #[inline]
100    fn index(&self, index: Range<usize>) -> &Self::Output {
101        self.as_slice().index(index)
102    }
103}
104
105impl<T: Copy, const N: usize> Index<RangeFrom<usize>> for Buffer<T, N> {
106    type Output = [T];
107
108    #[inline]
109    fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
110        self.as_slice().index(index)
111    }
112}
113
114impl<T: Copy, const N: usize> Index<RangeInclusive<usize>> for Buffer<T, N> {
115    type Output = [T];
116
117    #[inline]
118    fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
119        self.as_slice().index(index)
120    }
121}
122
123impl<T: Copy, const N: usize> Index<RangeTo<usize>> for Buffer<T, N> {
124    type Output = [T];
125
126    #[inline]
127    fn index(&self, index: RangeTo<usize>) -> &Self::Output {
128        self.as_slice().index(index)
129    }
130}
131
132impl<T: Copy, const N: usize> Index<RangeToInclusive<usize>> for Buffer<T, N> {
133    type Output = [T];
134
135    #[inline]
136    fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
137        self.as_slice().index(index)
138    }
139}
140
141#[derive(Debug)]
142pub struct BufferMut<'a> {
143    buf: &'a mut [u8],
144    buf_len: usize,
145}
146
147impl<'a> BufferMut<'a> {
148    #[inline]
149    pub fn new(slice: &'a mut [u8]) -> Self {
150        Self {
151            buf: slice,
152            buf_len: 0,
153        }
154    }
155
156    #[inline]
157    pub fn as_slice(&self) -> &[u8] {
158        &self.buf[..self.buf_len]
159    }
160
161    #[inline]
162    pub fn as_mut_slice(&mut self) -> &mut [u8] {
163        &mut self.buf[..self.buf_len]
164    }
165
166    /// Appends the provided bytes to the buffer, panicking if insufficient space is available in
167    /// the buffer.
168    #[inline]
169    pub fn append(&mut self, bytes: &[u8]) {
170        self.buf[self.buf_len..self.buf_len + bytes.len()].copy_from_slice(bytes);
171        self.buf_len += bytes.len();
172    }
173
174    /// Appends the provided bytes to the buffer, returning `error` if insufficient space is
175    /// available in the buffer.
176    #[inline]
177    pub fn append_or<T>(&mut self, bytes: &[u8], error: T) -> Result<(), T> {
178        let buf_slice = self
179            .buf
180            .get_mut(self.buf_len..self.buf_len + bytes.len())
181            .ok_or(error)?;
182        buf_slice.copy_from_slice(bytes);
183        self.buf_len += bytes.len();
184        Ok(())
185    }
186
187    /// Appends the provided bytes to the buffer, panicking if insufficient space is available in
188    /// the buffer.
189    #[inline]
190    pub fn try_append(&mut self, bytes: &[u8]) -> Option<()> {
191        if self.remaining() < bytes.len() {
192            return None;
193        } else {
194            self.append(bytes);
195            return Some(());
196        }
197    }
198
199    /// Truncates the buffer to the specified position.
200    pub fn truncate(&mut self, pos: usize) {
201        assert!(self.buf_len >= pos);
202        self.buf_len = pos;
203    }
204
205    #[inline]
206    pub fn to_mut_slice(self) -> &'a mut [u8] {
207        &mut self.buf[..self.buf_len]
208    }
209
210    /// The length of the stored buffer.
211    #[inline]
212    pub fn len(&self) -> usize {
213        self.buf_len
214    }
215
216    #[inline]
217    pub fn is_empty(&self) -> bool {
218        self.buf_len == 0
219    }
220
221    /// The number of unused bytes in the buffer.
222    #[inline]
223    pub fn remaining(&self) -> usize {
224        self.buf.len() - self.buf_len
225    }
226}
227
228impl Index<usize> for BufferMut<'_> {
229    type Output = u8;
230
231    #[inline]
232    fn index(&self, index: usize) -> &Self::Output {
233        self.as_slice().index(index)
234    }
235}
236
237impl Index<Range<usize>> for BufferMut<'_> {
238    type Output = [u8];
239
240    #[inline]
241    fn index(&self, index: Range<usize>) -> &Self::Output {
242        self.as_slice().index(index)
243    }
244}
245
246impl Index<RangeFrom<usize>> for BufferMut<'_> {
247    type Output = [u8];
248
249    #[inline]
250    fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
251        self.as_slice().index(index)
252    }
253}
254
255impl Index<RangeInclusive<usize>> for BufferMut<'_> {
256    type Output = [u8];
257
258    #[inline]
259    fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
260        self.as_slice().index(index)
261    }
262}
263
264impl Index<RangeTo<usize>> for BufferMut<'_> {
265    type Output = [u8];
266
267    #[inline]
268    fn index(&self, index: RangeTo<usize>) -> &Self::Output {
269        self.as_slice().index(index)
270    }
271}
272
273impl Index<RangeToInclusive<usize>> for BufferMut<'_> {
274    type Output = [u8];
275
276    #[inline]
277    fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
278        self.as_slice().index(index)
279    }
280}