Skip to main content

ltk_meta/
traits.rs

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
11/// General methods for property values
12pub trait PropertyExt {
13    /// Get the size of the property value, including the kind header if specified
14    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
38/// Methods for reading properties
39pub 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
46/// Extension trait for reading property kinds
47pub trait ReaderExt: io::Read {
48    /// Reads a u8 as a property kind
49    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
69/// Methods for writing properties
70pub 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
78/// Extension trait for writing property kinds
79pub 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 {}