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