chainlink_data_streams_report/report/
base.rs

1use num_bigint::{BigInt, Sign};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum ReportError {
6    #[error("Data is too short for {0}")]
7    DataTooShort(&'static str),
8
9    #[error("Invalid length for {0}")]
10    InvalidLength(&'static str),
11
12    #[error("Failed to parse {0}")]
13    ParseError(&'static str),
14}
15
16pub(crate) struct ReportBase;
17
18impl ReportBase {
19    pub(crate) const WORD_SIZE: usize = 32;
20
21    pub(crate) fn read_int192(data: &[u8], offset: usize) -> Result<BigInt, ReportError> {
22        if offset + Self::WORD_SIZE > data.len() {
23            return Err(ReportError::DataTooShort("int192"));
24        }
25        let value_bytes = &data[offset..offset + Self::WORD_SIZE];
26        Ok(BigInt::from_signed_bytes_be(&value_bytes[8..32]))
27    }
28
29    pub(crate) fn encode_int192(value: &BigInt) -> Result<[u8; 32], ReportError> {
30        let mut buffer = [0u8; 32];
31        let bytes_value = value.to_signed_bytes_be();
32        let len = bytes_value.len();
33
34        if len > 24 {
35            return Err(ReportError::InvalidLength("int192"));
36        }
37
38        buffer[32 - len..32].copy_from_slice(&bytes_value);
39        Ok(buffer)
40    }
41
42    pub(crate) fn read_uint192(data: &[u8], offset: usize) -> Result<BigInt, ReportError> {
43        if offset + Self::WORD_SIZE > data.len() {
44            return Err(ReportError::DataTooShort("uint192"));
45        }
46        let value_bytes = &data[offset..offset + Self::WORD_SIZE];
47        Ok(BigInt::from_bytes_be(Sign::Plus, &value_bytes[8..32]))
48    }
49
50    pub(crate) fn encode_uint192(value: &BigInt) -> Result<[u8; 32], ReportError> {
51        let mut buffer = [0u8; 32];
52        let (_, bytes_value) = value.to_bytes_be();
53        let len = bytes_value.len();
54
55        if len > 24 {
56            return Err(ReportError::InvalidLength("uint192"));
57        }
58
59        buffer[32 - len..32].copy_from_slice(&bytes_value);
60        Ok(buffer)
61    }
62
63    pub(crate) fn read_uint32(data: &[u8], offset: usize) -> Result<u32, ReportError> {
64        if offset + Self::WORD_SIZE > data.len() {
65            return Err(ReportError::DataTooShort("uint32"));
66        }
67        let value_bytes = &data[offset..offset + Self::WORD_SIZE];
68        Ok(u32::from_be_bytes(
69            value_bytes[28..32]
70                .try_into()
71                .map_err(|_| ReportError::InvalidLength("uint32"))?,
72        ))
73    }
74
75    pub(crate) fn encode_uint32(value: u32) -> Result<[u8; 32], ReportError> {
76        let mut buffer = [0u8; 32];
77        let bytes_value = value.to_be_bytes();
78        let len = bytes_value.len();
79
80        if len > 4 {
81            return Err(ReportError::InvalidLength("uint32"));
82        }
83
84        buffer[32 - len..32].copy_from_slice(&bytes_value);
85        Ok(buffer)
86    }
87
88    pub(crate) fn read_uint64(data: &[u8], offset: usize) -> Result<u64, ReportError> {
89        if offset + Self::WORD_SIZE > data.len() {
90            return Err(ReportError::DataTooShort("uint64"));
91        }
92        let value_bytes = &data[offset..offset + Self::WORD_SIZE];
93        Ok(u64::from_be_bytes(
94            value_bytes[24..32]
95                .try_into()
96                .map_err(|_| ReportError::InvalidLength("uint64"))?,
97        ))
98    }
99
100    pub(crate) fn encode_uint64(value: u64) -> Result<[u8; 32], ReportError> {
101        let mut buffer = [0u8; 32];
102        let bytes_value = value.to_be_bytes();
103        let len = bytes_value.len();
104
105        if len > 8 {
106            return Err(ReportError::InvalidLength("uint64"));
107        }
108
109        buffer[32 - len..32].copy_from_slice(&bytes_value);
110        Ok(buffer)
111    }
112
113    pub(crate) fn read_int64(data: &[u8], offset: usize) -> Result<i64, ReportError> {
114        if offset + Self::WORD_SIZE > data.len() {
115            return Err(ReportError::DataTooShort("int64"));
116        }
117        let value_bytes = &data[offset..offset + Self::WORD_SIZE];
118        Ok(i64::from_be_bytes(
119            value_bytes[24..32]
120                .try_into()
121                .map_err(|_| ReportError::InvalidLength("int64"))?,
122        ))
123    }
124
125    pub(crate) fn encode_int64(value: i64) -> Result<[u8; 32], ReportError> {
126        let mut buffer = [0u8; 32];
127        let bytes_value = value.to_be_bytes();
128        let len = bytes_value.len();
129
130        if len > 8 {
131            return Err(ReportError::InvalidLength("int64"));
132        }
133
134        buffer[32 - len..32].copy_from_slice(&bytes_value);
135        Ok(buffer)
136    }
137}