1use std::{
6 fmt,
7 fmt::{Debug, Display, Formatter, Write},
8 marker::PhantomData,
9 ops::Deref,
10 str::FromStr,
11};
12
13use iota_protocol_config::ProtocolVersion;
14use move_core_types::{
15 account_address::AccountAddress,
16 language_storage::{StructTag, TypeTag},
17};
18use schemars::JsonSchema;
19use serde::{
20 self, Deserialize, Serialize,
21 de::{Deserializer, Error},
22 ser::{Error as SerError, Serializer},
23};
24use serde_with::{Bytes, DeserializeAs, DisplayFromStr, SerializeAs, serde_as};
25
26use crate::{
27 IOTA_CLOCK_ADDRESS, IOTA_FRAMEWORK_ADDRESS, IOTA_SYSTEM_ADDRESS, IOTA_SYSTEM_STATE_ADDRESS,
28 STARDUST_ADDRESS, parse_iota_struct_tag, parse_iota_type_tag,
29};
30
31#[inline]
32pub(crate) fn to_custom_deser_error<'de, D, E>(e: E) -> D::Error
33where
34 E: Debug,
35 D: Deserializer<'de>,
36{
37 Error::custom(format!("byte deserialization failed, cause by: {e:?}"))
38}
39
40#[inline]
41pub(crate) fn to_custom_ser_error<S, E>(e: E) -> S::Error
42where
43 E: Debug,
44 S: Serializer,
45{
46 S::Error::custom(format!("byte serialization failed, cause by: {e:?}"))
47}
48
49pub struct Readable<H, R> {
65 human_readable: PhantomData<H>,
66 non_human_readable: PhantomData<R>,
67}
68
69impl<T: ?Sized, H, R> SerializeAs<T> for Readable<H, R>
70where
71 H: SerializeAs<T>,
72 R: SerializeAs<T>,
73{
74 fn serialize_as<S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 if serializer.is_human_readable() {
79 H::serialize_as(value, serializer)
80 } else {
81 R::serialize_as(value, serializer)
82 }
83 }
84}
85
86impl<'de, R, H, T> DeserializeAs<'de, T> for Readable<H, R>
87where
88 H: DeserializeAs<'de, T>,
89 R: DeserializeAs<'de, T>,
90{
91 fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
92 where
93 D: Deserializer<'de>,
94 {
95 if deserializer.is_human_readable() {
96 H::deserialize_as(deserializer)
97 } else {
98 R::deserialize_as(deserializer)
99 }
100 }
101}
102
103pub struct IotaStructTag;
104
105impl SerializeAs<StructTag> for IotaStructTag {
106 fn serialize_as<S>(value: &StructTag, serializer: S) -> Result<S::Ok, S::Error>
107 where
108 S: Serializer,
109 {
110 let f = to_iota_struct_tag_string(value).map_err(S::Error::custom)?;
111 f.serialize(serializer)
112 }
113}
114
115const IOTA_ADDRESSES: [AccountAddress; 7] = [
116 AccountAddress::ZERO,
117 AccountAddress::ONE,
118 IOTA_FRAMEWORK_ADDRESS,
119 IOTA_SYSTEM_ADDRESS,
120 STARDUST_ADDRESS,
121 IOTA_SYSTEM_STATE_ADDRESS,
122 IOTA_CLOCK_ADDRESS,
123];
124pub fn to_iota_struct_tag_string(value: &StructTag) -> Result<String, fmt::Error> {
126 let mut f = String::new();
127 let address = if IOTA_ADDRESSES.contains(&value.address) {
129 value.address.short_str_lossless()
130 } else {
131 value.address.to_canonical_string(false)
132 };
133
134 write!(f, "0x{}::{}::{}", address, value.module, value.name)?;
135 if let Some(first_ty) = value.type_params.first() {
136 write!(f, "<")?;
137 write!(f, "{}", to_iota_type_tag_string(first_ty)?)?;
138 for ty in value.type_params.iter().skip(1) {
139 write!(f, ", {}", to_iota_type_tag_string(ty)?)?;
140 }
141 write!(f, ">")?;
142 }
143 Ok(f)
144}
145
146fn to_iota_type_tag_string(value: &TypeTag) -> Result<String, fmt::Error> {
147 match value {
148 TypeTag::Vector(t) => Ok(format!("vector<{}>", to_iota_type_tag_string(t)?)),
149 TypeTag::Struct(s) => to_iota_struct_tag_string(s),
150 _ => Ok(value.to_string()),
151 }
152}
153
154impl<'de> DeserializeAs<'de, StructTag> for IotaStructTag {
155 fn deserialize_as<D>(deserializer: D) -> Result<StructTag, D::Error>
156 where
157 D: Deserializer<'de>,
158 {
159 let s = String::deserialize(deserializer)?;
160 parse_iota_struct_tag(&s).map_err(D::Error::custom)
161 }
162}
163
164pub struct IotaTypeTag;
165
166impl SerializeAs<TypeTag> for IotaTypeTag {
167 fn serialize_as<S>(value: &TypeTag, serializer: S) -> Result<S::Ok, S::Error>
168 where
169 S: Serializer,
170 {
171 let s = to_iota_type_tag_string(value).map_err(S::Error::custom)?;
172 s.serialize(serializer)
173 }
174}
175
176impl<'de> DeserializeAs<'de, TypeTag> for IotaTypeTag {
177 fn deserialize_as<D>(deserializer: D) -> Result<TypeTag, D::Error>
178 where
179 D: Deserializer<'de>,
180 {
181 let s = String::deserialize(deserializer)?;
182 parse_iota_type_tag(&s).map_err(D::Error::custom)
183 }
184}
185
186#[serde_as]
187#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, JsonSchema)]
188pub struct BigInt<T>(
189 #[schemars(with = "String")]
190 #[serde_as(as = "DisplayFromStr")]
191 T,
192)
193where
194 T: Display + FromStr,
195 <T as FromStr>::Err: Display;
196
197impl<T> BigInt<T>
198where
199 T: Display + FromStr,
200 <T as FromStr>::Err: Display,
201{
202 pub fn into_inner(self) -> T {
203 self.0
204 }
205}
206
207impl<T> SerializeAs<T> for BigInt<T>
208where
209 T: Display + FromStr + Copy,
210 <T as FromStr>::Err: Display,
211{
212 fn serialize_as<S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
213 where
214 S: Serializer,
215 {
216 BigInt(*value).serialize(serializer)
217 }
218}
219
220impl<'de, T> DeserializeAs<'de, T> for BigInt<T>
221where
222 T: Display + FromStr + Copy,
223 <T as FromStr>::Err: Display,
224{
225 fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
226 where
227 D: Deserializer<'de>,
228 {
229 Ok(*BigInt::deserialize(deserializer)?)
230 }
231}
232
233impl<T> From<T> for BigInt<T>
234where
235 T: Display + FromStr,
236 <T as FromStr>::Err: Display,
237{
238 fn from(v: T) -> BigInt<T> {
239 BigInt(v)
240 }
241}
242
243impl<T> Deref for BigInt<T>
244where
245 T: Display + FromStr,
246 <T as FromStr>::Err: Display,
247{
248 type Target = T;
249
250 fn deref(&self) -> &Self::Target {
251 &self.0
252 }
253}
254
255impl<T> Display for BigInt<T>
256where
257 T: Display + FromStr,
258 <T as FromStr>::Err: Display,
259{
260 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
261 write!(f, "{}", self.0)
262 }
263}
264
265#[serde_as]
266#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, JsonSchema)]
267pub struct SequenceNumber(#[schemars(with = "BigInt<u64>")] u64);
268
269impl SerializeAs<crate::base_types::SequenceNumber> for SequenceNumber {
270 fn serialize_as<S>(
271 value: &crate::base_types::SequenceNumber,
272 serializer: S,
273 ) -> Result<S::Ok, S::Error>
274 where
275 S: Serializer,
276 {
277 let s = value.value().to_string();
278 s.serialize(serializer)
279 }
280}
281
282impl<'de> DeserializeAs<'de, crate::base_types::SequenceNumber> for SequenceNumber {
283 fn deserialize_as<D>(deserializer: D) -> Result<crate::base_types::SequenceNumber, D::Error>
284 where
285 D: Deserializer<'de>,
286 {
287 let b = BigInt::deserialize(deserializer)?;
288 Ok(crate::base_types::SequenceNumber::from_u64(*b))
289 }
290}
291
292#[serde_as]
293#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, JsonSchema)]
294#[serde(rename = "ProtocolVersion")]
295pub struct AsProtocolVersion(#[schemars(with = "BigInt<u64>")] u64);
296
297impl SerializeAs<ProtocolVersion> for AsProtocolVersion {
298 fn serialize_as<S>(value: &ProtocolVersion, serializer: S) -> Result<S::Ok, S::Error>
299 where
300 S: Serializer,
301 {
302 let s = value.as_u64().to_string();
303 s.serialize(serializer)
304 }
305}
306
307impl<'de> DeserializeAs<'de, ProtocolVersion> for AsProtocolVersion {
308 fn deserialize_as<D>(deserializer: D) -> Result<ProtocolVersion, D::Error>
309 where
310 D: Deserializer<'de>,
311 {
312 let b = BigInt::<u64>::deserialize(deserializer)?;
313 Ok(ProtocolVersion::from(*b))
314 }
315}
316
317pub(crate) struct IotaBitmap;
320
321impl SerializeAs<roaring::RoaringBitmap> for IotaBitmap {
322 fn serialize_as<S>(source: &roaring::RoaringBitmap, serializer: S) -> Result<S::Ok, S::Error>
323 where
324 S: Serializer,
325 {
326 let mut bytes = vec![];
327
328 source
329 .serialize_into(&mut bytes)
330 .map_err(to_custom_ser_error::<S, _>)?;
331 Bytes::serialize_as(&bytes, serializer)
332 }
333}
334
335impl<'de> DeserializeAs<'de, roaring::RoaringBitmap> for IotaBitmap {
336 fn deserialize_as<D>(deserializer: D) -> Result<roaring::RoaringBitmap, D::Error>
337 where
338 D: Deserializer<'de>,
339 {
340 let bytes: Vec<u8> = Bytes::deserialize_as(deserializer)?;
341 deserialize_iota_bitmap(&bytes).map_err(to_custom_deser_error::<'de, D, _>)
342 }
343}
344
345fn deserialize_iota_bitmap(bytes: &[u8]) -> std::io::Result<roaring::RoaringBitmap> {
350 roaring::RoaringBitmap::deserialize_from(bytes)
351}
352
353#[cfg(test)]
354mod test {
355 use base64::Engine as _;
356
357 use super::*;
358
359 #[test]
360 fn test_iota_bitmap_rejects_unsorted_keys() {
361 let raw = "OjAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAAAFoAAABcAAAAXgAAAGAAAABiAAAAZAAAAGYAAABoAAAAagAAAAEAAQABAAEAAQABAAEAAQABAAEA";
364 let bytes = base64::engine::general_purpose::STANDARD
365 .decode(raw)
366 .unwrap();
367
368 assert!(deserialize_iota_bitmap(&bytes[..]).is_err());
369 }
370
371 #[test]
372 fn test_iota_bitmap_valid_roundtrip() {
373 let mut original = roaring::RoaringBitmap::new();
375 original.insert(1);
376 original.insert(42);
377 original.insert(100);
378
379 let mut bytes = vec![];
380 original.serialize_into(&mut bytes).unwrap();
381
382 let result = deserialize_iota_bitmap(&bytes[..]).unwrap();
383 assert_eq!(result.len(), 3);
384 let values: Vec<u32> = result.iter().collect();
385 assert_eq!(values, vec![1, 42, 100]);
386 }
387}