lighthouse_common/types/
compact_u64.rs

1use borsh::maybestd::io::Read;
2use borsh::{BorshDeserialize, BorshSerialize};
3use std::fmt::Debug;
4use std::io::Write;
5use std::ops::{Deref, DerefMut};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct CompactU64(pub u64);
10
11impl BorshSerialize for CompactU64 {
12    fn serialize<W: Write>(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> {
13        leb128::write::unsigned(writer, self.0)?;
14
15        Ok(())
16    }
17}
18
19impl BorshDeserialize for CompactU64 {
20    fn deserialize_reader<R: Read>(reader: &mut R) -> borsh::maybestd::io::Result<Self> {
21        let value = leb128::read::unsigned(reader).map_err(|e| {
22            borsh::maybestd::io::Error::new(borsh::maybestd::io::ErrorKind::InvalidData, e)
23        })?;
24
25        Ok(Self(value))
26    }
27}
28
29impl Deref for CompactU64 {
30    type Target = u64;
31
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl DerefMut for CompactU64 {
38    fn deref_mut(&mut self) -> &mut Self::Target {
39        &mut self.0
40    }
41}
42
43macro_rules! impl_from_unsigned {
44    ($($t:ty),*) => {
45        $(
46            impl From<$t> for CompactU64 {
47                fn from(value: $t) -> Self {
48                    CompactU64(value as u64)
49                }
50            }
51        )*
52    };
53}
54
55impl_from_unsigned!(u8, u16, u32, u64);
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn deserialize_data() {
63        let mut data: Vec<u8> = vec![];
64
65        leb128::write::unsigned(&mut data, 10).unwrap();
66
67        let mut reader = &data[..];
68        let leb128_vec: CompactU64 = BorshDeserialize::deserialize(&mut reader).unwrap();
69
70        assert_eq!(leb128_vec, CompactU64(10));
71    }
72
73    #[test]
74    fn serialize_data() {
75        let leb128_vec: CompactU64 = CompactU64(10);
76
77        let mut data: Vec<u8> = vec![];
78
79        leb128_vec.serialize(&mut data).unwrap();
80
81        assert_eq!(data, (vec![10]));
82    }
83
84    #[test]
85    fn large_serialize_data() {
86        let leb128_vec: CompactU64 = CompactU64(1000);
87
88        let mut data: Vec<u8> = vec![];
89        leb128_vec.serialize(&mut data).unwrap();
90
91        // LEB128 encoding of 1000 is 0b11101000 0b00000111
92        let expected_data: Vec<u8> = vec![0b11101000, 0b00000111];
93
94        assert_eq!(data, expected_data);
95    }
96
97    #[test]
98    fn max_u64_serialize_data() {
99        let leb128_vec: CompactU64 = CompactU64(u64::MAX);
100
101        let mut data: Vec<u8> = vec![];
102        leb128_vec.serialize(&mut data).unwrap();
103
104        assert_eq!(
105            data,
106            vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]
107        );
108    }
109
110    #[test]
111    fn max_u64_deserialize() {
112        let data: Vec<u8> = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01];
113
114        let mut reader = &data[..];
115
116        let leb128_vec: CompactU64 = BorshDeserialize::deserialize(&mut reader).unwrap();
117
118        assert_eq!(leb128_vec, CompactU64(u64::MAX));
119    }
120}