use crate::base::{RUMResult, RUMVec};
use crate::buffers::buffer_to_str;
use crate::mem::{as_slice_mut, copy_from_slice, AsPtr, AsSlice, SizedType};
use rumtk_arena::dune::Dune;
use rumtk_arena::rumtk_dune_new;
use std::cmp::PartialEq;
use std::mem;
use std::ops::DerefMut;
use std::ops::{Deref, RangeTo, RangeToInclusive};
use std::ops::{Index, Range, RangeFull};
use std::sync::LazyLock;
#[derive(Default, Debug, Clone)]
enum RUMBufferDataPtr {
StaticBuffer(&'static [u8]),
String(String),
Vec(RUMVec<u8>),
Arena(Dune),
#[default]
None
}
impl PartialEq for RUMBufferDataPtr {
fn eq(&self, other: &Self) -> bool {
mem::discriminant(self) == mem::discriminant(other)
}
}
pub type RUMBufferInner = RUMBufferDataPtr;
const EMPTY_BUFFER_DATA: [u8;0] = [0;0];
static EMPTY_RUMBUFFER: LazyLock<RUMBuffer> = LazyLock::new(|| RUMBuffer::new());
#[derive(Debug)]
pub struct RUMBuffer {
data: RUMBufferInner,
ptr: *const u8,
size: usize,
}
impl RUMBuffer {
#[inline]
pub const fn new() -> Self {
let data_length = 0;
let ptr = EMPTY_BUFFER_DATA.as_ptr();
Self {
data: RUMBufferDataPtr::None,
ptr,
size: data_length,
}
}
#[inline]
pub fn from_slice(data: &[u8]) -> Self {
if data.is_empty() {
return Self::new();
}
let data_length = data.len();
let mut mem = rumtk_dune_new!(data_length);
let mut ptr = mem.allocate_raw(data_length).unwrap();
let dst = as_slice_mut(ptr, data_length);
copy_from_slice(&data[..], dst);
Self {
data: RUMBufferDataPtr::Arena(mem),
ptr,
size: data_length,
}
}
#[inline]
pub fn from_vec(mut data: Vec<u8>) -> Self {
let mut ptr = data.as_mut_ptr();
let size = data.len();
Self {
data: RUMBufferDataPtr::Vec(data),
ptr,
size,
}
}
#[inline]
pub fn from_string(mut data: String) -> Self {
let mut ptr = data.as_mut_ptr();
let size = data.len();
Self {
data: RUMBufferDataPtr::String(data),
ptr,
size,
}
}
#[inline]
pub fn from_static(mut data: &'static [u8]) -> Self {
let mut ptr = data.as_mut_ptr();
let size = data.len();
Self {
data: RUMBufferDataPtr::StaticBuffer(data),
ptr,
size,
}
}
#[inline]
pub fn split_to(&mut self, offset: usize) -> Self {
debug_assert!(offset <= self.size, "offset too large");
let copy = Self {
data: RUMBufferDataPtr::None,
ptr: self.ptr,
size: offset,
};
self.ptr = unsafe { self.ptr.add(offset) };
self.size -= offset;
copy
}
#[inline]
pub fn freeze(&self) -> Self {
Self {
data: RUMBufferDataPtr::None,
ptr: self.ptr,
size: self.size,
}
}
#[inline]
pub fn to_vec(&self) -> RUMVec<u8> {
self.as_slice().to_vec()
}
#[inline]
pub fn as_str(&self) -> RUMResult<&str> {
buffer_to_str(self)
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.size = len;
}
#[inline]
pub fn is_empty(&self) -> bool {
self.size == 0
}
#[inline]
pub fn is_buffer(&self) -> bool {
!self.is_view()
}
#[inline]
pub fn is_view(&self) -> bool {
self.data == RUMBufferDataPtr::None
}
}
impl Iterator for RUMBuffer {
type Item = u8;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.size == 0 { return None };
let v = self[0];
self.ptr = unsafe { self.ptr.add(1) };
Some(v)
}
}
impl SizedType for RUMBuffer {
fn size(&self) -> usize {
self.size
}
}
impl AsPtr for RUMBuffer {
#[inline(always)]
fn as_ptr(&self) -> *const u8 {
self.ptr
}
#[inline(always)]
fn as_mut_ptr(&mut self) -> *mut u8 {
self.ptr as *mut u8
}
}
impl AsSlice for RUMBuffer { }
impl AsRef<[u8]> for RUMBuffer {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl Deref for RUMBuffer {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for RUMBuffer {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
self.as_slice_mut()
}
}
impl PartialEq for RUMBuffer {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl Default for RUMBuffer {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl Clone for RUMBuffer {
#[inline]
fn clone(&self) -> Self {
self.freeze()
}
}
unsafe impl Send for RUMBuffer {}
unsafe impl Sync for RUMBuffer {}
impl Index<usize> for RUMBuffer {
type Output = u8;
#[inline]
fn index(&self, i: usize) -> &Self::Output {
&self.as_slice()[i]
}
}
impl Index<Range<usize>> for RUMBuffer {
type Output = [u8];
#[inline]
fn index(&self, i: Range<usize>) -> &Self::Output {
&self.as_slice()[i.start..i.end]
}
}
impl Index<RangeTo<usize>> for RUMBuffer {
type Output = [u8];
#[inline]
fn index(&self, i: RangeTo<usize>) -> &Self::Output {
&self.as_slice()[..i.end]
}
}
impl Index<RangeToInclusive<usize>> for RUMBuffer {
type Output = [u8];
#[inline]
fn index(&self, i: RangeToInclusive<usize>) -> &Self::Output {
&self.as_slice()[..=i.end]
}
}
impl Index<RangeFull> for RUMBuffer {
type Output = [u8];
#[inline]
fn index(&self, i: RangeFull) -> &Self::Output {
self.as_slice()
}
}
impl From<String> for RUMBuffer {
#[inline]
fn from(data: String) -> Self {
Self::from_string(data)
}
}
impl From<Vec<u8>> for RUMBuffer {
#[inline]
fn from(data: Vec<u8>) -> Self {
Self::from_vec(data)
}
}
impl From<&RUMVec<u8>> for RUMBuffer {
#[inline]
fn from(data: &RUMVec<u8>) -> Self {
Self::from_slice(data.as_slice())
}
}
impl From<&[u8]> for RUMBuffer {
#[inline]
fn from(data: &[u8]) -> Self {
Self::from_slice(data)
}
}
impl<const N: usize> From<&[u8; N]> for RUMBuffer {
#[inline]
fn from(data: &[u8; N]) -> Self {
Self::from(data.as_slice())
}
}
impl From<&str> for RUMBuffer {
#[inline]
fn from(data: &str) -> Self {
Self::from(data.as_bytes())
}
}