cw_storage_plus/
int_key.rs

1use std::mem;
2
3/// Our int keys are simply the big-endian representation bytes for unsigned ints,
4/// but "sign-flipped" (xored msb) big-endian bytes for signed ints.
5///
6/// So that the representation of signed integers is in the right lexicographical order.
7pub trait IntKey: Sized + Copy {
8    type Buf: AsRef<[u8]> + AsMut<[u8]> + Into<Vec<u8>> + Default;
9
10    fn to_cw_bytes(&self) -> Self::Buf;
11    fn from_cw_bytes(bytes: Self::Buf) -> Self;
12}
13
14macro_rules! cw_uint_keys {
15    (for $($t:ty),+) => {
16        $(impl IntKey for $t {
17            type Buf = [u8; mem::size_of::<$t>()];
18
19            #[inline]
20            fn to_cw_bytes(&self) -> Self::Buf {
21                self.to_be_bytes()
22            }
23
24            #[inline]
25            fn from_cw_bytes(bytes: Self::Buf) -> Self {
26                Self::from_be_bytes(bytes)
27            }
28        })*
29    }
30}
31
32cw_uint_keys!(for u8, u16, u32, u64, u128);
33
34macro_rules! cw_int_keys {
35    (for $($t:ty, $ut:ty),+) => {
36        $(impl IntKey for $t {
37            type Buf = [u8; mem::size_of::<$t>()];
38
39            #[inline]
40            fn to_cw_bytes(&self) -> Self::Buf {
41                (*self as $ut ^ <$t>::MIN as $ut).to_be_bytes()
42            }
43
44            #[inline]
45            fn from_cw_bytes(bytes: Self::Buf) -> Self {
46                (Self::from_be_bytes(bytes) as $ut ^ <$t>::MIN as $ut) as _
47            }
48        })*
49    }
50}
51
52cw_int_keys!(for i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
53
54#[cfg(test)]
55mod test {
56    use super::*;
57
58    #[test]
59    fn x8_int_key_works() {
60        assert_eq!(0x42u8.to_cw_bytes(), [0x42]);
61        assert_eq!(0x42i8.to_cw_bytes(), [0xc2]);
62        assert_eq!((-0x3ei8).to_cw_bytes(), [0x42]);
63    }
64
65    #[test]
66    fn x16_int_key_works() {
67        assert_eq!(0x4243u16.to_cw_bytes(), [0x42, 0x43]);
68        assert_eq!(0x4243i16.to_cw_bytes(), [0xc2, 0x43]);
69        assert_eq!((-0x3dbdi16).to_cw_bytes(), [0x42, 0x43]);
70    }
71
72    #[test]
73    fn x32_int_key_works() {
74        assert_eq!(0x424344u32.to_cw_bytes(), [0x00, 0x42, 0x43, 0x44]);
75        assert_eq!(0x424344i32.to_cw_bytes(), [0x80, 0x42, 0x43, 0x44]);
76        assert_eq!((-0x7fbdbcbci32).to_cw_bytes(), [0x00, 0x42, 0x43, 0x44]);
77    }
78
79    #[test]
80    fn x64_int_key_works() {
81        assert_eq!(
82            0x42434445u64.to_cw_bytes(),
83            [0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
84        );
85        assert_eq!(
86            0x42434445i64.to_cw_bytes(),
87            [0x80, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
88        );
89        assert_eq!(
90            (-0x7fffffffbdbcbbbbi64).to_cw_bytes(),
91            [0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
92        );
93    }
94
95    #[test]
96    fn x128_int_key_works() {
97        assert_eq!(
98            0x4243444546u128.to_cw_bytes(),
99            [
100                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
101                0x45, 0x46
102            ]
103        );
104        assert_eq!(
105            0x4243444546i128.to_cw_bytes(),
106            [
107                0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
108                0x45, 0x46
109            ]
110        );
111        assert_eq!(
112            (-0x7fffffffffffffffffffffbdbcbbbabai128).to_cw_bytes(),
113            [
114                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
115                0x45, 0x46
116            ]
117        );
118    }
119
120    #[test]
121    fn unsigned_int_key_order() {
122        assert!(0u32.to_cw_bytes() < 652u32.to_cw_bytes());
123    }
124
125    #[test]
126    fn signed_int_key_order() {
127        assert!((-321i32).to_cw_bytes() < 0i32.to_cw_bytes());
128        assert!(0i32.to_cw_bytes() < 652i32.to_cw_bytes());
129    }
130}