use std::cell::RefCell;
use crate::{ByteBuffer, Renderable};
pub struct BufferData<'a, R: Renderable> {
data: &'a [u8],
byte_offset: u32,
byte_length: u32,
rc_client: RefCell<R::Buffer>,
}
impl<'a, R: Renderable> std::fmt::Debug for BufferData<'a, R> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let (data, cont) = {
if self.data.len() < 8 {
(self.data, "")
} else {
(&self.data[0..8], "...")
}
};
write!(
fmt,
"BufferData {{{0:?}{cont}#{4}, byte_offset:{1}, byte_length:{2}, client:{3:?}}}",
data,
self.byte_offset,
self.byte_length,
self.rc_client,
self.data.len(),
)
}
}
impl<'a, R: Renderable> BufferData<'a, R> {
#[inline]
pub fn byte_length(&self) -> u32 {
self.byte_length
}
#[inline]
pub fn byte_offset(&self) -> u32 {
self.byte_offset
}
pub fn new<B: ByteBuffer + ?Sized>(data: &'a B, byte_offset: u32, byte_length: u32) -> Self {
let byte_length = {
if byte_length == 0 {
(data.byte_length() as u32) - byte_offset
} else {
byte_length
}
};
let rc_client = RefCell::new(R::Buffer::default());
let data = data.borrow_bytes();
assert!(
byte_offset + byte_length <= data.len() as u32,
"Buffer is not large enough for data {byte_offset} + #{byte_length} [ got {}]",
data.len()
);
Self {
data,
byte_offset,
byte_length,
rc_client,
}
}
pub fn create_client(&self, renderable: &mut R) {
use std::ops::DerefMut;
renderable.init_buffer_data_client(self.rc_client.borrow_mut().deref_mut(), self);
}
pub fn borrow_client(&self) -> std::cell::Ref<R::Buffer> {
self.rc_client.borrow()
}
}
impl<'a, R> AsRef<[u8]> for BufferData<'a, R>
where
R: Renderable,
{
fn as_ref(&self) -> &[u8] {
let start = self.byte_offset as usize;
let end = (self.byte_offset + self.byte_length) as usize;
&self.data[start..end]
}
}
impl<'a, R: Renderable> std::fmt::Display for BufferData<'a, R> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let data_ptr = self.data.as_ptr();
write!(
f,
"BufferData[{:?}+{}#{}]:",
data_ptr, self.byte_offset, self.byte_length,
)?;
use crate::BufferClient;
(*self.rc_client.borrow()).fmt(f)
}
}
impl<'a, R: Renderable> indent_display::DefaultIndentedDisplay for BufferData<'a, R> {}