pub struct SatbBuffer {
buffer: Vec<*mut u8>,
capacity: usize,
}
unsafe impl Send for SatbBuffer {}
impl SatbBuffer {
pub fn new(capacity: usize) -> Self {
Self {
buffer: Vec::with_capacity(capacity),
capacity,
}
}
#[inline(always)]
pub fn enqueue(&mut self, old_ref: *mut u8) {
if !old_ref.is_null() {
self.buffer.push(old_ref);
}
}
pub fn drain(&mut self) -> Vec<*mut u8> {
std::mem::take(&mut self.buffer)
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub fn len(&self) -> usize {
self.buffer.len()
}
#[inline(always)]
pub fn should_flush(&self) -> bool {
self.buffer.len() >= self.capacity
}
}
impl Default for SatbBuffer {
fn default() -> Self {
Self::new(256)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_buffer_is_empty() {
let buf = SatbBuffer::new(64);
assert!(buf.is_empty());
assert_eq!(buf.len(), 0);
}
#[test]
fn test_enqueue_and_drain() {
let mut buf = SatbBuffer::new(64);
let a = 0x1000 as *mut u8;
let b = 0x2000 as *mut u8;
buf.enqueue(a);
buf.enqueue(b);
assert_eq!(buf.len(), 2);
assert!(!buf.is_empty());
let drained = buf.drain();
assert_eq!(drained.len(), 2);
assert_eq!(drained[0], a);
assert_eq!(drained[1], b);
assert!(buf.is_empty());
}
#[test]
fn test_null_enqueue_ignored() {
let mut buf = SatbBuffer::new(64);
buf.enqueue(std::ptr::null_mut());
assert!(buf.is_empty());
}
#[test]
fn test_should_flush() {
let mut buf = SatbBuffer::new(2);
assert!(!buf.should_flush());
buf.enqueue(0x1000 as *mut u8);
assert!(!buf.should_flush());
buf.enqueue(0x2000 as *mut u8);
assert!(buf.should_flush());
}
#[test]
fn test_drain_resets_buffer() {
let mut buf = SatbBuffer::new(64);
buf.enqueue(0x1000 as *mut u8);
buf.enqueue(0x2000 as *mut u8);
let _ = buf.drain();
assert!(buf.is_empty());
assert_eq!(buf.len(), 0);
buf.enqueue(0x3000 as *mut u8);
assert_eq!(buf.len(), 1);
}
}