use std::io::{self, Write};
use std::mem::size_of;
use bytemuck::bytes_of;
use crate::internal::align_offset;
use crate::std140::{AsStd140, Std140, WriteStd140};
pub struct Writer<W> {
writer: W,
offset: usize,
}
impl<W: Write> Writer<W> {
pub fn new(writer: W) -> Self {
Self { writer, offset: 0 }
}
pub fn write<T>(&mut self, value: &T) -> io::Result<usize>
where
T: WriteStd140 + ?Sized,
{
value.write_std140(self)
}
pub fn write_iter<I, T>(&mut self, iter: I) -> io::Result<usize>
where
I: IntoIterator<Item = T>,
T: WriteStd140,
{
let mut offset = self.offset;
let mut iter = iter.into_iter();
if let Some(item) = iter.next() {
offset = item.write_std140(self)?;
}
for item in iter {
item.write_std140(self)?;
}
Ok(offset)
}
pub fn write_std140<T>(&mut self, value: &T) -> io::Result<usize>
where
T: Std140,
{
let padding = align_offset(self.offset, T::ALIGNMENT);
for _ in 0..padding {
self.writer.write_all(&[0])?;
}
self.offset += padding;
let value = value.as_std140();
self.writer.write_all(bytes_of(&value))?;
let write_here = self.offset;
self.offset += size_of::<T>();
Ok(write_here)
}
#[deprecated(
since = "0.6.0",
note = "Use `write` instead -- it now works on slices."
)]
pub fn write_slice<T>(&mut self, slice: &[T]) -> io::Result<usize>
where
T: AsStd140,
{
self.write(slice)
}
pub fn len(&self) -> usize {
self.offset
}
}