1#![allow(clippy::non_canonical_partial_ord_impl)]
12
13pub use error::*;
14
15pub mod error;
16pub mod network;
17pub mod ordered_hash_map;
18pub mod serialization;
19
20use crate::serialization::{fit_sz, Deserialize, Serialize};
21
22extern crate derivative;
23use derivative::Derivative;
24
25use cbor_event::{de::Deserializer, se::Serializer};
26use std::io::{BufRead, Seek, Write};
27
28pub type Epoch = u64;
29
30pub type Slot = u64;
31
32pub type TransactionIndex = u16;
33
34pub type CertificateIndex = u64;
35
36#[derive(Clone, Debug, Derivative)]
37#[derivative(
38 Eq,
39 PartialEq,
40 Ord = "feature_allow_slow_enum",
41 PartialOrd = "feature_allow_slow_enum",
42 Hash
43)]
44pub enum Int {
45 Uint {
46 value: u64,
47 #[derivative(
48 PartialEq = "ignore",
49 Ord = "ignore",
50 PartialOrd = "ignore",
51 Hash = "ignore"
52 )]
53 encoding: Option<cbor_event::Sz>,
54 },
55 Nint {
56 value: u64,
57 #[derivative(
58 PartialEq = "ignore",
59 Ord = "ignore",
60 PartialOrd = "ignore",
61 Hash = "ignore"
62 )]
63 encoding: Option<cbor_event::Sz>,
64 },
65}
66
67#[derive(Clone, Debug)]
68pub enum IntError {
69 Bounds(std::num::TryFromIntError),
70 Parsing(std::num::ParseIntError),
71}
72
73impl Int {
74 pub fn new_uint(value: u64) -> Self {
75 Self::Uint {
76 value,
77 encoding: None,
78 }
79 }
80
81 pub fn new_nint(value: u64) -> Self {
83 Self::Nint {
84 value,
85 encoding: None,
86 }
87 }
88
89 pub fn encoding(&self) -> &Option<cbor_event::Sz> {
90 match self {
91 Self::Uint { encoding, .. } => encoding,
92 Self::Nint { encoding, .. } => encoding,
93 }
94 }
95}
96
97impl std::fmt::Display for Int {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match self {
100 Self::Uint { value, .. } => write!(f, "{value}"),
101 Self::Nint { value, .. } => write!(f, "-{}", (*value as i128) + 1),
103 }
104 }
105}
106
107impl std::str::FromStr for Int {
108 type Err = IntError;
109
110 fn from_str(s: &str) -> Result<Self, Self::Err> {
111 use std::convert::TryFrom;
112 let x = i128::from_str(s).map_err(IntError::Parsing)?;
113 Self::try_from(x).map_err(IntError::Bounds)
114 }
115}
116
117impl serde::Serialize for Int {
121 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122 where
123 S: serde::Serializer,
124 {
125 serializer.serialize_str(&self.to_string())
126 }
127}
128
129impl<'de> serde::de::Deserialize<'de> for Int {
130 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131 where
132 D: serde::de::Deserializer<'de>,
133 {
134 use std::str::FromStr;
135 let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
136 Self::from_str(&s).map_err(|_e| {
137 serde::de::Error::invalid_value(
138 serde::de::Unexpected::Str(&s),
139 &"invalid int (as string)",
140 )
141 })
142 }
143}
144
145impl schemars::JsonSchema for Int {
146 fn schema_name() -> String {
147 String::from("Int")
148 }
149
150 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
151 String::json_schema(gen)
152 }
153
154 fn is_referenceable() -> bool {
155 String::is_referenceable()
156 }
157}
158
159impl From<u64> for Int {
160 fn from(x: u64) -> Self {
161 Self::Uint {
162 value: x,
163 encoding: None,
164 }
165 }
166}
167
168impl From<i64> for Int {
169 fn from(x: i64) -> Self {
170 if x >= 0 {
171 Self::Uint {
172 value: x as u64,
173 encoding: None,
174 }
175 } else {
176 Self::Nint {
177 value: (x + 1).unsigned_abs(),
178 encoding: None,
179 }
180 }
181 }
182}
183
184impl std::convert::TryFrom<i128> for Int {
185 type Error = std::num::TryFromIntError;
186
187 fn try_from(x: i128) -> Result<Self, Self::Error> {
188 if x >= 0 {
189 u64::try_from(x).map(|x| Self::Uint {
190 value: x,
191 encoding: None,
192 })
193 } else {
194 u64::try_from((x + 1).abs()).map(|x| Self::Nint {
195 value: x,
196 encoding: None,
197 })
198 }
199 }
200}
201
202impl From<&Int> for i128 {
203 fn from(val: &Int) -> Self {
204 match val {
205 Int::Uint { value, .. } => (*value).into(),
206 Int::Nint { value, .. } => -((*value as i128) + 1),
207 }
208 }
209}
210
211impl Serialize for Int {
212 fn serialize<'se, W: Write>(
213 &self,
214 serializer: &'se mut Serializer<W>,
215 force_canonical: bool,
216 ) -> cbor_event::Result<&'se mut Serializer<W>> {
217 match self {
218 Self::Uint { value, encoding } => serializer
219 .write_unsigned_integer_sz(*value, fit_sz(*value, *encoding, force_canonical)),
220 Self::Nint { value, encoding } => serializer.write_negative_integer_sz(
221 -((*value as i128) + 1),
222 fit_sz(*value, *encoding, force_canonical),
223 ),
224 }
225 }
226}
227
228impl Deserialize for Int {
229 fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
230 (|| -> Result<_, DeserializeError> {
231 match raw.cbor_type()? {
232 cbor_event::Type::UnsignedInteger => raw
233 .unsigned_integer_sz()
234 .map(|(x, enc)| Self::Uint {
235 value: x,
236 encoding: Some(enc),
237 })
238 .map_err(std::convert::Into::into),
239 cbor_event::Type::NegativeInteger => raw
240 .negative_integer_sz()
241 .map(|(x, enc)| Self::Nint {
242 value: (-1 - x) as u64,
243 encoding: Some(enc),
244 })
245 .map_err(std::convert::Into::into),
246 _ => Err(DeserializeFailure::NoVariantMatched.into()),
247 }
248 })()
249 .map_err(|e| e.annotate("Int"))
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn int_uint_min() {
259 let bytes = [0x00];
260 let x = Int::from_cbor_bytes(&bytes).unwrap();
261 assert_eq!(bytes, x.to_cbor_bytes().as_slice());
262 assert_eq!(Into::<i128>::into(&x), u64::MIN as i128);
263 assert_eq!(x.to_string(), "0");
264 }
265
266 #[test]
267 fn int_uint_max() {
268 let bytes = [0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
269 let x = Int::from_cbor_bytes(&bytes).unwrap();
270 assert_eq!(bytes, x.to_cbor_bytes().as_slice());
271 assert_eq!(Into::<i128>::into(&x), u64::MAX as i128);
272 assert_eq!(x.to_string(), "18446744073709551615");
273 }
274
275 #[test]
276 fn int_nint_min() {
277 let bytes = [0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
278 let x = Int::from_cbor_bytes(&bytes).unwrap();
279 assert_eq!(bytes, x.to_cbor_bytes().as_slice());
280 assert_eq!(Into::<i128>::into(&x), -((u64::MAX as i128) + 1));
281 assert_eq!(x.to_string(), "-18446744073709551616");
282 }
283
284 #[test]
285 fn int_nint_max() {
286 let bytes = [0x20];
287 let x = Int::from_cbor_bytes(&bytes).unwrap();
288 assert_eq!(bytes, x.to_cbor_bytes().as_slice());
289 assert_eq!(Into::<i128>::into(&x), -1i128);
290 assert_eq!(x.to_string(), "-1");
291 let y = Int::from(-1i64);
292 assert_eq!(x.to_canonical_cbor_bytes(), y.to_canonical_cbor_bytes());
293 }
294}