1use std::io;
2
3use crate::PropertyValueEnum;
4
5use super::property::Kind;
6use byteorder::{ReadBytesExt as _, WriteBytesExt as _, LE};
7use ltk_hash::{BinHash, ReadBytesExt as _, WriteBytesExt as _};
8
9const HEADER_SIZE: usize = 5;
10
11pub trait PropertyExt {
13 fn size(&self, include_header: bool) -> usize {
15 self.size_no_header()
16 + match include_header {
17 true => HEADER_SIZE,
18 false => 0,
19 }
20 }
21 fn size_no_header(&self) -> usize;
22}
23
24pub trait PropertyValueExt {
25 const KIND: Kind;
26}
27
28pub trait PropertyValueDyn: PropertyExt {
29 fn kind(&self) -> Kind;
30}
31
32impl<T: PropertyValueExt + PropertyExt> PropertyValueDyn for T {
33 fn kind(&self) -> Kind {
34 Self::KIND
35 }
36}
37
38pub trait ReadProperty: Sized {
40 fn from_reader<R: io::Read + io::Seek + ?Sized>(
41 reader: &mut R,
42 legacy: bool,
43 ) -> Result<Self, crate::Error>;
44}
45
46pub trait ReaderExt: io::Read {
48 fn read_property_kind(&mut self, legacy: bool) -> Result<Kind, crate::Error> {
50 Kind::unpack(self.read_u8()?, legacy)
51 }
52
53 fn read_property(&mut self, legacy: bool) -> Result<(BinHash, PropertyValueEnum), crate::Error>
54 where
55 Self: io::Seek,
56 {
57 let name_hash = self.read_bin_hash::<LE>()?;
58 let kind = self.read_property_kind(legacy)?;
59
60 Ok((
61 name_hash,
62 PropertyValueEnum::from_reader(self, kind, legacy)?,
63 ))
64 }
65}
66
67impl<R: io::Read + ?Sized> ReaderExt for R {}
68
69pub trait WriteProperty: Sized {
71 fn to_writer<R: io::Write + io::Seek + ?Sized>(
72 &self,
73 writer: &mut R,
74 legacy: bool,
75 ) -> Result<(), io::Error>;
76}
77
78pub trait WriterExt: io::Write {
80 fn write_property_kind(&mut self, kind: Kind) -> Result<(), io::Error> {
81 self.write_u8(kind.into())
82 }
83
84 fn write_property(
85 &mut self,
86 name_hash: BinHash,
87 value: &PropertyValueEnum,
88 ) -> Result<(), io::Error>
89 where
90 Self: io::Seek,
91 {
92 self.write_bin_hash::<LE>(name_hash)?;
93 self.write_property_kind(value.kind())?;
94 value.to_writer(self)?;
95 Ok(())
96 }
97}
98
99impl<R: io::Write + ?Sized> WriterExt for R {}