#[derive(Debug)]
pub struct Stream<'a> {
buffer: &'a [u8],
name: &'a str,
offset: usize,
size: Option<usize>,
}
impl<'a> Stream<'a> {
pub fn new(name: &'a str, buffer: &'a [u8], offset: usize, size: Option<usize>) -> Self {
Stream {
buffer,
name,
offset,
size,
}
}
pub fn name(&'a self) -> &'a str {
self.name
}
pub fn buffer(&'a self) -> &'a [u8] {
self.buffer
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn size(&self) -> Option<usize> {
self.size
}
}
impl<'a> From<StreamMut<'a>> for Stream<'a> {
fn from(value: StreamMut<'a>) -> Self {
Stream::new(value.name, value.buffer, value.offset, value.size)
}
}
#[derive(Debug)]
pub struct StreamMut<'a> {
buffer: &'a mut [u8],
name: &'a str,
offset: usize,
size: Option<usize>,
}
impl<'a> StreamMut<'a> {
pub fn new<T: Copy>(name: &'a str, buffer: &'a mut [T]) -> Self {
let buffer = unsafe { std::slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut u8, std::mem::size_of_val(buffer)) };
StreamMut {
buffer,
name,
offset: 0,
size: None,
}
}
pub fn with_size(self, size: usize) -> Self {
StreamMut {
size: Some(size),
..self
}
}
pub fn buffer(&self) -> &'_ [u8] {
self.buffer
}
pub fn buffer_mut(&mut self) -> &'_ mut [u8] {
self.buffer
}
pub fn name(&self) -> &'_ str {
self.name
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn size(&self) -> Option<usize> {
self.size
}
}
#[cfg(test)]
mod tests {
use super::{Stream, StreamMut};
#[test]
fn immutable_stream_preserves_name_range_and_buffer() {
let bytes = [1u8, 2, 3, 4];
let stream = Stream::new("vertices", &bytes, 12, Some(3));
assert_eq!(stream.name(), "vertices");
assert_eq!(stream.buffer(), &bytes);
assert_eq!(stream.offset(), 12);
assert_eq!(stream.size(), Some(3));
}
#[test]
fn mutable_typed_stream_exposes_the_complete_object_representation() {
let mut words = [0x1122u16, 0x3344u16];
let expected = words;
{
let mut stream = StreamMut::new("indices", &mut words).with_size(3);
assert_eq!(stream.name(), "indices");
assert_eq!(stream.offset(), 0);
assert_eq!(stream.size(), Some(3));
assert_eq!(stream.buffer().len(), std::mem::size_of_val(&expected));
stream.buffer_mut().fill(0);
}
assert_eq!(words, [0, 0]);
}
#[test]
fn mutable_to_immutable_conversion_retains_metadata_and_storage() {
let mut bytes = [1u8, 2, 3];
let stream = Stream::from(StreamMut::new("payload", &mut bytes).with_size(2));
assert_eq!(stream.name(), "payload");
assert_eq!(stream.buffer(), &[1, 2, 3]);
assert_eq!(stream.offset(), 0);
assert_eq!(stream.size(), Some(2));
}
}