Skip to main content

icydb_core/value/
wire.rs

1//! Module: value::wire
2//! Defines serde-only wire helpers that rebuild public runtime value wrappers
3//! from persisted payload shapes.
4
5use crate::{
6    types::*,
7    value::{MapValueError, Value, ValueEnum},
8};
9use candid::{Int as WrappedInt, Nat as WrappedNat};
10use num_bigint::{BigInt, BigUint, Sign as BigIntSign};
11use serde::{Deserialize, Deserializer, de};
12use serde_bytes::ByteBuf;
13
14///
15/// IntBigWire
16///
17/// IntBigWire accepts the persisted bigint `(sign, limbs)` payload shape and
18/// rebuilds the public `Int` wrapper without routing through the derived
19/// `Deserialize` form of `candid::Int`.
20///
21
22struct IntBigWire(Int);
23
24impl IntBigWire {
25    fn into_inner(self) -> Int {
26        self.0
27    }
28}
29
30impl<'de> Deserialize<'de> for IntBigWire {
31    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
32    where
33        D: Deserializer<'de>,
34    {
35        let (sign, limbs): (i8, Vec<u32>) = Deserialize::deserialize(deserializer)?;
36        let sign = match sign {
37            -1 => BigIntSign::Minus,
38            0 => BigIntSign::NoSign,
39            1 => BigIntSign::Plus,
40            _ => return Err(de::Error::custom(format!("invalid bigint sign {sign}"))),
41        };
42        let magnitude = BigUint::new(limbs);
43
44        Ok(Self(Int::from(WrappedInt::from(BigInt::from_biguint(
45            sign, magnitude,
46        )))))
47    }
48}
49
50///
51/// UintBigWire
52///
53/// UintBigWire accepts the persisted biguint limb payload shape and rebuilds
54/// the public `Nat` wrapper without routing through the derived `Deserialize`
55/// form of `candid::Nat`.
56///
57
58struct UintBigWire(Nat);
59
60impl UintBigWire {
61    fn into_inner(self) -> Nat {
62        self.0
63    }
64}
65
66impl<'de> Deserialize<'de> for UintBigWire {
67    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68    where
69        D: Deserializer<'de>,
70    {
71        let limbs: Vec<u32> = Deserialize::deserialize(deserializer)?;
72        Ok(Self(Nat::from(WrappedNat::from(BigUint::new(limbs)))))
73    }
74}
75
76///
77/// ValueWire
78/// Serde decode shape used to re-check Value::Map invariants during deserialization.
79///
80
81#[derive(Deserialize)]
82enum ValueWire {
83    Account(Account),
84    Blob(ByteBuf),
85    Bool(bool),
86    Date(Date),
87    Decimal(Decimal),
88    Duration(Duration),
89    Enum(ValueEnum),
90    Float32(Float32),
91    Float64(Float64),
92    Int(i64),
93    Int128(Int128),
94    IntBig(IntBigWire),
95    List(Vec<Self>),
96    Map(Vec<(Self, Self)>),
97    Null,
98    Principal(Principal),
99    Subaccount(Subaccount),
100    Text(String),
101    Timestamp(Timestamp),
102    Uint(u64),
103    Uint128(Nat128),
104    UintBig(UintBigWire),
105    Ulid(Ulid),
106    Unit,
107}
108
109impl ValueWire {
110    // Decode recursively while enforcing runtime map invariants.
111    fn into_value(self) -> Result<Value, MapValueError> {
112        match self {
113            Self::Account(v) => Ok(Value::Account(v)),
114            Self::Blob(v) => Ok(Value::Blob(v.into_vec())),
115            Self::Bool(v) => Ok(Value::Bool(v)),
116            Self::Date(v) => Ok(Value::Date(v)),
117            Self::Decimal(v) => Ok(Value::Decimal(v)),
118            Self::Duration(v) => Ok(Value::Duration(v)),
119            Self::Enum(v) => Ok(Value::Enum(v)),
120            Self::Float32(v) => Ok(Value::Float32(v)),
121            Self::Float64(v) => Ok(Value::Float64(v)),
122            Self::Int(v) => Ok(Value::Int(v)),
123            Self::Int128(v) => Ok(Value::Int128(v)),
124            Self::IntBig(v) => Ok(Value::IntBig(v.into_inner())),
125            Self::List(items) => {
126                let items = items
127                    .into_iter()
128                    .map(Self::into_value)
129                    .collect::<Result<Vec<_>, _>>()?;
130                Ok(Value::List(items))
131            }
132            Self::Map(entries) => {
133                let entries = entries
134                    .into_iter()
135                    .map(|(key, value)| Ok((key.into_value()?, value.into_value()?)))
136                    .collect::<Result<Vec<_>, MapValueError>>()?;
137                Value::from_map(entries)
138            }
139            Self::Null => Ok(Value::Null),
140            Self::Principal(v) => Ok(Value::Principal(v)),
141            Self::Subaccount(v) => Ok(Value::Subaccount(v)),
142            Self::Text(v) => Ok(Value::Text(v)),
143            Self::Timestamp(v) => Ok(Value::Timestamp(v)),
144            Self::Uint(v) => Ok(Value::Uint(v)),
145            Self::Uint128(v) => Ok(Value::Uint128(v)),
146            Self::UintBig(v) => Ok(Value::UintBig(v.into_inner())),
147            Self::Ulid(v) => Ok(Value::Ulid(v)),
148            Self::Unit => Ok(Value::Unit),
149        }
150    }
151}
152
153impl<'de> Deserialize<'de> for Value {
154    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155    where
156        D: Deserializer<'de>,
157    {
158        let wire = ValueWire::deserialize(deserializer)?;
159        wire.into_value().map_err(serde::de::Error::custom)
160    }
161}