apache_avro/
bytes.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::cell::Cell;
19
20thread_local! {
21    /// A thread local that is used to decide how to serialize Rust bytes into an Avro
22    /// `types::Value` of type bytes.
23    ///
24    /// Relies on the fact that serde's serialization process is single-threaded.
25    pub(crate) static SER_BYTES_TYPE: Cell<BytesType> = const { Cell::new(BytesType::Bytes) };
26
27    /// A thread local that is used to decide how to deserialize an Avro `types::Value`
28    /// of type bytes into Rust bytes.
29    ///
30    /// Relies on the fact that serde's deserialization process is single-threaded.
31    pub(crate) static DE_BYTES_BORROWED: Cell<bool> = const { Cell::new(false) };
32}
33
34#[derive(Debug, Clone, Copy)]
35pub(crate) enum BytesType {
36    Bytes,
37    Fixed,
38}
39
40/// Efficient (de)serialization of Avro bytes values.
41///
42/// This module is intended to be used through the Serde `with` attribute. Use
43/// [`serde_avro_bytes_opt`](crate::serde_avro_bytes_opt) for optional bytes.
44///
45/// See usage with below example:
46/// ```rust
47/// use apache_avro::{serde_avro_bytes, serde_avro_fixed};
48/// use serde::{Deserialize, Serialize};
49///
50/// #[derive(Serialize, Deserialize)]
51/// struct StructWithBytes {
52///     #[serde(with = "serde_avro_bytes")]
53///     vec_field: Vec<u8>,
54///
55///     #[serde(with = "serde_avro_fixed")]
56///     fixed_field: [u8; 6],
57/// }
58/// ```
59pub mod serde_avro_bytes {
60    use serde::{Deserializer, Serializer};
61
62    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
63    where
64        S: Serializer,
65    {
66        serde_bytes::serialize(bytes, serializer)
67    }
68
69    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        serde_bytes::deserialize(deserializer)
74    }
75}
76
77/// Efficient (de)serialization of optional Avro bytes values.
78///
79/// This module is intended to be used through the Serde `with` attribute. Use
80/// [`serde_avro_bytes`](crate::serde_avro_bytes) for non optional bytes.
81///
82/// See usage with below example:
83/// ```rust
84/// use apache_avro::{serde_avro_bytes_opt, serde_avro_fixed_opt};
85/// use serde::{Deserialize, Serialize};
86///
87/// #[derive(Serialize, Deserialize)]
88/// struct StructWithBytes {
89///     #[serde(with = "serde_avro_bytes_opt")]
90///     vec_field: Option<Vec<u8>>,
91///
92///     #[serde(with = "serde_avro_fixed_opt")]
93///     fixed_field: Option<[u8; 6]>,
94/// }
95/// ```
96pub mod serde_avro_bytes_opt {
97    use serde::{Deserializer, Serializer};
98    use std::borrow::Borrow;
99
100    pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
101    where
102        S: Serializer,
103        B: Borrow<[u8]> + serde_bytes::Serialize,
104    {
105        serde_bytes::serialize(bytes, serializer)
106    }
107
108    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
109    where
110        D: Deserializer<'de>,
111    {
112        serde_bytes::deserialize(deserializer)
113    }
114}
115
116/// Efficient (de)serialization of Avro fixed values.
117///
118/// This module is intended to be used through the Serde `with` attribute. Use
119/// [`serde_avro_fixed_opt`](crate::serde_avro_fixed_opt) for optional fixed values.
120///
121/// See usage with below example:
122/// ```rust
123/// use apache_avro::{serde_avro_bytes, serde_avro_fixed};
124/// use serde::{Deserialize, Serialize};
125///
126/// #[derive(Serialize, Deserialize)]
127/// struct StructWithBytes {
128///     #[serde(with = "serde_avro_bytes")]
129///     vec_field: Vec<u8>,
130///
131///     #[serde(with = "serde_avro_fixed")]
132///     fixed_field: [u8; 6],
133/// }
134/// ```
135pub mod serde_avro_fixed {
136    use super::{BytesType, SER_BYTES_TYPE};
137    use serde::{Deserializer, Serializer};
138
139    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
140    where
141        S: Serializer,
142    {
143        SER_BYTES_TYPE.set(BytesType::Fixed);
144        let res = serde_bytes::serialize(bytes, serializer);
145        SER_BYTES_TYPE.set(BytesType::Bytes);
146        res
147    }
148
149    pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
150    where
151        D: Deserializer<'de>,
152    {
153        serde_bytes::deserialize(deserializer)
154    }
155}
156
157/// Efficient (de)serialization of optional Avro fixed values.
158///
159/// This module is intended to be used through the Serde `with` attribute. Use
160/// [`serde_avro_fixed`](crate::serde_avro_fixed) for non optional fixed values.
161///
162/// See usage with below example:
163/// ```rust
164/// use apache_avro::{serde_avro_bytes_opt, serde_avro_fixed_opt};
165/// use serde::{Deserialize, Serialize};
166///
167/// #[derive(Serialize, Deserialize)]
168/// struct StructWithBytes {
169///     #[serde(with = "serde_avro_bytes_opt")]
170///     vec_field: Option<Vec<u8>>,
171///
172///     #[serde(with = "serde_avro_fixed_opt")]
173///     fixed_field: Option<[u8; 6]>,
174/// }
175/// ```
176pub mod serde_avro_fixed_opt {
177    use super::{BytesType, SER_BYTES_TYPE};
178    use serde::{Deserializer, Serializer};
179    use std::borrow::Borrow;
180
181    pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
182    where
183        S: Serializer,
184        B: Borrow<[u8]> + serde_bytes::Serialize,
185    {
186        SER_BYTES_TYPE.set(BytesType::Fixed);
187        let res = serde_bytes::serialize(bytes, serializer);
188        SER_BYTES_TYPE.set(BytesType::Bytes);
189        res
190    }
191
192    pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<Option<[u8; N]>, D::Error>
193    where
194        D: Deserializer<'de>,
195    {
196        serde_bytes::deserialize(deserializer)
197    }
198}
199
200/// Efficient (de)serialization of Avro bytes/fixed borrowed values.
201///
202/// This module is intended to be used through the Serde `with` attribute. Note that
203/// `bytes: &[u8]` are always serialized as
204/// [`Value::Bytes`](crate::types::Value::Bytes). However, both
205/// [`Value::Bytes`](crate::types::Value::Bytes) and
206/// [`Value::Fixed`](crate::types::Value::Fixed) can be deserialized as `bytes:
207/// &[u8]`. Use [`serde_avro_slice_opt`](crate::serde_avro_slice_opt) for optional
208/// bytes/fixed borrowed values.
209///
210/// See usage with below example:
211/// ```rust
212/// use apache_avro::serde_avro_slice;
213/// use serde::{Deserialize, Serialize};
214///
215/// #[derive(Serialize, Deserialize)]
216/// struct StructWithBytes<'a> {
217///     #[serde(with = "serde_avro_slice")]
218///     slice_field: &'a [u8],
219/// }
220/// ```
221pub mod serde_avro_slice {
222    use super::DE_BYTES_BORROWED;
223    use serde::{Deserializer, Serializer};
224
225    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
226    where
227        S: Serializer,
228    {
229        serde_bytes::serialize(bytes, serializer)
230    }
231
232    pub fn deserialize<'de, D>(deserializer: D) -> Result<&'de [u8], D::Error>
233    where
234        D: Deserializer<'de>,
235    {
236        DE_BYTES_BORROWED.set(true);
237        let res = serde_bytes::deserialize(deserializer);
238        DE_BYTES_BORROWED.set(false);
239        res
240    }
241}
242
243/// Efficient (de)serialization of optional Avro bytes/fixed borrowed values.
244///
245/// This module is intended to be used through the Serde `with` attribute. Note that
246/// `bytes: &[u8]` are always serialized as
247/// [`Value::Bytes`](crate::types::Value::Bytes). However, both
248/// [`Value::Bytes`](crate::types::Value::Bytes) and
249/// [`Value::Fixed`](crate::types::Value::Fixed) can be deserialized as `bytes:
250/// &[u8]`. Use [`serde_avro_slice`](crate::serde_avro_slice) for non optional
251/// bytes/fixed borrowed values.
252///
253/// See usage with below example:
254/// ```rust
255/// use apache_avro::serde_avro_slice_opt;
256/// use serde::{Deserialize, Serialize};
257///
258/// #[derive(Serialize, Deserialize)]
259/// struct StructWithBytes<'a> {
260///     #[serde(with = "serde_avro_slice_opt")]
261///     slice_field: Option<&'a [u8]>,
262/// }
263/// ```
264pub mod serde_avro_slice_opt {
265    use super::DE_BYTES_BORROWED;
266    use serde::{Deserializer, Serializer};
267    use std::borrow::Borrow;
268
269    pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
270    where
271        S: Serializer,
272        B: Borrow<[u8]> + serde_bytes::Serialize,
273    {
274        serde_bytes::serialize(&bytes, serializer)
275    }
276
277    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<&'de [u8]>, D::Error>
278    where
279        D: Deserializer<'de>,
280    {
281        DE_BYTES_BORROWED.set(true);
282        let res = serde_bytes::deserialize(deserializer);
283        DE_BYTES_BORROWED.set(false);
284        res
285    }
286}
287
288#[cfg(test)]
289mod tests {
290    use super::*;
291    use crate::{from_value, to_value, types::Value, Schema};
292    use serde::{Deserialize, Serialize};
293
294    #[test]
295    fn avro_3631_validate_schema_for_struct_with_byte_types() {
296        #[derive(Debug, Serialize)]
297        struct TestStructWithBytes<'a> {
298            #[serde(with = "serde_avro_bytes")]
299            vec_field: Vec<u8>,
300            #[serde(with = "serde_avro_bytes_opt")]
301            vec_field_opt: Option<Vec<u8>>,
302
303            #[serde(with = "serde_avro_fixed")]
304            fixed_field: [u8; 6],
305            #[serde(with = "serde_avro_fixed_opt")]
306            fixed_field_opt: Option<[u8; 7]>,
307
308            #[serde(with = "serde_avro_slice")]
309            slice_field: &'a [u8],
310            #[serde(with = "serde_avro_slice_opt")]
311            slice_field_opt: Option<&'a [u8]>,
312        }
313
314        let test = TestStructWithBytes {
315            vec_field: vec![2, 3, 4],
316            vec_field_opt: Some(vec![2, 3, 4]),
317            fixed_field: [1; 6],
318            fixed_field_opt: Some([1; 7]),
319            slice_field: &[1, 2, 3],
320            slice_field_opt: Some(&[1, 2, 3]),
321        };
322        let value: Value = to_value(test).unwrap();
323        let schema = Schema::parse_str(
324            r#"
325            {
326              "type": "record",
327              "name": "TestStructWithBytes",
328              "fields": [ {
329                "name": "vec_field",
330                "type": "bytes"
331              }, {
332                "name": "vec_field_opt",
333                "type": ["null", "bytes"]
334              }, {
335                "name": "fixed_field",
336                "type": {
337                  "name": "ByteData",
338                  "type": "fixed",
339                  "size": 6
340                }
341              }, {
342                "name": "fixed_field_opt",
343                "type": ["null", {
344                  "name": "ByteData2",
345                  "type": "fixed",
346                  "size": 7
347                } ]
348              }, {
349                "name": "slice_field",
350                "type": "bytes"
351              }, {
352                "name": "slice_field_opt",
353                "type": ["null", "bytes"]
354              } ]
355            }"#,
356        )
357        .unwrap();
358        assert!(value.validate(&schema));
359    }
360
361    #[test]
362    fn avro_3631_deserialize_value_to_struct_with_byte_types() {
363        #[derive(Debug, Deserialize, PartialEq)]
364        struct TestStructWithBytes<'a> {
365            #[serde(with = "serde_avro_bytes")]
366            vec_field: Vec<u8>,
367            #[serde(with = "serde_avro_bytes_opt")]
368            vec_field_opt: Option<Vec<u8>>,
369            #[serde(with = "serde_avro_bytes_opt")]
370            vec_field_opt2: Option<Vec<u8>>,
371
372            #[serde(with = "serde_avro_fixed")]
373            fixed_field: [u8; 6],
374            #[serde(with = "serde_avro_fixed_opt")]
375            fixed_field_opt: Option<[u8; 7]>,
376            #[serde(with = "serde_avro_fixed_opt")]
377            fixed_field_opt2: Option<[u8; 8]>,
378
379            #[serde(with = "serde_avro_slice")]
380            slice_bytes_field: &'a [u8],
381            #[serde(with = "serde_avro_slice_opt")]
382            slice_bytes_field_opt: Option<&'a [u8]>,
383            #[serde(with = "serde_avro_slice_opt")]
384            slice_bytes_field_opt2: Option<&'a [u8]>,
385
386            #[serde(with = "serde_avro_slice")]
387            slice_fixed_field: &'a [u8],
388            #[serde(with = "serde_avro_slice_opt")]
389            slice_fixed_field_opt: Option<&'a [u8]>,
390            #[serde(with = "serde_avro_slice_opt")]
391            slice_fixed_field_opt2: Option<&'a [u8]>,
392        }
393
394        let expected = TestStructWithBytes {
395            vec_field: vec![3, 33],
396            vec_field_opt: Some(vec![4, 44]),
397            vec_field_opt2: None,
398            fixed_field: [1; 6],
399            fixed_field_opt: Some([7; 7]),
400            fixed_field_opt2: None,
401            slice_bytes_field: &[1, 11, 111],
402            slice_bytes_field_opt: Some(&[5, 5, 5, 5, 5]),
403            slice_bytes_field_opt2: None,
404            slice_fixed_field: &[2, 22, 222],
405            slice_fixed_field_opt: Some(&[3, 3, 3]),
406            slice_fixed_field_opt2: None,
407        };
408
409        let value = Value::Record(vec![
410            (
411                "vec_field".to_owned(),
412                Value::Bytes(expected.vec_field.clone()),
413            ),
414            (
415                "vec_field_opt".to_owned(),
416                Value::Union(
417                    1,
418                    Box::new(Value::Bytes(
419                        expected.vec_field_opt.as_ref().unwrap().clone(),
420                    )),
421                ),
422            ),
423            (
424                "vec_field_opt2".to_owned(),
425                Value::Union(0, Box::new(Value::Null)),
426            ),
427            (
428                "fixed_field".to_owned(),
429                Value::Fixed(expected.fixed_field.len(), expected.fixed_field.to_vec()),
430            ),
431            (
432                "fixed_field_opt".to_owned(),
433                Value::Union(
434                    1,
435                    Box::new(Value::Fixed(
436                        expected.fixed_field_opt.as_ref().unwrap().len(),
437                        expected.fixed_field_opt.as_ref().unwrap().to_vec(),
438                    )),
439                ),
440            ),
441            (
442                "fixed_field_opt2".to_owned(),
443                Value::Union(0, Box::new(Value::Null)),
444            ),
445            (
446                "slice_bytes_field".to_owned(),
447                Value::Bytes(expected.slice_bytes_field.to_vec()),
448            ),
449            (
450                "slice_bytes_field_opt".to_owned(),
451                Value::Union(
452                    1,
453                    Box::new(Value::Bytes(
454                        expected.slice_bytes_field_opt.as_ref().unwrap().to_vec(),
455                    )),
456                ),
457            ),
458            (
459                "slice_bytes_field_opt2".to_owned(),
460                Value::Union(0, Box::new(Value::Null)),
461            ),
462            (
463                "slice_fixed_field".to_owned(),
464                Value::Fixed(
465                    expected.slice_fixed_field.len(),
466                    expected.slice_fixed_field.to_vec(),
467                ),
468            ),
469            (
470                "slice_fixed_field_opt".to_owned(),
471                Value::Union(
472                    1,
473                    Box::new(Value::Fixed(
474                        expected.slice_fixed_field_opt.as_ref().unwrap().len(),
475                        expected.slice_fixed_field_opt.as_ref().unwrap().to_vec(),
476                    )),
477                ),
478            ),
479            (
480                "slice_fixed_field_opt2".to_owned(),
481                Value::Union(1, Box::new(Value::Null)),
482            ),
483        ]);
484        assert_eq!(expected, from_value(&value).unwrap());
485    }
486
487    #[test]
488    fn avro_3631_serialize_struct_to_value_with_byte_types() {
489        #[derive(Debug, Serialize)]
490        struct TestStructWithBytes<'a> {
491            array_field: &'a [u8],
492            vec_field: Vec<u8>,
493
494            #[serde(with = "serde_avro_fixed")]
495            vec_field2: Vec<u8>,
496            #[serde(with = "serde_avro_fixed_opt")]
497            vec_field2_opt: Option<Vec<u8>>,
498            #[serde(with = "serde_avro_fixed_opt")]
499            vec_field2_opt2: Option<Vec<u8>>,
500
501            #[serde(with = "serde_avro_bytes")]
502            vec_field3: Vec<u8>,
503            #[serde(with = "serde_avro_bytes_opt")]
504            vec_field3_opt: Option<Vec<u8>>,
505            #[serde(with = "serde_avro_bytes_opt")]
506            vec_field3_opt2: Option<Vec<u8>>,
507
508            #[serde(with = "serde_avro_fixed")]
509            fixed_field: [u8; 6],
510            #[serde(with = "serde_avro_fixed_opt")]
511            fixed_field_opt: Option<[u8; 5]>,
512            #[serde(with = "serde_avro_fixed_opt")]
513            fixed_field_opt2: Option<[u8; 4]>,
514
515            #[serde(with = "serde_avro_fixed")]
516            fixed_field2: &'a [u8],
517            #[serde(with = "serde_avro_fixed_opt")]
518            fixed_field2_opt: Option<&'a [u8]>,
519            #[serde(with = "serde_avro_fixed_opt")]
520            fixed_field2_opt2: Option<&'a [u8]>,
521
522            #[serde(with = "serde_avro_bytes")]
523            bytes_field: &'a [u8],
524            #[serde(with = "serde_avro_bytes_opt")]
525            bytes_field_opt: Option<&'a [u8]>,
526            #[serde(with = "serde_avro_bytes_opt")]
527            bytes_field_opt2: Option<&'a [u8]>,
528
529            #[serde(with = "serde_avro_bytes")]
530            bytes_field2: [u8; 6],
531            #[serde(with = "serde_avro_bytes_opt")]
532            bytes_field2_opt: Option<[u8; 7]>,
533            #[serde(with = "serde_avro_bytes_opt")]
534            bytes_field2_opt2: Option<[u8; 8]>,
535        }
536
537        let test = TestStructWithBytes {
538            array_field: &[1, 11, 111],
539            vec_field: vec![3, 33],
540            vec_field2: vec![4, 44],
541            vec_field2_opt: Some(vec![14, 144]),
542            vec_field2_opt2: None,
543            vec_field3: vec![5, 55],
544            vec_field3_opt: Some(vec![15, 155]),
545            vec_field3_opt2: None,
546            fixed_field: [1; 6],
547            fixed_field_opt: Some([6; 5]),
548            fixed_field_opt2: None,
549            fixed_field2: &[6, 66],
550            fixed_field2_opt: Some(&[7, 77]),
551            fixed_field2_opt2: None,
552            bytes_field: &[2, 22, 222],
553            bytes_field_opt: Some(&[3, 33, 233]),
554            bytes_field_opt2: None,
555            bytes_field2: [2; 6],
556            bytes_field2_opt: Some([2; 7]),
557            bytes_field2_opt2: None,
558        };
559        let expected = Value::Record(vec![
560            (
561                "array_field".to_owned(),
562                Value::Array(
563                    test.array_field
564                        .iter()
565                        .map(|&i| Value::Int(i as i32))
566                        .collect(),
567                ),
568            ),
569            (
570                "vec_field".to_owned(),
571                Value::Array(
572                    test.vec_field
573                        .iter()
574                        .map(|&i| Value::Int(i as i32))
575                        .collect(),
576                ),
577            ),
578            (
579                "vec_field2".to_owned(),
580                Value::Fixed(test.vec_field2.len(), test.vec_field2.clone()),
581            ),
582            (
583                "vec_field2_opt".to_owned(),
584                Value::Union(
585                    1,
586                    Box::new(Value::Fixed(
587                        test.vec_field2_opt.as_ref().unwrap().len(),
588                        test.vec_field2_opt.as_ref().unwrap().to_vec(),
589                    )),
590                ),
591            ),
592            (
593                "vec_field2_opt2".to_owned(),
594                Value::Union(0, Box::new(Value::Null)),
595            ),
596            (
597                "vec_field3".to_owned(),
598                Value::Bytes(test.vec_field3.clone()),
599            ),
600            (
601                "vec_field3_opt".to_owned(),
602                Value::Union(
603                    1,
604                    Box::new(Value::Bytes(test.vec_field3_opt.as_ref().unwrap().clone())),
605                ),
606            ),
607            (
608                "vec_field3_opt2".to_owned(),
609                Value::Union(0, Box::new(Value::Null)),
610            ),
611            (
612                "fixed_field".to_owned(),
613                Value::Fixed(test.fixed_field.len(), test.fixed_field.to_vec()),
614            ),
615            (
616                "fixed_field_opt".to_owned(),
617                Value::Union(
618                    1,
619                    Box::new(Value::Fixed(
620                        test.fixed_field_opt.as_ref().unwrap().len(),
621                        test.fixed_field_opt.as_ref().unwrap().to_vec(),
622                    )),
623                ),
624            ),
625            (
626                "fixed_field_opt2".to_owned(),
627                Value::Union(0, Box::new(Value::Null)),
628            ),
629            (
630                "fixed_field2".to_owned(),
631                Value::Fixed(test.fixed_field2.len(), test.fixed_field2.to_vec()),
632            ),
633            (
634                "fixed_field2_opt".to_owned(),
635                Value::Union(
636                    1,
637                    Box::new(Value::Fixed(
638                        test.fixed_field2_opt.as_ref().unwrap().len(),
639                        test.fixed_field2_opt.as_ref().unwrap().to_vec(),
640                    )),
641                ),
642            ),
643            (
644                "fixed_field2_opt2".to_owned(),
645                Value::Union(0, Box::new(Value::Null)),
646            ),
647            (
648                "bytes_field".to_owned(),
649                Value::Bytes(test.bytes_field.to_vec()),
650            ),
651            (
652                "bytes_field_opt".to_owned(),
653                Value::Union(
654                    1,
655                    Box::new(Value::Bytes(
656                        test.bytes_field_opt.as_ref().unwrap().to_vec(),
657                    )),
658                ),
659            ),
660            (
661                "bytes_field_opt2".to_owned(),
662                Value::Union(0, Box::new(Value::Null)),
663            ),
664            (
665                "bytes_field2".to_owned(),
666                Value::Bytes(test.bytes_field2.to_vec()),
667            ),
668            (
669                "bytes_field2_opt".to_owned(),
670                Value::Union(
671                    1,
672                    Box::new(Value::Bytes(
673                        test.bytes_field2_opt.as_ref().unwrap().to_vec(),
674                    )),
675                ),
676            ),
677            (
678                "bytes_field2_opt2".to_owned(),
679                Value::Union(0, Box::new(Value::Null)),
680            ),
681        ]);
682        assert_eq!(expected, to_value(test).unwrap());
683    }
684}