use binrw::io::SeekFrom;
use binrw::{
helpers::{read_u24, write_u24},
prelude::*,
};
use std::{convert::TryFrom, fmt::Debug};
pub struct PosMarker3Byte {
pub pos: core::cell::Cell<u64>,
pub value: u32,
}
impl BinRead for PosMarker3Byte {
type Args<'a> = ();
fn read_options<R: binrw::io::Read + binrw::io::Seek>(
reader: &mut R,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> BinResult<Self> {
let pos = reader.stream_position()?;
read_u24(reader, endian, args).map(|value| Self {
pos: core::cell::Cell::new(pos),
value,
})
}
}
impl BinWrite for PosMarker3Byte {
type Args<'a> = ();
fn write_options<W: binrw::io::Write + binrw::io::Seek>(
&self,
writer: &mut W,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> BinResult<()> {
self.pos.set(writer.stream_position()?);
write_u24(&u32::default(), writer, endian, args)
}
}
impl PosMarker3Byte {
#[binrw::writer(writer, endian)]
pub fn write_and_fill_size<U>(value: &U, this: &Self) -> BinResult<()>
where
U: BinWrite<Args<'static> = ()>,
{
let begin_offset = writer.stream_position()?;
value.write_options(writer, endian, ())?;
let end_offset = writer.stream_position()?;
let size_written = end_offset - begin_offset;
let written_bytes_value =
u32::try_from(size_written).map_err(|err| binrw::error::Error::Custom {
pos: begin_offset,
err: Box::new(err),
})?;
writer.seek(SeekFrom::Start(this.pos.get()))?;
write_u24(&written_bytes_value, writer, endian, ())?;
writer.seek(SeekFrom::End(0))?;
Ok(())
}
}
impl Debug for PosMarker3Byte {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PosMarker3Byte")
.field("pos", &self.pos)
.field("value", &self.value)
.finish()
}
}
impl Default for PosMarker3Byte {
fn default() -> Self {
Self {
pos: core::cell::Cell::new(0),
value: u32::default(),
}
}
}
impl From<u32> for PosMarker3Byte {
fn from(value: u32) -> Self {
Self {
pos: core::cell::Cell::new(0),
value,
}
}
}