1use crate::{
6 types::*,
7 value::{VALUE_WIRE_TYPE_NAME, VALUE_WIRE_VARIANT_LABELS, Value, ValueWireVariant},
8};
9use candid::{Int as WrappedInt, Nat as WrappedNat};
10use num_bigint::{BigInt, BigUint, Sign as BigIntSign};
11use serde::{
12 Deserialize, Deserializer,
13 de::{self, EnumAccess, VariantAccess, Visitor},
14};
15use serde_bytes::ByteBuf;
16use std::{fmt, marker::PhantomData};
17
18struct IntBigWire(Int);
27
28impl IntBigWire {
29 fn into_inner(self) -> Int {
30 self.0
31 }
32}
33
34impl<'de> Deserialize<'de> for IntBigWire {
35 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36 where
37 D: Deserializer<'de>,
38 {
39 let (sign, limbs): (i8, Vec<u32>) = Deserialize::deserialize(deserializer)?;
40 let sign = match sign {
41 -1 => BigIntSign::Minus,
42 0 => BigIntSign::NoSign,
43 1 => BigIntSign::Plus,
44 _ => return Err(de::Error::custom(format!("invalid bigint sign {sign}"))),
45 };
46 let magnitude = BigUint::new(limbs);
47
48 Ok(Self(Int::from(WrappedInt::from(BigInt::from_biguint(
49 sign, magnitude,
50 )))))
51 }
52}
53
54struct UintBigWire(Nat);
63
64impl UintBigWire {
65 fn into_inner(self) -> Nat {
66 self.0
67 }
68}
69
70impl<'de> Deserialize<'de> for UintBigWire {
71 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
72 where
73 D: Deserializer<'de>,
74 {
75 let limbs: Vec<u32> = Deserialize::deserialize(deserializer)?;
76 Ok(Self(Nat::from(WrappedNat::from(BigUint::new(limbs)))))
77 }
78}
79
80struct ValueWireVisitor(PhantomData<()>);
88
89impl ValueWireVisitor {
90 fn decode_map_entries<E>(entries: Vec<(Value, Value)>) -> Result<Value, E>
91 where
92 E: de::Error,
93 {
94 Value::from_map(entries).map_err(E::custom)
95 }
96}
97
98impl<'de> Visitor<'de> for ValueWireVisitor {
99 type Value = Value;
100
101 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
102 formatter.write_str("the stable Value enum wire shape")
103 }
104
105 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
106 where
107 A: EnumAccess<'de>,
108 {
109 let (variant, payload) = data.variant::<String>()?;
110
111 let Some(variant_tag) = ValueWireVariant::from_label(variant.as_str()) else {
112 return Err(de::Error::unknown_variant(
113 variant.as_str(),
114 VALUE_WIRE_VARIANT_LABELS,
115 ));
116 };
117
118 match variant_tag {
119 ValueWireVariant::Account => Ok(Value::Account(payload.newtype_variant()?)),
120 ValueWireVariant::Blob => Ok(Value::Blob(
121 payload.newtype_variant::<ByteBuf>()?.into_vec(),
122 )),
123 ValueWireVariant::Bool => Ok(Value::Bool(payload.newtype_variant()?)),
124 ValueWireVariant::Date => Ok(Value::Date(payload.newtype_variant()?)),
125 ValueWireVariant::Decimal => Ok(Value::Decimal(payload.newtype_variant()?)),
126 ValueWireVariant::Duration => Ok(Value::Duration(payload.newtype_variant()?)),
127 ValueWireVariant::Enum => Ok(Value::Enum(payload.newtype_variant()?)),
128 ValueWireVariant::Float32 => Ok(Value::Float32(payload.newtype_variant()?)),
129 ValueWireVariant::Float64 => Ok(Value::Float64(payload.newtype_variant()?)),
130 ValueWireVariant::Int => Ok(Value::Int(payload.newtype_variant()?)),
131 ValueWireVariant::Int128 => Ok(Value::Int128(payload.newtype_variant()?)),
132 ValueWireVariant::IntBig => Ok(Value::IntBig(
133 payload.newtype_variant::<IntBigWire>()?.into_inner(),
134 )),
135 ValueWireVariant::List => Ok(Value::List(payload.newtype_variant()?)),
136 ValueWireVariant::Map => {
137 let entries = payload.newtype_variant::<Vec<(Value, Value)>>()?;
138 Self::decode_map_entries(entries)
139 }
140 ValueWireVariant::Null => {
141 payload.unit_variant()?;
142 Ok(Value::Null)
143 }
144 ValueWireVariant::Principal => Ok(Value::Principal(payload.newtype_variant()?)),
145 ValueWireVariant::Subaccount => Ok(Value::Subaccount(payload.newtype_variant()?)),
146 ValueWireVariant::Text => Ok(Value::Text(payload.newtype_variant()?)),
147 ValueWireVariant::Timestamp => Ok(Value::Timestamp(payload.newtype_variant()?)),
148 ValueWireVariant::Uint => Ok(Value::Uint(payload.newtype_variant()?)),
149 ValueWireVariant::Uint128 => Ok(Value::Uint128(payload.newtype_variant()?)),
150 ValueWireVariant::UintBig => Ok(Value::UintBig(
151 payload.newtype_variant::<UintBigWire>()?.into_inner(),
152 )),
153 ValueWireVariant::Ulid => Ok(Value::Ulid(payload.newtype_variant()?)),
154 ValueWireVariant::Unit => {
155 payload.unit_variant()?;
156 Ok(Value::Unit)
157 }
158 }
159 }
160}
161
162impl<'de> Deserialize<'de> for Value {
163 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
164 where
165 D: Deserializer<'de>,
166 {
167 deserializer.deserialize_enum(
168 VALUE_WIRE_TYPE_NAME,
169 VALUE_WIRE_VARIANT_LABELS,
170 ValueWireVisitor(PhantomData),
171 )
172 }
173}