chainlink_data_streams_report/report/
base.rs1use 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}