use std::{
marker::PhantomData,
ops::{Index, IndexMut, Range, RangeFrom, RangeFull, RangeTo},
sync::Arc,
};
use crate::proxies::BufferProxy;
pub struct Buffer<T> {
pub(crate) inner: Arc<dyn BufferProxy>,
_t: PhantomData<T>,
}
impl<T> Buffer<T> {
pub(crate) fn new(proxy: Arc<dyn BufferProxy>) -> Self {
Self {
inner: proxy,
_t: PhantomData,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn len(&self) -> u64 {
self.inner.get_size() / size_of::<T>() as u64
}
}
impl<T> Index<u64> for Buffer<T> {
type Output = T;
#[inline]
fn index(&self, index: u64) -> &Self::Output {
let size = size_of::<T>() as u64;
let offset = index * size;
let bytes = self.inner.get_memory(offset..offset + size);
unsafe { &*((bytes.as_ptr()) as *const T) }
}
}
impl<T> IndexMut<u64> for Buffer<T> {
#[inline]
fn index_mut(&mut self, index: u64) -> &mut Self::Output {
let size = size_of::<T>() as u64;
let offset = index * size;
let bytes = self.inner.get_memory(offset..offset + size);
unsafe { &mut *((bytes.as_ptr()) as *mut T) }
}
}
impl<T> Index<Range<u64>> for Buffer<T> {
type Output = [T];
#[inline]
fn index(&self, range: Range<u64>) -> &Self::Output {
let bytes = self
.inner
.get_memory(range.start * size_of::<T>() as u64..range.end * size_of::<T>() as u64);
let len = (range.end - range.start) as usize;
unsafe { std::slice::from_raw_parts(bytes.as_ptr() as *const T, len) }
}
}
impl<T> IndexMut<Range<u64>> for Buffer<T> {
#[inline]
fn index_mut(&mut self, range: Range<u64>) -> &mut Self::Output {
let bytes = self
.inner
.get_memory(range.start * size_of::<T>() as u64..range.end * size_of::<T>() as u64);
let len = (range.end - range.start) as usize;
unsafe { std::slice::from_raw_parts_mut(bytes.as_ptr() as *mut T, len) }
}
}
impl<T> Index<RangeFull> for Buffer<T> {
type Output = [T];
#[inline]
fn index(&self, _index: RangeFull) -> &Self::Output {
&self[0..self.len()]
}
}
impl<T> IndexMut<RangeFull> for Buffer<T> {
#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output {
let size = self.len();
&mut self[0..size]
}
}
impl<T> Index<RangeTo<u64>> for Buffer<T> {
type Output = [T];
#[inline]
fn index(&self, range: RangeTo<u64>) -> &Self::Output {
&self[0..range.end]
}
}
impl<T> IndexMut<RangeTo<u64>> for Buffer<T> {
#[inline]
fn index_mut(&mut self, range: RangeTo<u64>) -> &mut Self::Output {
&mut self[0..range.end]
}
}
impl<T> Index<RangeFrom<u64>> for Buffer<T> {
type Output = [T];
#[inline]
fn index(&self, range: RangeFrom<u64>) -> &Self::Output {
&self[range.start..self.len()]
}
}
impl<T> IndexMut<RangeFrom<u64>> for Buffer<T> {
#[inline]
fn index_mut(&mut self, range: RangeFrom<u64>) -> &mut Self::Output {
let size = self.len();
&mut self[range.start..size]
}
}