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