lighthouse_sol/types/
compact_u64.rs

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