use crate::archive::Struct;
use crate::memory;
use std::fmt;
use std::marker;
pub struct StructBuf<T>
where
T: for<'a> Struct<'a>,
{
data: Vec<u8>,
_phantom: marker::PhantomData<T>,
}
impl<T> StructBuf<T>
where
T: for<'a> Struct<'a>,
{
pub fn new() -> Self {
let data = vec![0; <T as Struct>::SIZE_IN_BYTES + memory::PADDING_SIZE];
Self {
data,
_phantom: marker::PhantomData,
}
}
pub fn get(&self) -> <T as Struct>::Item {
<T as Struct>::create(&self.data)
}
pub fn get_mut(&mut self) -> <T as Struct>::ItemMut {
<T as Struct>::create_mut(&mut self.data)
}
pub fn as_bytes(&self) -> &[u8] {
&self.data[0..<T as Struct>::SIZE_IN_BYTES]
}
}
impl<T> fmt::Debug for StructBuf<T>
where
T: for<'a> Struct<'a>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "StructBuf {{ resource: {:?} }}", self.get())
}
}
impl<T> Default for StructBuf<T>
where
T: for<'a> Struct<'a>,
{
fn default() -> Self {
Self::new()
}
}
impl<T> AsRef<[u8]> for StructBuf<T>
where
T: for<'a> Struct<'a>,
{
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
#[cfg(test)]
#[allow(dead_code)]
mod test {
use super::*;
define_struct!(
A,
RefA,
RefMutA,
"no_schema",
4,
(x, set_x, u32, 0, 16),
(y, set_y, u32, 16, 16)
);
#[test]
fn test_new() {
let a = StructBuf::<A>::new();
let b = StructBuf::<A>::default();
assert_eq!(a.get(), b.get());
}
#[test]
fn test_setter_getter() {
let mut a = StructBuf::<A>::new();
a.get_mut().set_x(1);
a.get_mut().set_y(2);
assert_eq!(a.get().x(), 1);
assert_eq!(a.get().y(), 2);
a.get_mut().set_x(3);
assert_eq!(a.get().x(), 3);
assert_eq!(a.get().y(), 2);
a.get_mut().set_y(4);
assert_eq!(a.get().x(), 3);
assert_eq!(a.get().y(), 4);
let a_ref = a.get();
assert_eq!(a_ref.x(), 3);
assert_eq!(a_ref.y(), 4);
}
}