openzeppelin_relayer/utils/serde/
u64_deserializer.rs

1//! Deserialization utilities for u64 values
2//!
3//! This module provides a custom deserializer for u64 values.
4
5use std::fmt;
6
7use serde::{de, Deserializer};
8
9#[derive(Debug)]
10struct U64Visitor;
11
12impl de::Visitor<'_> for U64Visitor {
13    type Value = u64;
14
15    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
16        formatter.write_str("a string containing a u64 number or a u64 integer")
17    }
18
19    // Handle string inputs like "340282366920938463463374607431768211455"
20    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
21    where
22        E: de::Error,
23    {
24        value.parse::<u64>().map_err(de::Error::custom)
25    }
26
27    // Handle u64 inputs
28    #[allow(clippy::unnecessary_cast)]
29    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
30    where
31        E: de::Error,
32    {
33        Ok(value)
34    }
35
36    // Handle i64 inputs
37    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
38    where
39        E: de::Error,
40    {
41        if value < 0 {
42            Err(de::Error::custom(
43                "negative value cannot be converted to u64",
44            ))
45        } else {
46            Ok(value as u64)
47        }
48    }
49}
50
51pub fn deserialize_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
52where
53    D: Deserializer<'de>,
54{
55    deserializer.deserialize_any(U64Visitor)
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use serde::de::value::{
62        Error as ValueError, I64Deserializer, StringDeserializer, U64Deserializer,
63    };
64
65    #[test]
66    fn test_deserialize_from_string() {
67        let input = "12345";
68        let deserializer = StringDeserializer::<ValueError>::new(input.to_string());
69        let result = deserialize_u64(deserializer);
70        assert!(result.is_ok());
71        assert_eq!(result.unwrap(), 12345);
72    }
73
74    #[test]
75    fn test_deserialize_from_string_max_u64() {
76        let input = "18446744073709551615"; // u64::MAX
77        let deserializer = StringDeserializer::<ValueError>::new(input.to_string());
78        let result = deserialize_u64(deserializer);
79        assert!(result.is_ok());
80        assert_eq!(result.unwrap(), u64::MAX);
81    }
82
83    #[test]
84    fn test_deserialize_from_invalid_string() {
85        let input = "not a number";
86        let deserializer = StringDeserializer::<ValueError>::new(input.to_string());
87        let result = deserialize_u64(deserializer);
88        assert!(result.is_err());
89    }
90
91    #[test]
92    fn test_deserialize_from_u64() {
93        let input: u64 = 54321;
94        let deserializer = U64Deserializer::<ValueError>::new(input);
95        let result = deserialize_u64(deserializer);
96        assert!(result.is_ok());
97        assert_eq!(result.unwrap(), 54321);
98    }
99
100    #[test]
101    fn test_deserialize_from_i64_positive() {
102        let input: i64 = 9876;
103        let deserializer = I64Deserializer::<ValueError>::new(input);
104        let result = deserialize_u64(deserializer);
105        assert!(result.is_ok());
106        assert_eq!(result.unwrap(), 9876);
107    }
108
109    #[test]
110    fn test_deserialize_from_i64_negative() {
111        let input: i64 = -123;
112        let deserializer = I64Deserializer::<ValueError>::new(input);
113        let result = deserialize_u64(deserializer);
114        assert!(result.is_err());
115    }
116}