#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CopyBuffer {
data: Vec<u8>,
capacity: usize,
}
#[allow(dead_code)]
impl CopyBuffer {
pub fn new(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity),
capacity,
}
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn remaining(&self) -> usize {
self.capacity.saturating_sub(self.data.len())
}
pub fn copy_in(&mut self, src: &[u8]) -> usize {
let avail = self.remaining();
let n = src.len().min(avail);
self.data.extend_from_slice(&src[..n]);
n
}
pub fn copy_out(&mut self, n: usize) -> Vec<u8> {
let take = n.min(self.data.len());
let out: Vec<u8> = self.data.drain(..take).collect();
out
}
pub fn peek(&self, n: usize) -> &[u8] {
let take = n.min(self.data.len());
&self.data[..take]
}
pub fn clear(&mut self) {
self.data.clear();
}
pub fn as_slice(&self) -> &[u8] {
&self.data
}
pub fn is_full(&self) -> bool {
self.data.len() >= self.capacity
}
pub fn fill(&mut self, byte: u8) {
let n = self.remaining();
for _ in 0..n {
self.data.push(byte);
}
}
pub fn set_byte(&mut self, pos: usize, byte: u8) -> bool {
if pos < self.data.len() {
self.data[pos] = byte;
true
} else {
false
}
}
pub fn get_byte(&self, pos: usize) -> Option<u8> {
self.data.get(pos).copied()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_empty() {
let buf = CopyBuffer::new(64);
assert!(buf.is_empty());
assert_eq!(buf.capacity(), 64);
assert_eq!(buf.remaining(), 64);
}
#[test]
fn copy_in_basic() {
let mut buf = CopyBuffer::new(8);
let n = buf.copy_in(&[1, 2, 3, 4]);
assert_eq!(n, 4);
assert_eq!(buf.len(), 4);
}
#[test]
fn copy_in_clamped_to_capacity() {
let mut buf = CopyBuffer::new(4);
let n = buf.copy_in(&[0u8; 10]);
assert_eq!(n, 4);
assert!(buf.is_full());
}
#[test]
fn copy_out_removes_front() {
let mut buf = CopyBuffer::new(16);
buf.copy_in(&[10, 20, 30, 40]);
let out = buf.copy_out(2);
assert_eq!(out, vec![10, 20]);
assert_eq!(buf.len(), 2);
}
#[test]
fn peek_does_not_consume() {
let mut buf = CopyBuffer::new(16);
buf.copy_in(&[1, 2, 3]);
let peeked = buf.peek(2);
assert_eq!(peeked, &[1, 2]);
assert_eq!(buf.len(), 3);
}
#[test]
fn fill_to_capacity() {
let mut buf = CopyBuffer::new(4);
buf.fill(0xFF);
assert!(buf.is_full());
assert_eq!(buf.as_slice(), &[0xFF, 0xFF, 0xFF, 0xFF]);
}
#[test]
fn set_and_get_byte() {
let mut buf = CopyBuffer::new(8);
buf.copy_in(&[0u8; 4]);
assert!(buf.set_byte(2, 99));
assert_eq!(buf.get_byte(2), Some(99));
assert!(!buf.set_byte(100, 0));
}
#[test]
fn clear_resets() {
let mut buf = CopyBuffer::new(8);
buf.copy_in(&[1, 2, 3]);
buf.clear();
assert!(buf.is_empty());
assert_eq!(buf.remaining(), 8);
}
#[test]
fn remaining_decreases() {
let mut buf = CopyBuffer::new(10);
buf.copy_in(&[0u8; 7]);
assert_eq!(buf.remaining(), 3);
}
#[test]
fn copy_out_partial_when_short() {
let mut buf = CopyBuffer::new(8);
buf.copy_in(&[5, 6]);
let out = buf.copy_out(10);
assert_eq!(out, vec![5, 6]);
assert!(buf.is_empty());
}
}