Skip to main content

cardano_serialization_lib/serialization/numeric/
int.rs

1use crate::*;
2use crate::serialization::utils::read_nint;
3
4impl cbor_event::se::Serialize for Int {
5    fn serialize<'se, W: Write>(
6        &self,
7        serializer: &'se mut Serializer<W>,
8    ) -> cbor_event::Result<&'se mut Serializer<W>> {
9        // Invariant: Int::CBOR_MIN <= self.0 <= Int::CBOR_MAX, i.e. fits in CBOR int.
10        // For negatives we use the i128-aware writer: nint payload (-1 - value)
11        // can be up to u64::MAX, which does not fit in i64.
12        if self.0 < 0 {
13            let payload = (-self.0 - 1) as u64;
14            serializer.write_negative_integer_sz(self.0, cbor_event::Sz::canonical(payload))
15        } else {
16            serializer.write_unsigned_integer(self.0 as u64)
17        }
18    }
19}
20
21impl Deserialize for Int {
22    fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
23        (|| -> Result<_, DeserializeError> {
24            match raw.cbor_type()? {
25                cbor_event::Type::UnsignedInteger => {
26                    // raw u64 fits Int::CBOR_MAX by construction.
27                    Ok(Self(raw.unsigned_integer()? as i128))
28                }
29                cbor_event::Type::NegativeInteger => {
30                    let n = read_nint(raw)?;
31                    // read_nint returns i128 in [-2^64, -1] which exactly matches
32                    // [Int::CBOR_MIN, -1]. Validate as defense-in-depth.
33                    Int::new_checked(n).map_err(|e| {
34                        DeserializeFailure::CustomError(format!("{:?}", e)).into()
35                    })
36                }
37                _ => Err(DeserializeFailure::NoVariantMatched.into()),
38            }
39        })()
40            .map_err(|e| e.annotate("Int"))
41    }
42}