use std::io;
use crate::PropertyValueEnum;
use super::property::Kind;
use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE};
use ltk_hash::{BinHash, ReadBytesExt as _, WriteBytesExt as _};
const HEADER_SIZE: usize = 5;
pub trait PropertyExt {
fn size(&self, include_header: bool) -> usize {
self.size_no_header()
+ match include_header {
true => HEADER_SIZE,
false => 0,
}
}
fn size_no_header(&self) -> usize;
}
pub trait PropertyValueExt {
const KIND: Kind;
}
pub trait PropertyValueDyn: PropertyExt {
fn kind(&self) -> Kind;
}
impl<T: PropertyValueExt + PropertyExt> PropertyValueDyn for T {
fn kind(&self) -> Kind {
Self::KIND
}
}
pub trait ReadProperty: Sized {
fn from_reader<R: io::Read + io::Seek + ?Sized>(
reader: &mut R,
legacy: bool,
) -> Result<Self, crate::Error>;
}
pub trait ReaderExt: io::Read {
fn read_property_kind(&mut self, legacy: bool) -> Result<Kind, crate::Error> {
Kind::unpack(self.read_u8()?, legacy)
}
fn read_property(&mut self, legacy: bool) -> Result<(BinHash, PropertyValueEnum), crate::Error>
where
Self: io::Seek,
{
let name_hash = self.read_bin_hash::<LE>()?;
let kind = self.read_property_kind(legacy)?;
Ok((
name_hash,
PropertyValueEnum::from_reader(self, kind, legacy)?,
))
}
}
impl<R: io::Read + ?Sized> ReaderExt for R {}
pub trait WriteProperty: Sized {
fn to_writer<R: io::Write + io::Seek + ?Sized>(
&self,
writer: &mut R,
legacy: bool,
) -> Result<(), io::Error>;
}
pub trait WriterExt: io::Write {
fn write_property_kind(&mut self, kind: Kind) -> Result<(), io::Error> {
self.write_u8(kind.into())
}
fn write_property(
&mut self,
name_hash: BinHash,
value: &PropertyValueEnum,
) -> Result<(), io::Error>
where
Self: io::Seek,
{
self.write_bin_hash::<LE>(name_hash)?;
self.write_property_kind(value.kind())?;
value.to_writer(self)?;
Ok(())
}
}
impl<R: io::Write + ?Sized> WriterExt for R {}