1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/// FIFO buffer
///
/// This implements a simple FIFO buffer which can be useful when managing data to/from Anchor
/// protocol handling. Using this is completely optional, it is provided as a convenience.
pub struct FifoBuffer<const BUF_SIZE: usize> {
buffer: [u8; BUF_SIZE],
used: usize,
}
impl<const BUF_SIZE: usize> FifoBuffer<BUF_SIZE> {
/// Creates a new buffer
///
/// This is declared const, allowing it to be used even in `static const` contexts.
pub const fn new() -> Self {
FifoBuffer {
buffer: [0u8; BUF_SIZE],
used: 0,
}
}
/// Checks for buffer emptiness
pub fn is_empty(&self) -> bool {
self.used == 0
}
/// Return length of currently stored buffer
pub fn len(&self) -> usize {
self.used
}
/// Return mutable slice to the non-filled part of the buffer
pub fn receive_buffer(&mut self) -> &mut [u8] {
&mut self.buffer[self.used..]
}
/// Append `buf` to the non-filled part of the buffer
///
/// Any excess will be discarded.
pub fn extend(&mut self, buf: &[u8]) {
let into = self.receive_buffer();
if into.len() < buf.len() {
// Drop if we'd overrun
return;
}
into[..buf.len()].copy_from_slice(buf);
self.used += buf.len();
}
/// Moves the used cursor forward
///
/// This can be used after filling part of the non-filled buffer returned by `receive_buffer`.
pub fn advance(&mut self, n: usize) {
self.used = (self.used + n).clamp(0, self.buffer.len());
}
/// Returns the filled part of the buffer
pub fn data(&self) -> &[u8] {
&self.buffer[0..self.used]
}
/// Removes `n` bytes from the front of the buffer
///
/// This operation moves the used part of the buffer down in memory. This is linear in the
/// number of bytes currently stored.
pub fn pop(&mut self, n: usize) {
let n = n.clamp(0, self.used);
let remain = n..self.used;
let len = remain.len();
self.buffer.copy_within(remain, 0);
self.used = len;
}
}