caff_archive/archive/
key.rs

1use crate::prelude::*;
2use std::ops::{BitXor, BitXorAssign};
3
4#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(test, derive(Arbitrary))]
6pub struct Key(u32);
7
8impl std::fmt::Debug for Key {
9  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10    f.write_fmt(format_args!("Key({:#010X?})", self.0))
11  }
12}
13
14impl From<u32> for Key {
15  fn from(value: u32) -> Self {
16    Self(value)
17  }
18}
19
20impl Default for Key {
21  fn default() -> Self {
22    Self::from(0)
23  }
24}
25
26impl From<Key> for u32 {
27  fn from(key: Key) -> Self {
28    key.0
29  }
30}
31
32impl From<Key> for u16 {
33  fn from(key: Key) -> Self {
34    (key.0 & u32::from(u16::MAX)) as u16
35  }
36}
37
38impl From<Key> for u8 {
39  fn from(key: Key) -> Self {
40    (key.0 & u32::from(u8::MAX)) as u8
41  }
42}
43
44impl<T> BitXor<T> for Key
45where
46  T: From<Key> + BitXor<T, Output = T>,
47{
48  type Output = T;
49  fn bitxor(self, value: T) -> Self::Output {
50    T::from(self) ^ value
51  }
52}
53
54impl BitXor<Key> for u32 {
55  type Output = u32;
56  fn bitxor(self, key: Key) -> Self::Output {
57    key ^ self
58  }
59}
60
61impl BitXor<Key> for u16 {
62  type Output = u16;
63  fn bitxor(self, key: Key) -> Self::Output {
64    key ^ self
65  }
66}
67
68impl BitXor<Key> for u8 {
69  type Output = u8;
70  fn bitxor(self, key: Key) -> Self::Output {
71    key ^ self
72  }
73}
74
75impl BitXorAssign<Key> for u32 {
76  fn bitxor_assign(&mut self, key: Key) {
77    self.bitxor_assign(Self::from(key))
78  }
79}
80
81impl BitXorAssign<Key> for u8 {
82  fn bitxor_assign(&mut self, key: Key) {
83    self.bitxor_assign(Self::from(key))
84  }
85}
86
87impl Key {
88  pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Self> {
89    reader.trace(|reader| {
90      let value = reader.read_u32::<BigEndian>()?.into();
91      Ok(value)
92    })
93  }
94
95  pub fn write<W: Write + Seek>(self, writer: &mut W) -> Result<()> {
96    writer.trace(|writer| {
97      writer.write_u32::<BigEndian>(self.into())?;
98      Ok(())
99    })
100  }
101}
102
103#[cfg(test)]
104mod tests {
105  use super::*;
106  use test_strategy::proptest;
107
108  #[proptest]
109  fn roundtrip(expected: Key) {
110    let mut buffer = Cursor::new(Vec::new());
111
112    expected.write(&mut buffer).unwrap();
113    buffer.rewind().unwrap();
114    let actual = Key::read(&mut buffer).unwrap();
115
116    assert_eq!(expected, actual);
117  }
118
119  #[proptest]
120  fn default(value: u32) {
121    let expected = value;
122    let actual = Key::default() ^ value;
123
124    assert_eq!(expected, actual)
125  }
126
127  mod bitxor {
128    use super::*;
129
130    #[proptest]
131    fn u32(key: Key, value: u32) {
132      let expected = value ^ u32::from(key);
133      let actual = value ^ key;
134
135      assert_eq!(expected, actual);
136    }
137
138    #[proptest]
139    fn u16(key: Key, value: u16) {
140      let expected = value ^ u16::from(key);
141      let actual = value ^ key;
142
143      assert_eq!(expected, actual);
144    }
145
146    #[proptest]
147    fn u8(key: Key, value: u8) {
148      let expected = value ^ u8::from(key);
149      let actual = value ^ key;
150
151      assert_eq!(expected, actual);
152    }
153  }
154}