Skip to main content

icydb_core/value/
wire.rs

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