Skip to main content

tycho_common/
serde_primitives.rs

1use std::{collections::HashMap, fmt, hash::Hash, marker::PhantomData};
2
3use hex::FromHexError;
4use serde::{de, Deserialize, Deserializer};
5
6use crate::Bytes;
7
8/// Decodes a hex string with an optional `0x` prefix. An odd number of digits has an implied
9/// leading zero.
10fn decode_hex_with_prefix(val: &str) -> Result<Vec<u8>, FromHexError> {
11    let digits = val
12        .strip_prefix("0x")
13        .unwrap_or(val)
14        .as_bytes();
15    let mut out = vec![0u8; digits.len().div_ceil(2)];
16    if digits.len().is_multiple_of(2) {
17        hex::decode_to_slice(digits, &mut out)?;
18    } else if let (Some((first, rest)), Some((first_out, rest_out))) =
19        (digits.split_first(), out.split_first_mut())
20    {
21        hex::decode_to_slice([b'0', *first], std::slice::from_mut(first_out))?;
22        hex::decode_to_slice(rest, rest_out)?;
23    }
24    Ok(out)
25}
26
27/// Bytes decoded from a hex string. The string is decoded where the deserializer holds it, without
28/// copying it into a `String` first.
29struct HexValue(Vec<u8>);
30
31impl<'de> Deserialize<'de> for HexValue {
32    fn deserialize<D>(d: D) -> Result<Self, D::Error>
33    where
34        D: Deserializer<'de>,
35    {
36        struct HexVisitor;
37
38        impl de::Visitor<'_> for HexVisitor {
39            type Value = HexValue;
40
41            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
42                f.write_str("a hex string")
43            }
44
45            fn visit_str<E: de::Error>(self, value: &str) -> Result<HexValue, E> {
46                decode_hex_with_prefix(value)
47                    .map(HexValue)
48                    .map_err(|e| E::custom(e.to_string()))
49            }
50        }
51
52        d.deserialize_str(HexVisitor)
53    }
54}
55
56impl From<HexValue> for Bytes {
57    fn from(value: HexValue) -> Self {
58        Bytes::from(value.0)
59    }
60}
61
62/// Deserializes a map straight into its final types: each entry is read as `(KR, VR)` and
63/// converted, with no intermediate map.
64fn deserialize_map<'de, D, KR, VR, K, V>(d: D) -> Result<HashMap<K, V>, D::Error>
65where
66    D: Deserializer<'de>,
67    KR: Deserialize<'de> + Into<K>,
68    VR: Deserialize<'de> + Into<V>,
69    K: Eq + Hash,
70{
71    struct MapVisitor<KR, VR, K, V>(PhantomData<(KR, VR, K, V)>);
72
73    impl<'de, KR, VR, K, V> de::Visitor<'de> for MapVisitor<KR, VR, K, V>
74    where
75        KR: Deserialize<'de> + Into<K>,
76        VR: Deserialize<'de> + Into<V>,
77        K: Eq + Hash,
78    {
79        type Value = HashMap<K, V>;
80
81        fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
82            f.write_str("a map")
83        }
84
85        fn visit_map<A: de::MapAccess<'de>>(self, mut access: A) -> Result<Self::Value, A::Error> {
86            let mut map = HashMap::with_capacity(access.size_hint().unwrap_or(0));
87            while let Some((key, value)) = access.next_entry::<KR, VR>()? {
88                map.insert(key.into(), value.into());
89            }
90            Ok(map)
91        }
92    }
93
94    d.deserialize_map(MapVisitor::<KR, VR, K, V>(PhantomData))
95}
96
97/// A buffer for writing bytes as `0x`-prefixed lowercase hex.
98///
99/// Reusing one buffer for many values allocates only when a value is longer than every value
100/// before it.
101#[derive(Default)]
102struct HexBuffer(Vec<u8>);
103
104impl HexBuffer {
105    /// Returns `bytes` as `0x` followed by two lowercase hex digits per byte. Empty input gives
106    /// `"0x"`. The string borrows the buffer and is valid until the next call.
107    ///
108    /// # Errors
109    ///
110    /// Returns a serializer error if the hex string length overflows `usize`.
111    fn encode<E: serde::ser::Error>(&mut self, bytes: &[u8]) -> Result<&str, E> {
112        let hex_len = bytes
113            .len()
114            .checked_mul(2)
115            .and_then(|digits| digits.checked_add(2))
116            .ok_or_else(|| {
117                E::custom(format!("cannot hex encode {} bytes: length overflows", bytes.len()))
118            })?;
119        self.0.clear();
120        self.0.extend_from_slice(b"0x");
121        self.0.resize(hex_len, 0);
122        let digits = self
123            .0
124            .get_mut(2..)
125            .ok_or_else(|| E::custom("hex buffer is shorter than its prefix"))?;
126        hex::encode_to_slice(bytes, digits).map_err(E::custom)?;
127        std::str::from_utf8(&self.0).map_err(E::custom)
128    }
129}
130
131/// serde functions for handling bytes as hex strings, such as [bytes::Bytes]
132pub mod hex_bytes {
133    use serde::{Deserialize, Deserializer, Serializer};
134
135    use super::{HexBuffer, HexValue};
136
137    /// Serialize a byte vec as a hex string with 0x prefix
138    pub fn serialize<S, T>(x: T, s: S) -> Result<S::Ok, S::Error>
139    where
140        S: Serializer,
141        T: AsRef<[u8]>,
142    {
143        s.serialize_str(HexBuffer::default().encode(x.as_ref())?)
144    }
145
146    /// Deserialize a hex string into a byte vec
147    /// Accepts a hex string with optional 0x prefix
148    pub fn deserialize<'de, T, D>(d: D) -> Result<T, D::Error>
149    where
150        D: Deserializer<'de>,
151        T: From<Vec<u8>>,
152    {
153        HexValue::deserialize(d).map(|value| value.0.into())
154    }
155}
156
157/// serde functions for handling Option of bytes
158pub mod hex_bytes_option {
159    use serde::{Deserialize, Deserializer, Serializer};
160
161    use super::{HexBuffer, HexValue};
162
163    /// Serialize a byte vec as a Some hex string with 0x prefix
164    pub fn serialize<S, T>(x: &Option<T>, s: S) -> Result<S::Ok, S::Error>
165    where
166        S: Serializer,
167        T: AsRef<[u8]>,
168    {
169        if let Some(x) = x {
170            s.serialize_str(HexBuffer::default().encode(x.as_ref())?)
171        } else {
172            s.serialize_none()
173        }
174    }
175
176    /// Deserialize a hex string into a byte vec or None
177    /// Accepts a hex string with optional 0x prefix
178    pub fn deserialize<'de, T, D>(d: D) -> Result<Option<T>, D::Error>
179    where
180        D: Deserializer<'de>,
181        T: From<Vec<u8>>,
182    {
183        let value: Option<HexValue> = Option::deserialize(d)?;
184        Ok(value.map(|value| value.0.into()))
185    }
186}
187
188/// serde functions for handling HashMap with a bytes key
189pub mod hex_hashmap_key {
190    use std::collections::HashMap;
191
192    use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
193
194    use super::{deserialize_map, HexBuffer, HexValue};
195    use crate::Bytes;
196
197    pub fn serialize<S, V>(x: &HashMap<Bytes, V>, s: S) -> Result<S::Ok, S::Error>
198    where
199        S: Serializer,
200        V: Serialize,
201    {
202        let mut key_hex = HexBuffer::default();
203        let mut map = s.serialize_map(Some(x.len()))?;
204        for (k, v) in x.iter() {
205            map.serialize_entry(key_hex.encode(k)?, v)?;
206        }
207        map.end()
208    }
209
210    pub fn deserialize<'de, V, D>(d: D) -> Result<HashMap<Bytes, V>, D::Error>
211    where
212        D: Deserializer<'de>,
213        V: Deserialize<'de>,
214    {
215        deserialize_map::<D, HexValue, V, Bytes, V>(d)
216    }
217}
218
219/// serde functions for handling Vec of Bytes as hex strings
220pub mod hex_bytes_vec {
221    use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serializer};
222
223    use super::{HexBuffer, HexValue};
224
225    /// Serialize Vec<Vec<u8>> as a list of hex strings with 0x prefix
226    pub fn serialize<S>(list: &[Vec<u8>], s: S) -> Result<S::Ok, S::Error>
227    where
228        S: Serializer,
229    {
230        let mut hex = HexBuffer::default();
231        let mut seq = s.serialize_seq(Some(list.len()))?;
232        for x in list {
233            seq.serialize_element(hex.encode(x)?)?;
234        }
235        seq.end()
236    }
237
238    /// Deserialize a list of hex strings into Vec<Vec<u8>>
239    pub fn deserialize<'de, D>(d: D) -> Result<Vec<Vec<u8>>, D::Error>
240    where
241        D: Deserializer<'de>,
242    {
243        let values = Vec::<HexValue>::deserialize(d)?;
244        Ok(values
245            .into_iter()
246            .map(|value| value.0)
247            .collect())
248    }
249}
250
251/// serde functions for handling HashMap with bytes value
252pub mod hex_hashmap_value {
253    use std::collections::HashMap;
254
255    use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
256
257    use super::{deserialize_map, HexBuffer, HexValue};
258    use crate::Bytes;
259
260    pub fn serialize<S, K>(x: &HashMap<K, Bytes>, s: S) -> Result<S::Ok, S::Error>
261    where
262        S: Serializer,
263        K: Serialize,
264    {
265        let mut value_hex = HexBuffer::default();
266        let mut map = s.serialize_map(Some(x.len()))?;
267        for (k, v) in x.iter() {
268            map.serialize_entry(k, value_hex.encode(v)?)?;
269        }
270        map.end()
271    }
272
273    pub fn deserialize<'de, K, D>(d: D) -> Result<HashMap<K, Bytes>, D::Error>
274    where
275        D: Deserializer<'de>,
276        K: Deserialize<'de> + Eq + std::hash::Hash, // HashMap key trait bounds
277    {
278        deserialize_map::<D, K, HexValue, K, Bytes>(d)
279    }
280}
281
282/// serde functions for handling HashMap with a bytes key and value
283pub mod hex_hashmap_key_value {
284    use std::collections::HashMap;
285
286    use serde::{ser::SerializeMap, Deserializer, Serializer};
287
288    use super::{deserialize_map, HexBuffer, HexValue};
289    use crate::Bytes;
290
291    pub fn serialize<S>(x: &HashMap<Bytes, Bytes>, s: S) -> Result<S::Ok, S::Error>
292    where
293        S: Serializer,
294    {
295        let (mut key_hex, mut value_hex) = (HexBuffer::default(), HexBuffer::default());
296        let mut map = s.serialize_map(Some(x.len()))?;
297        for (k, v) in x.iter() {
298            map.serialize_entry(key_hex.encode(k)?, value_hex.encode(v)?)?;
299        }
300        map.end()
301    }
302
303    pub fn deserialize<'de, D>(d: D) -> Result<HashMap<Bytes, Bytes>, D::Error>
304    where
305        D: Deserializer<'de>,
306    {
307        deserialize_map::<D, HexValue, HexValue, Bytes, Bytes>(d)
308    }
309}
310
311#[cfg(test)]
312mod tests {
313    use std::collections::HashMap;
314
315    use serde::{Deserialize, Serialize};
316
317    use super::*;
318    use crate::Bytes;
319
320    #[derive(Debug, Serialize, Deserialize)]
321    struct TestStruct {
322        #[serde(with = "hex_bytes")]
323        bytes: Vec<u8>,
324
325        #[serde(with = "hex_bytes_option")]
326        bytes_option: Option<Vec<u8>>,
327
328        #[serde(with = "hex_bytes_vec")]
329        bytes_vec: Vec<Vec<u8>>,
330    }
331
332    #[test]
333    fn hex_bytes_serialize_deserialize() {
334        let test_struct = TestStruct {
335            bytes: vec![0u8; 10],
336            bytes_option: Some(vec![0u8; 10]),
337            bytes_vec: vec![vec![0, 1, 2, 3], vec![0xFF, 0xAB]],
338        };
339
340        // Serialize to JSON
341        let serialized = serde_json::to_string(&test_struct).unwrap();
342        assert_eq!(
343            serialized,
344            "{\"bytes\":\"0x00000000000000000000\",\"bytes_option\":\"0x00000000000000000000\",\"bytes_vec\":[\"0x00010203\",\"0xffab\"]}"
345        );
346
347        // Deserialize from JSON
348        let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
349        assert_eq!(deserialized.bytes, vec![0u8; 10]);
350        assert_eq!(deserialized.bytes_option, Some(vec![0u8; 10]));
351        assert_eq!(deserialized.bytes_vec, vec![vec![0, 1, 2, 3], vec![0xFF, 0xAB]]);
352    }
353
354    #[test]
355    fn hex_bytes_option_none() {
356        let test_struct =
357            TestStruct { bytes: vec![0u8; 10], bytes_option: None, bytes_vec: vec![] };
358
359        // Serialize to JSON
360        let serialized = serde_json::to_string(&test_struct).unwrap();
361        assert_eq!(
362            serialized,
363            "{\"bytes\":\"0x00000000000000000000\",\"bytes_option\":null,\"bytes_vec\":[]}"
364        );
365
366        // Deserialize from JSON
367        let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
368        assert_eq!(deserialized.bytes, vec![0u8; 10]);
369        assert_eq!(deserialized.bytes_option, None);
370    }
371
372    /// Serializers that format every value with `format!`: the expected output for the ones above.
373    mod reference {
374        use std::collections::HashMap;
375
376        use serde::{ser::SerializeMap, Serialize, Serializer};
377
378        use crate::Bytes;
379
380        pub fn hex(x: &[u8]) -> String {
381            format!("0x{}", hex::encode(x))
382        }
383
384        pub fn hex_bytes<S: Serializer>(x: &[u8], s: S) -> Result<S::Ok, S::Error> {
385            s.serialize_str(&hex(x))
386        }
387
388        pub fn hex_bytes_option<S: Serializer>(
389            x: &Option<Vec<u8>>,
390            s: S,
391        ) -> Result<S::Ok, S::Error> {
392            match x {
393                Some(x) => s.serialize_str(&hex(x)),
394                None => s.serialize_none(),
395            }
396        }
397
398        pub fn hex_bytes_vec<S: Serializer>(list: &[Vec<u8>], s: S) -> Result<S::Ok, S::Error> {
399            list.iter()
400                .map(|x| hex(x))
401                .collect::<Vec<_>>()
402                .serialize(s)
403        }
404
405        pub fn hex_hashmap_key<S: Serializer>(
406            x: &HashMap<Bytes, Bytes>,
407            s: S,
408        ) -> Result<S::Ok, S::Error> {
409            let mut map = s.serialize_map(Some(x.len()))?;
410            for (k, v) in x.iter() {
411                map.serialize_entry(&format!("{k:#x}"), v)?;
412            }
413            map.end()
414        }
415
416        pub fn hex_hashmap_value<S: Serializer>(
417            x: &HashMap<Bytes, Bytes>,
418            s: S,
419        ) -> Result<S::Ok, S::Error> {
420            let mut map = s.serialize_map(Some(x.len()))?;
421            for (k, v) in x.iter() {
422                map.serialize_entry(k, &format!("{v:#x}"))?;
423            }
424            map.end()
425        }
426
427        pub fn hex_hashmap_key_value<S: Serializer>(
428            x: &HashMap<Bytes, Bytes>,
429            s: S,
430        ) -> Result<S::Ok, S::Error> {
431            let mut map = s.serialize_map(Some(x.len()))?;
432            for (k, v) in x.iter() {
433                map.serialize_entry(&format!("{k:#x}"), &format!("{v:#x}"))?;
434            }
435            map.end()
436        }
437
438        /// Decodes by copying the digits and prepending a zero to an odd count.
439        pub fn decode(val: &str) -> Result<Vec<u8>, hex::FromHexError> {
440            let mut digits: String = val
441                .strip_prefix("0x")
442                .unwrap_or(val)
443                .into();
444            if !digits.len().is_multiple_of(2) {
445                digits.insert(0, '0');
446            }
447            hex::decode(&digits)
448        }
449    }
450
451    #[derive(Serialize)]
452    struct CurrentBytes<'a> {
453        #[serde(with = "hex_bytes")]
454        bytes: &'a Vec<u8>,
455        #[serde(with = "hex_bytes_option")]
456        bytes_option: &'a Option<Vec<u8>>,
457        #[serde(with = "hex_bytes_vec")]
458        bytes_vec: &'a Vec<Vec<u8>>,
459    }
460
461    #[derive(Serialize)]
462    struct ReferenceBytes<'a> {
463        #[serde(serialize_with = "reference::hex_bytes")]
464        bytes: &'a Vec<u8>,
465        #[serde(serialize_with = "reference::hex_bytes_option")]
466        bytes_option: &'a Option<Vec<u8>>,
467        #[serde(serialize_with = "reference::hex_bytes_vec")]
468        bytes_vec: &'a Vec<Vec<u8>>,
469    }
470
471    #[derive(Serialize)]
472    struct CurrentMaps<'a> {
473        #[serde(with = "hex_hashmap_key")]
474        key: &'a HashMap<Bytes, Bytes>,
475        #[serde(with = "hex_hashmap_value")]
476        value: &'a HashMap<Bytes, Bytes>,
477        #[serde(with = "hex_hashmap_key_value")]
478        key_value: &'a HashMap<Bytes, Bytes>,
479    }
480
481    #[derive(Serialize)]
482    struct ReferenceMaps<'a> {
483        #[serde(serialize_with = "reference::hex_hashmap_key")]
484        key: &'a HashMap<Bytes, Bytes>,
485        #[serde(serialize_with = "reference::hex_hashmap_value")]
486        value: &'a HashMap<Bytes, Bytes>,
487        #[serde(serialize_with = "reference::hex_hashmap_key_value")]
488        key_value: &'a HashMap<Bytes, Bytes>,
489    }
490
491    /// Empty, single bytes, leading zeros, a full word, and values longer than any slot: the
492    /// largest contract code, odd lengths and 128 KiB.
493    fn hex_cases() -> Vec<Vec<u8>> {
494        let long = |len: usize| {
495            (0..len)
496                .map(|i| (i * 31 % 256) as u8)
497                .collect()
498        };
499        vec![
500            vec![],
501            vec![0],
502            vec![0x0a],
503            vec![0xff],
504            vec![0, 0, 1],
505            vec![0xff; 32],
506            (0..32).collect(),
507            long(33),
508            long(24_576),
509            long(24_577),
510            long((1 << 17) + 3),
511        ]
512    }
513
514    #[test]
515    fn hex_bytes_serializers_write_the_same_json_as_formatting_each_value() {
516        let cases = hex_cases();
517        for value in &cases {
518            let option = Some(value.clone());
519            let current = CurrentBytes { bytes: value, bytes_option: &option, bytes_vec: &cases };
520            let reference =
521                ReferenceBytes { bytes: value, bytes_option: &option, bytes_vec: &cases };
522
523            assert!(
524                serde_json::to_vec(&current).unwrap() == serde_json::to_vec(&reference).unwrap(),
525                "output differs for a {}-byte value",
526                value.len()
527            );
528        }
529    }
530
531    #[test]
532    fn hex_hashmap_serializers_write_the_same_json_as_formatting_each_entry() {
533        let cases = hex_cases();
534        // Each key is a case followed by its index and a value prefix, so that keys are distinct
535        // and short and long keys sit next to short and long values.
536        let mut map = HashMap::new();
537        for (i, key) in cases.iter().enumerate() {
538            for value in &cases {
539                let mut key = key.clone();
540                key.push(i as u8);
541                key.extend_from_slice(&value[..value.len().min(40)]);
542                map.insert(Bytes::from(key), Bytes::from(value.clone()));
543            }
544        }
545
546        let current = CurrentMaps { key: &map, value: &map, key_value: &map };
547        let reference = ReferenceMaps { key: &map, value: &map, key_value: &map };
548
549        assert!(serde_json::to_vec(&current).unwrap() == serde_json::to_vec(&reference).unwrap());
550    }
551
552    #[test]
553    fn hex_serializers_round_trip_long_values() {
554        let test_struct = TestStruct {
555            bytes: hex_cases().pop().unwrap(),
556            bytes_option: Some(vec![]),
557            bytes_vec: hex_cases(),
558        };
559
560        let serialized = serde_json::to_string(&test_struct).unwrap();
561        let deserialized: TestStruct = serde_json::from_str(&serialized).unwrap();
562
563        assert_eq!(deserialized.bytes, test_struct.bytes);
564        assert_eq!(deserialized.bytes_option, Some(vec![]));
565        assert_eq!(deserialized.bytes_vec, test_struct.bytes_vec);
566    }
567
568    /// Every case as lowercase and uppercase digits, with and without the prefix, and with an odd
569    /// number of digits where the first one is a zero.
570    fn hex_strings() -> Vec<String> {
571        let mut strings = vec![];
572        for value in hex_cases() {
573            let digits = hex::encode(&value);
574            for digits in [digits.clone(), digits.to_uppercase()] {
575                strings.push(format!("0x{digits}"));
576                strings.push(digits.clone());
577                if let Some(odd) = digits.strip_prefix('0') {
578                    strings.push(format!("0x{odd}"));
579                    strings.push(odd.to_string());
580                }
581            }
582        }
583        strings
584    }
585
586    #[test]
587    fn decode_hex_with_prefix_reads_the_same_bytes_as_the_reference_decoder() {
588        for string in hex_strings() {
589            assert_eq!(
590                decode_hex_with_prefix(&string).unwrap(),
591                reference::decode(&string).unwrap(),
592                "differs for {}",
593                &string[..string.len().min(20)]
594            );
595        }
596    }
597
598    #[test]
599    fn decode_hex_with_prefix_rejects_what_the_reference_decoder_rejects() {
600        for string in ["0xzz", "0x1g", "0xg", "g", "0x0x", "é", "0xé", "0x0é", "é0", "0x é", "0x-1"]
601        {
602            assert!(reference::decode(string).is_err(), "reference accepts {string}");
603            assert!(decode_hex_with_prefix(string).is_err(), "accepts {string}");
604        }
605    }
606
607    #[derive(Debug, PartialEq, Deserialize)]
608    struct DecodedMaps {
609        #[serde(with = "hex_hashmap_key")]
610        key: HashMap<Bytes, u64>,
611        #[serde(with = "hex_hashmap_value")]
612        value: HashMap<String, Bytes>,
613        #[serde(with = "hex_hashmap_key_value")]
614        key_value: HashMap<Bytes, Bytes>,
615    }
616
617    #[test]
618    fn hex_deserializers_read_borrowed_escaped_and_owned_strings() {
619        // "\u0030x0a" is "0x0a" with an escaped first character: the deserializer can't lend it
620        // from the input.
621        let json = r#"{
622            "key": {"0x0a": 1, "\u0030x0b": 2},
623            "value": {"a": "0x0c", "b": "\u0030x0d"},
624            "key_value": {"0x01": "0x0002", "3": "0xff", "\u0030x04": "0x"}
625        }"#;
626        let expected = DecodedMaps {
627            key: HashMap::from([(Bytes::from(vec![0x0a]), 1), (Bytes::from(vec![0x0b]), 2)]),
628            value: HashMap::from([
629                ("a".to_string(), Bytes::from(vec![0x0c])),
630                ("b".to_string(), Bytes::from(vec![0x0d])),
631            ]),
632            key_value: HashMap::from([
633                (Bytes::from(vec![0x01]), Bytes::from(vec![0x00, 0x02])),
634                (Bytes::from(vec![0x03]), Bytes::from(vec![0xff])),
635                (Bytes::from(vec![0x04]), Bytes::from(vec![])),
636            ]),
637        };
638
639        let from_str: DecodedMaps = serde_json::from_str(json).unwrap();
640        let from_reader: DecodedMaps = serde_json::from_reader(json.as_bytes()).unwrap();
641        let value: serde_json::Value = serde_json::from_str(json).unwrap();
642        let from_value: DecodedMaps = serde_json::from_value(value).unwrap();
643
644        assert_eq!(from_str, expected);
645        assert_eq!(from_reader, expected);
646        assert_eq!(from_value, expected);
647    }
648
649    #[test]
650    fn hex_deserializers_reject_invalid_hex_and_non_strings() {
651        let invalid = [
652            r#"{"key": {"0xzz": 1}, "value": {}, "key_value": {}}"#,
653            r#"{"key": {}, "value": {"a": "0x1g"}, "key_value": {}}"#,
654            r#"{"key": {}, "value": {}, "key_value": {"0x01": "é"}}"#,
655            r#"{"key": {}, "value": {"a": 1}, "key_value": {}}"#,
656        ];
657        for json in invalid {
658            assert!(serde_json::from_str::<DecodedMaps>(json).is_err(), "accepts {json}");
659        }
660        assert!(serde_json::from_str::<TestStruct>(
661            r#"{"bytes": 1, "bytes_option": null, "bytes_vec": []}"#
662        )
663        .is_err());
664    }
665}