caff_archive/archive/
header.rs1use 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}