use std::cell::UnsafeCell;
pub(crate) struct SyncCell<T>(UnsafeCell<T>);
impl<T> SyncCell<T> {
pub(crate) const fn new(value: T) -> Self {
Self(UnsafeCell::new(value))
}
#[inline]
pub(crate) const fn get(&self) -> *mut T {
self.0.get()
}
}
unsafe impl<T> Sync for SyncCell<T> {}
const SIZE: usize = 2048;
pub(crate) struct Buffer {
data: [u8; SIZE],
}
impl std::io::Write for Buffer {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let len = std::cmp::min(buf.len(), self.len());
self.data[..len].copy_from_slice(&buf[..len]);
Ok(len)
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl Buffer {
const fn new() -> Buffer {
Self { data: [0u8; SIZE] }
}
#[inline]
pub(crate) fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub(crate) fn max_size(&self) -> usize {
SIZE
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut u8 {
self.data.as_mut_ptr()
}
pub(crate) fn as_slice(&self) -> &[u8] {
&self.data
}
pub(crate) fn as_subslice(&self, size: usize) -> &[u8] {
&self.data[0..size]
}
pub(crate) fn as_mut_subslice(&mut self, size: usize) -> &mut [u8] {
&mut self.data[0..size]
}
pub(crate) fn to_boxed_slice(&self, size: usize) -> Box<[u8]> {
Box::from(self.as_subslice(size))
}
pub(crate) fn append(&mut self, data: &[u8]) {
let copy_len = std::cmp::min(data.len(), SIZE);
let start = SIZE - copy_len;
self.data[start..].copy_from_slice(&data[..copy_len]);
}
#[cfg(test)]
pub(super) fn from_slice(data: &[u8]) -> Buffer {
let mut buffer = [0; SIZE];
buffer[..data.len()].clone_from_slice(data);
Self { data: buffer }
}
}
static BUFFER: SyncCell<Buffer> = SyncCell::new(Buffer::new());
pub(crate) fn buffer() -> &'static mut Buffer {
unsafe { &mut *BUFFER.get() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sync_cell_basic_usage() {
let cell = SyncCell::new(42);
let value = unsafe { &mut *cell.get() };
assert_eq!(*value, 42);
*value = 99;
assert_eq!(*value, 99);
}
#[test]
fn test_new_buffer() {
let buf = Buffer::new();
assert_eq!(buf.len(), SIZE);
assert!(buf.as_slice().iter().all(|&b| b == 0));
}
#[test]
fn test_as_slice() {
let c = b"test";
let buf = Buffer::from_slice(c);
let r = buf.as_subslice(c.len());
assert_eq!(c, r);
}
#[test]
fn test_as_slice_empty() {
let c = b"";
let buf = Buffer::from_slice(c);
let r = buf.as_subslice(c.len());
assert!(r.is_empty());
}
}