forest_bigint/
bigint_ser.rs

1// Copyright 2020 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use num_bigint::{BigInt, Sign};
5use serde::{Deserialize, Serialize};
6use std::borrow::Cow;
7
8/// Wrapper for serializing big ints to match filecoin spec. Serializes as bytes.
9#[derive(Serialize)]
10#[serde(transparent)]
11pub struct BigIntSer<'a>(#[serde(with = "self")] pub &'a BigInt);
12
13/// Wrapper for deserializing as BigInt from bytes.
14#[derive(Deserialize, Serialize, Clone, Default, PartialEq)]
15#[serde(transparent)]
16pub struct BigIntDe(#[serde(with = "self")] pub BigInt);
17
18/// Serializes big int as bytes following Filecoin spec.
19pub fn serialize<S>(int: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
20where
21    S: serde::Serializer,
22{
23    let (sign, mut bz) = int.to_bytes_be();
24
25    // Insert sign byte at start of encoded bytes
26    match sign {
27        Sign::Minus => bz.insert(0, 1),
28        Sign::Plus => bz.insert(0, 0),
29        Sign::NoSign => bz = Vec::new(),
30    }
31
32    // Serialize as bytes
33    serde_bytes::Serialize::serialize(&bz, serializer)
34}
35
36/// Deserializes bytes into big int.
37pub fn deserialize<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
38where
39    D: serde::Deserializer<'de>,
40{
41    let bz: Cow<'de, [u8]> = serde_bytes::Deserialize::deserialize(deserializer)?;
42    if bz.is_empty() {
43        return Ok(BigInt::default());
44    }
45    let sign_byte = bz[0];
46    let sign: Sign = match sign_byte {
47        1 => Sign::Minus,
48        0 => Sign::Plus,
49        _ => {
50            return Err(serde::de::Error::custom(
51                "First byte must be valid sign (0, 1)",
52            ));
53        }
54    };
55    Ok(BigInt::from_bytes_be(sign, &bz[1..]))
56}
57
58#[cfg(feature = "json")]
59pub mod json {
60    use super::*;
61    use std::str::FromStr;
62
63    /// Serializes BigInt as String
64    pub fn serialize<S>(int: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
65    where
66        S: serde::Serializer,
67    {
68        String::serialize(&int.to_string(), serializer)
69    }
70
71    /// Deserializes String into BigInt.
72    pub fn deserialize<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
73    where
74        D: serde::Deserializer<'de>,
75    {
76        let s = String::deserialize(deserializer)?;
77        BigInt::from_str(&s).map_err(serde::de::Error::custom)
78    }
79
80    pub mod opt {
81        use super::*;
82        use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
83
84        pub fn serialize<S>(v: &Option<BigInt>, serializer: S) -> Result<S::Ok, S::Error>
85        where
86            S: Serializer,
87        {
88            v.as_ref().map(|s| s.to_string()).serialize(serializer)
89        }
90
91        pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<BigInt>, D::Error>
92        where
93            D: Deserializer<'de>,
94        {
95            let s: Option<String> = Deserialize::deserialize(deserializer)?;
96            if let Some(v) = s {
97                return Ok(Some(
98                    BigInt::from_str(&v).map_err(serde::de::Error::custom)?,
99                ));
100            }
101            Ok(None)
102        }
103    }
104}