caff_archive/archive/
header.rs

1use crate::prelude::*;
2
3mod magic;
4mod preview_image;
5mod version;
6
7use crate::Padding;
8use magic::Magic;
9use preview_image::PreviewImage;
10use version::Version;
11
12#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(test, derive(Arbitrary))]
14pub struct Header {
15  #[cfg_attr(test, map(|magic: Magic| Magic::default()))]
16  pub archive_magic: Magic,
17  pub archive_version: Version,
18  pub format_identifier: [u8; 4],
19  pub format_version: Version,
20  pub key: Key,
21  unknown: Padding<8>,
22  pub preview_image: PreviewImage,
23  padding: Padding<12>,
24}
25
26impl Header {
27  pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Self> {
28    reader.trace(|reader| {
29      let archive_magic = Magic::read(reader)?;
30      let archive_version = Version::read(reader)?;
31      let mut format_identifier = [0u8; 4];
32      reader.read_exact(&mut format_identifier)?;
33      let format_version = Version::read(reader)?;
34      let key = Key::read(reader)?;
35      let unknown = Padding::read(reader)?;
36      let preview_image = PreviewImage::read(reader)?;
37      let padding = Padding::read(reader)?;
38
39      let value = Self {
40        archive_magic,
41        archive_version,
42        format_identifier,
43        format_version,
44        key,
45        unknown,
46        preview_image,
47        padding,
48      };
49
50      #[cfg(feature = "logging")]
51      log::debug!("read value={value:?}");
52
53      Ok(value)
54    })
55  }
56
57  pub fn write<W: Write + Seek>(&self, writer: &mut W) -> Result<()> {
58    writer.trace(|writer| {
59      let Self {
60        archive_magic,
61        archive_version,
62        format_identifier,
63        format_version,
64        key: obfuscate_key,
65        unknown,
66        preview_image,
67        padding,
68      } = self;
69
70      archive_magic.write(writer)?;
71      archive_version.write(writer)?;
72      writer.write_all(format_identifier)?;
73      format_version.write(writer)?;
74      obfuscate_key.write(writer)?;
75      unknown.write(writer)?;
76      preview_image.write(writer)?;
77      padding.write(writer)?;
78
79      Ok(())
80    })
81  }
82}
83
84#[cfg(test)]
85mod tests {
86  use super::*;
87  use test_strategy::proptest;
88
89  #[proptest]
90  fn roundtrip(expected: Header) {
91    let mut buffer = Cursor::new(Vec::new());
92
93    expected.write(&mut buffer).unwrap();
94    buffer.rewind().unwrap();
95    let actual = Header::read(&mut buffer).unwrap();
96
97    assert_eq!(expected, actual);
98  }
99}