fuel_compression/
key.rs

1use serde::{
2    Deserialize,
3    Serialize,
4};
5
6/// Untyped key pointing to a registry table entry.
7/// The last key (all bits set) is reserved for the default value and cannot be written
8/// to.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub struct RegistryKey([u8; Self::SIZE]);
11impl RegistryKey {
12    /// Key mapping to default value for the table type.
13    pub const DEFAULT_VALUE: Self = Self([u8::MAX; Self::SIZE]);
14    /// Maximum writable key.
15    pub const MAX_WRITABLE: Self = Self([u8::MAX, u8::MAX, u8::MAX - 1]);
16    /// Size of the key, in bytes.
17    pub const SIZE: usize = 3;
18    /// Zero key.
19    pub const ZERO: Self = Self([0; Self::SIZE]);
20
21    /// Convert to u32, big-endian.
22    pub fn as_u32(self) -> u32 {
23        u32::from_be_bytes([0, self.0[0], self.0[1], self.0[2]])
24    }
25
26    /// Wraps around just below max/default value.
27    /// Panics for max/default value.
28    pub fn next(self) -> Self {
29        if self == Self::DEFAULT_VALUE {
30            panic!("Max/default value has no next key");
31        }
32        let next_raw = self.as_u32() + 1u32;
33        if next_raw == Self::DEFAULT_VALUE.as_u32() {
34            Self::ZERO
35        } else {
36            Self::try_from(next_raw)
37                .expect("The procedure above always produces a valid key")
38        }
39    }
40}
41
42impl TryFrom<u32> for RegistryKey {
43    type Error = &'static str;
44
45    fn try_from(value: u32) -> Result<Self, Self::Error> {
46        let v = value.to_be_bytes();
47        if v[0] != 0 {
48            return Err("RegistryKey must be less than 2^24");
49        }
50
51        let mut bytes = [0u8; 3];
52        bytes.copy_from_slice(&v[1..]);
53        Ok(Self(bytes))
54    }
55}
56
57impl TryFrom<&[u8]> for RegistryKey {
58    type Error = &'static str;
59
60    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
61        if value.len() != Self::SIZE {
62            return Err("RegistryKey must be 3 bytes long");
63        }
64
65        let mut bytes = [0u8; 3];
66        bytes.copy_from_slice(value);
67        Ok(Self(bytes))
68    }
69}
70
71impl AsRef<[u8]> for RegistryKey {
72    fn as_ref(&self) -> &[u8] {
73        &self.0
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::RegistryKey;
80
81    #[test]
82    fn key_next() {
83        assert_eq!(RegistryKey::ZERO.next(), RegistryKey([0, 0, 1]));
84        assert_eq!(RegistryKey::ZERO.next().next(), RegistryKey([0, 0, 2]));
85        assert_eq!(RegistryKey([0, 0, 255]).next(), RegistryKey([0, 1, 0]));
86        assert_eq!(RegistryKey([0, 1, 255]).next(), RegistryKey([0, 2, 0]));
87        assert_eq!(RegistryKey([0, 255, 255]).next(), RegistryKey([1, 0, 0]));
88        assert_eq!(RegistryKey::MAX_WRITABLE.next(), RegistryKey::ZERO);
89    }
90}