tenderdash_proto/serializers/
part_set_header_total.rs

1//! Serialize and deserialize part_set_header.total (from string or u32), (into
2//! u32 in part_set_header.total).
3//!
4//! The deserializer is created for backwards compatibility: `total` was changed
5//! from a string-quoted integer value into an integer value without quotes in
6//! Tendermint Core v0.34.0. This deserializer allows backwards-compatibility by
7//! deserializing both ways. See also: <https://github.com/informalsystems/tendermint-rs/issues/679>
8
9#[cfg(not(feature = "std"))]
10use core::{convert::TryFrom, fmt::Formatter};
11#[cfg(feature = "std")]
12use std::fmt::Formatter;
13
14use serde::{
15    Deserializer, Serialize, Serializer,
16    de::{Error, Visitor},
17};
18
19use crate::prelude::*;
20
21struct PartSetHeaderTotalStringOrU32;
22
23/// Deserialize (string or u32) into u32(part_set_header.total)
24pub fn deserialize<'de, D>(deserializer: D) -> Result<u32, D::Error>
25where
26    D: Deserializer<'de>,
27{
28    deserializer.deserialize_any(PartSetHeaderTotalStringOrU32)
29}
30
31/// Serialize from u32(part_set_header.total) into u32
32pub fn serialize<S>(value: &u32, serializer: S) -> Result<S::Ok, S::Error>
33where
34    S: Serializer,
35{
36    value.serialize(serializer)
37}
38
39impl<'de> Visitor<'de> for PartSetHeaderTotalStringOrU32 {
40    type Value = u32;
41
42    fn expecting(&self, formatter: &mut Formatter<'_>) -> core::fmt::Result {
43        formatter.write_str("an integer or string between 0 and 2^32")
44    }
45
46    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
47    where
48        E: Error,
49    {
50        u32::try_from(v).map_err(|e| E::custom(format!("part_set_header.total {e}")))
51    }
52
53    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
54    where
55        E: Error,
56    {
57        u32::try_from(v).map_err(|e| E::custom(format!("part_set_header.total {e}")))
58    }
59
60    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
61    where
62        E: Error,
63    {
64        v.parse::<u32>()
65            .map_err(|e| E::custom(format!("part_set_header.total {e}")))
66    }
67}