serde_utils/
quoted_u64_vec.rs

1//! Formats `Vec<u64>` using quotes.
2//!
3//! E.g., `vec![0, 1, 2]` serializes as `["0", "1", "2"]`.
4//!
5//! Quotes can be optional during decoding.
6
7use serde::ser::SerializeSeq;
8use serde::{Deserializer, Serializer};
9use serde_derive::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct QuotedIntWrapper {
14    #[serde(with = "crate::quoted_u64")]
15    pub int: u64,
16}
17
18pub struct QuotedIntVecVisitor;
19impl<'a> serde::de::Visitor<'a> for QuotedIntVecVisitor {
20    type Value = Vec<u64>;
21
22    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
23        write!(formatter, "a list of quoted or unquoted integers")
24    }
25
26    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
27    where
28        A: serde::de::SeqAccess<'a>,
29    {
30        let mut vec = vec![];
31
32        while let Some(val) = seq.next_element()? {
33            let val: QuotedIntWrapper = val;
34            vec.push(val.int);
35        }
36
37        Ok(vec)
38    }
39}
40
41pub fn serialize<S>(value: &[u64], serializer: S) -> Result<S::Ok, S::Error>
42where
43    S: Serializer,
44{
45    let mut seq = serializer.serialize_seq(Some(value.len()))?;
46    for &int in value {
47        seq.serialize_element(&QuotedIntWrapper { int })?;
48    }
49    seq.end()
50}
51
52pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u64>, D::Error>
53where
54    D: Deserializer<'de>,
55{
56    deserializer.deserialize_any(QuotedIntVecVisitor)
57}
58
59#[cfg(test)]
60mod test {
61    use super::*;
62
63    #[derive(Debug, Serialize, Deserialize)]
64    struct Obj {
65        #[serde(with = "crate::quoted_u64_vec")]
66        values: Vec<u64>,
67    }
68
69    #[test]
70    fn quoted_list_success() {
71        let obj: Obj = serde_json::from_str(r#"{ "values": ["1", "2", "3", "4"] }"#).unwrap();
72        assert_eq!(obj.values, vec![1, 2, 3, 4]);
73    }
74
75    #[test]
76    fn unquoted_list_success() {
77        let obj: Obj = serde_json::from_str(r#"{ "values": [1, 2, 3, 4] }"#).unwrap();
78        assert_eq!(obj.values, vec![1, 2, 3, 4]);
79    }
80
81    #[test]
82    fn mixed_list_success() {
83        let obj: Obj = serde_json::from_str(r#"{ "values": ["1", 2, "3", "4"] }"#).unwrap();
84        assert_eq!(obj.values, vec![1, 2, 3, 4]);
85    }
86
87    #[test]
88    fn empty_list_success() {
89        let obj: Obj = serde_json::from_str(r#"{ "values": [] }"#).unwrap();
90        assert!(obj.values.is_empty());
91    }
92
93    #[test]
94    fn whole_list_quoted_err() {
95        serde_json::from_str::<Obj>(r#"{ "values": "[1, 2, 3, 4]" }"#).unwrap_err();
96    }
97}