apache_avro/
decode.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 crate::schema::{InnerDecimalSchema, UuidSchema};
19use crate::{
20    AvroResult, Error,
21    bigdecimal::deserialize_big_decimal,
22    decimal::Decimal,
23    duration::Duration,
24    error::Details,
25    schema::{
26        DecimalSchema, EnumSchema, FixedSchema, Name, Namespace, RecordSchema, ResolvedSchema,
27        Schema,
28    },
29    types::Value,
30    util::{safe_len, zag_i32, zag_i64},
31};
32use std::{
33    borrow::Borrow,
34    collections::HashMap,
35    io::{ErrorKind, Read},
36};
37use uuid::Uuid;
38
39#[inline]
40pub(crate) fn decode_long<R: Read>(reader: &mut R) -> AvroResult<Value> {
41    zag_i64(reader).map(Value::Long)
42}
43
44#[inline]
45fn decode_int<R: Read>(reader: &mut R) -> AvroResult<Value> {
46    zag_i32(reader).map(Value::Int)
47}
48
49#[inline]
50pub(crate) fn decode_len<R: Read>(reader: &mut R) -> AvroResult<usize> {
51    let len = zag_i64(reader)?;
52    safe_len(usize::try_from(len).map_err(|e| Details::ConvertI64ToUsize(e, len))?)
53}
54
55/// Decode the length of a sequence.
56///
57/// Maps and arrays are 0-terminated, 0i64 is also encoded as 0 in Avro reading a length of 0 means
58/// the end of the map or array.
59fn decode_seq_len<R: Read>(reader: &mut R) -> AvroResult<usize> {
60    let raw_len = zag_i64(reader)?;
61    safe_len(
62        usize::try_from(match raw_len.cmp(&0) {
63            std::cmp::Ordering::Equal => return Ok(0),
64            std::cmp::Ordering::Less => {
65                let _size = zag_i64(reader)?;
66                raw_len.checked_neg().ok_or(Details::IntegerOverflow)?
67            }
68            std::cmp::Ordering::Greater => raw_len,
69        })
70        .map_err(|e| Details::ConvertI64ToUsize(e, raw_len))?,
71    )
72}
73
74/// Decode a `Value` from avro format given its `Schema`.
75pub fn decode<R: Read>(schema: &Schema, reader: &mut R) -> AvroResult<Value> {
76    let rs = ResolvedSchema::try_from(schema)?;
77    decode_internal(schema, rs.get_names(), &None, reader)
78}
79
80pub(crate) fn decode_internal<R: Read, S: Borrow<Schema>>(
81    schema: &Schema,
82    names: &HashMap<Name, S>,
83    enclosing_namespace: &Namespace,
84    reader: &mut R,
85) -> AvroResult<Value> {
86    match schema {
87        Schema::Null => Ok(Value::Null),
88        Schema::Boolean => {
89            let mut buf = [0u8; 1];
90            match reader.read_exact(&mut buf[..]) {
91                Ok(_) => match buf[0] {
92                    0u8 => Ok(Value::Boolean(false)),
93                    1u8 => Ok(Value::Boolean(true)),
94                    _ => Err(Details::BoolValue(buf[0]).into()),
95                },
96                Err(io_err) => {
97                    if let ErrorKind::UnexpectedEof = io_err.kind() {
98                        Ok(Value::Null)
99                    } else {
100                        Err(Details::ReadBoolean(io_err).into())
101                    }
102                }
103            }
104        }
105        Schema::Decimal(DecimalSchema { inner, .. }) => match inner {
106            InnerDecimalSchema::Fixed(fixed) => {
107                match decode_internal(
108                    &Schema::Fixed(fixed.copy_only_size()),
109                    names,
110                    enclosing_namespace,
111                    reader,
112                )? {
113                    Value::Fixed(_, bytes) => Ok(Value::Decimal(Decimal::from(bytes))),
114                    value => Err(Details::FixedValue(value).into()),
115                }
116            }
117            InnerDecimalSchema::Bytes => {
118                match decode_internal(&Schema::Bytes, names, enclosing_namespace, reader)? {
119                    Value::Bytes(bytes) => Ok(Value::Decimal(Decimal::from(bytes))),
120                    value => Err(Details::BytesValue(value).into()),
121                }
122            }
123        },
124        Schema::BigDecimal => {
125            match decode_internal(&Schema::Bytes, names, enclosing_namespace, reader)? {
126                Value::Bytes(bytes) => deserialize_big_decimal(&bytes).map(Value::BigDecimal),
127                value => Err(Details::BytesValue(value).into()),
128            }
129        }
130        Schema::Uuid(UuidSchema::String) => {
131            let Value::String(string) =
132                decode_internal(&Schema::String, names, enclosing_namespace, reader)?
133            else {
134                // decoding a String can also return a Null, indicating EOF
135                return Err(Error::new(Details::ReadBytes(std::io::Error::from(
136                    ErrorKind::UnexpectedEof,
137                ))));
138            };
139            let uuid = Uuid::parse_str(&string).map_err(Details::ConvertStrToUuid)?;
140            Ok(Value::Uuid(uuid))
141        }
142        Schema::Uuid(UuidSchema::Bytes) => {
143            let Value::Bytes(bytes) =
144                decode_internal(&Schema::Bytes, names, enclosing_namespace, reader)?
145            else {
146                unreachable!(
147                    "decode_internal(Schema::Bytes) can only return a Value::Bytes or an error"
148                )
149            };
150            let uuid = Uuid::from_slice(&bytes).map_err(Details::ConvertSliceToUuid)?;
151            Ok(Value::Uuid(uuid))
152        }
153        Schema::Uuid(UuidSchema::Fixed(fixed)) => {
154            let Value::Fixed(n, bytes) = decode_internal(
155                &Schema::Fixed(fixed.copy_only_size()),
156                names,
157                enclosing_namespace,
158                reader,
159            )?
160            else {
161                unreachable!(
162                    "decode_internal(Schema::Fixed) can only return a Value::Fixed or an error"
163                )
164            };
165            if n != 16 {
166                return Err(Details::ConvertFixedToUuid(n).into());
167            }
168            let uuid = Uuid::from_slice(&bytes).map_err(Details::ConvertSliceToUuid)?;
169            Ok(Value::Uuid(uuid))
170        }
171        Schema::Int => decode_int(reader),
172        Schema::Date => zag_i32(reader).map(Value::Date),
173        Schema::TimeMillis => zag_i32(reader).map(Value::TimeMillis),
174        Schema::Long => decode_long(reader),
175        Schema::TimeMicros => zag_i64(reader).map(Value::TimeMicros),
176        Schema::TimestampMillis => zag_i64(reader).map(Value::TimestampMillis),
177        Schema::TimestampMicros => zag_i64(reader).map(Value::TimestampMicros),
178        Schema::TimestampNanos => zag_i64(reader).map(Value::TimestampNanos),
179        Schema::LocalTimestampMillis => zag_i64(reader).map(Value::LocalTimestampMillis),
180        Schema::LocalTimestampMicros => zag_i64(reader).map(Value::LocalTimestampMicros),
181        Schema::LocalTimestampNanos => zag_i64(reader).map(Value::LocalTimestampNanos),
182        Schema::Duration(fixed_schema) => {
183            if fixed_schema.size == 12 {
184                let mut buf = [0u8; 12];
185                reader.read_exact(&mut buf).map_err(Details::ReadDuration)?;
186                Ok(Value::Duration(Duration::from(buf)))
187            } else {
188                Err(Details::CompareFixedSizes {
189                    size: 12,
190                    n: fixed_schema.size,
191                }
192                .into())
193            }
194        }
195        Schema::Float => {
196            let mut buf = [0u8; std::mem::size_of::<f32>()];
197            reader
198                .read_exact(&mut buf[..])
199                .map_err(Details::ReadFloat)?;
200            Ok(Value::Float(f32::from_le_bytes(buf)))
201        }
202        Schema::Double => {
203            let mut buf = [0u8; std::mem::size_of::<f64>()];
204            reader
205                .read_exact(&mut buf[..])
206                .map_err(Details::ReadDouble)?;
207            Ok(Value::Double(f64::from_le_bytes(buf)))
208        }
209        Schema::Bytes => {
210            let len = decode_len(reader)?;
211            let mut buf = vec![0u8; len];
212            reader.read_exact(&mut buf).map_err(Details::ReadBytes)?;
213            Ok(Value::Bytes(buf))
214        }
215        Schema::String => {
216            let len = decode_len(reader)?;
217            let mut buf = vec![0u8; len];
218            match reader.read_exact(&mut buf) {
219                Ok(_) => Ok(Value::String(
220                    String::from_utf8(buf).map_err(Details::ConvertToUtf8)?,
221                )),
222                Err(io_err) => {
223                    if let ErrorKind::UnexpectedEof = io_err.kind() {
224                        Ok(Value::Null)
225                    } else {
226                        Err(Details::ReadString(io_err).into())
227                    }
228                }
229            }
230        }
231        Schema::Fixed(FixedSchema { size, .. }) => {
232            let mut buf = vec![0u8; *size];
233            reader
234                .read_exact(&mut buf)
235                .map_err(|e| Details::ReadFixed(e, *size))?;
236            Ok(Value::Fixed(*size, buf))
237        }
238        Schema::Array(inner) => {
239            let mut items = Vec::new();
240
241            loop {
242                let len = decode_seq_len(reader)?;
243                if len == 0 {
244                    break;
245                }
246
247                items.reserve(len);
248                for _ in 0..len {
249                    items.push(decode_internal(
250                        &inner.items,
251                        names,
252                        enclosing_namespace,
253                        reader,
254                    )?);
255                }
256            }
257
258            Ok(Value::Array(items))
259        }
260        Schema::Map(inner) => {
261            let mut items = HashMap::new();
262
263            loop {
264                let len = decode_seq_len(reader)?;
265                if len == 0 {
266                    break;
267                }
268
269                items.reserve(len);
270                for _ in 0..len {
271                    match decode_internal(&Schema::String, names, enclosing_namespace, reader)? {
272                        Value::String(key) => {
273                            let value =
274                                decode_internal(&inner.types, names, enclosing_namespace, reader)?;
275                            items.insert(key, value);
276                        }
277                        value => return Err(Details::MapKeyType(value.into()).into()),
278                    }
279                }
280            }
281
282            Ok(Value::Map(items))
283        }
284        Schema::Union(inner) => match zag_i64(reader).map_err(Error::into_details) {
285            Ok(index) => {
286                let variants = inner.variants();
287                let variant = variants
288                    .get(usize::try_from(index).map_err(|e| Details::ConvertI64ToUsize(e, index))?)
289                    .ok_or(Details::GetUnionVariant {
290                        index,
291                        num_variants: variants.len(),
292                    })?;
293                let value = decode_internal(variant, names, enclosing_namespace, reader)?;
294                Ok(Value::Union(index as u32, Box::new(value)))
295            }
296            Err(Details::ReadVariableIntegerBytes(io_err)) => {
297                if let ErrorKind::UnexpectedEof = io_err.kind() {
298                    Ok(Value::Union(0, Box::new(Value::Null)))
299                } else {
300                    Err(Details::ReadVariableIntegerBytes(io_err).into())
301                }
302            }
303            Err(io_err) => Err(Error::new(io_err)),
304        },
305        Schema::Record(RecordSchema { name, fields, .. }) => {
306            let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
307            // Benchmarks indicate ~10% improvement using this method.
308            let mut items = Vec::with_capacity(fields.len());
309            for field in fields {
310                // TODO: This clone is also expensive. See if we can do away with it...
311                items.push((
312                    field.name.clone(),
313                    decode_internal(
314                        &field.schema,
315                        names,
316                        &fully_qualified_name.namespace,
317                        reader,
318                    )?,
319                ));
320            }
321            Ok(Value::Record(items))
322        }
323        Schema::Enum(EnumSchema { symbols, .. }) => {
324            Ok(if let Value::Int(raw_index) = decode_int(reader)? {
325                let index = usize::try_from(raw_index)
326                    .map_err(|e| Details::ConvertI32ToUsize(e, raw_index))?;
327                if (0..symbols.len()).contains(&index) {
328                    let symbol = symbols[index].clone();
329                    Value::Enum(raw_index as u32, symbol)
330                } else {
331                    return Err(Details::GetEnumValue {
332                        index,
333                        nsymbols: symbols.len(),
334                    }
335                    .into());
336                }
337            } else {
338                return Err(Details::GetEnumUnknownIndexValue.into());
339            })
340        }
341        Schema::Ref { name } => {
342            let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
343            if let Some(resolved) = names.get(&fully_qualified_name) {
344                decode_internal(
345                    resolved.borrow(),
346                    names,
347                    &fully_qualified_name.namespace,
348                    reader,
349                )
350            } else {
351                Err(Details::SchemaResolutionError(fully_qualified_name).into())
352            }
353        }
354    }
355}
356
357#[cfg(test)]
358#[allow(clippy::expect_fun_call)]
359mod tests {
360    use crate::schema::{InnerDecimalSchema, UuidSchema};
361    use crate::{
362        Decimal,
363        decode::decode,
364        encode::{encode, tests::success},
365        schema::{DecimalSchema, FixedSchema, Schema},
366        types::{
367            Value,
368            Value::{Array, Int, Map},
369        },
370    };
371    use apache_avro_test_helper::TestResult;
372    use pretty_assertions::assert_eq;
373    use std::collections::HashMap;
374    use uuid::Uuid;
375
376    #[test]
377    fn test_decode_array_without_size() -> TestResult {
378        let mut input: &[u8] = &[6, 2, 4, 6, 0];
379        let result = decode(&Schema::array(Schema::Int), &mut input);
380        assert_eq!(Array(vec!(Int(1), Int(2), Int(3))), result?);
381
382        Ok(())
383    }
384
385    #[test]
386    fn test_decode_array_with_size() -> TestResult {
387        let mut input: &[u8] = &[5, 6, 2, 4, 6, 0];
388        let result = decode(&Schema::array(Schema::Int), &mut input);
389        assert_eq!(Array(vec!(Int(1), Int(2), Int(3))), result?);
390
391        Ok(())
392    }
393
394    #[test]
395    fn test_decode_map_without_size() -> TestResult {
396        let mut input: &[u8] = &[0x02, 0x08, 0x74, 0x65, 0x73, 0x74, 0x02, 0x00];
397        let result = decode(&Schema::map(Schema::Int), &mut input);
398        let mut expected = HashMap::new();
399        expected.insert(String::from("test"), Int(1));
400        assert_eq!(Map(expected), result?);
401
402        Ok(())
403    }
404
405    #[test]
406    fn test_decode_map_with_size() -> TestResult {
407        let mut input: &[u8] = &[0x01, 0x0C, 0x08, 0x74, 0x65, 0x73, 0x74, 0x02, 0x00];
408        let result = decode(&Schema::map(Schema::Int), &mut input);
409        let mut expected = HashMap::new();
410        expected.insert(String::from("test"), Int(1));
411        assert_eq!(Map(expected), result?);
412
413        Ok(())
414    }
415
416    #[test]
417    fn test_negative_decimal_value() -> TestResult {
418        use crate::{encode::encode, schema::Name};
419        use num_bigint::ToBigInt;
420        let schema = Schema::Decimal(DecimalSchema {
421            inner: InnerDecimalSchema::Fixed(
422                FixedSchema::builder()
423                    .name(Name::new("decimal")?)
424                    .size(2)
425                    .build(),
426            ),
427            precision: 4,
428            scale: 2,
429        });
430        let bigint = (-423).to_bigint().unwrap();
431        let value = Value::Decimal(Decimal::from(bigint.to_signed_bytes_be()));
432
433        let mut buffer = Vec::new();
434        encode(&value, &schema, &mut buffer).expect(&success(&value, &schema));
435
436        let mut bytes = &buffer[..];
437        let result = decode(&schema, &mut bytes)?;
438        assert_eq!(result, value);
439
440        Ok(())
441    }
442
443    #[test]
444    fn test_decode_decimal_with_bigger_than_necessary_size() -> TestResult {
445        use crate::{encode::encode, schema::Name};
446        use num_bigint::ToBigInt;
447        let schema = Schema::Decimal(DecimalSchema {
448            inner: InnerDecimalSchema::Fixed(FixedSchema {
449                size: 13,
450                name: Name::new("decimal")?,
451                aliases: None,
452                doc: None,
453                default: None,
454                attributes: Default::default(),
455            }),
456            precision: 4,
457            scale: 2,
458        });
459        let value = Value::Decimal(Decimal::from(
460            ((-423).to_bigint().unwrap()).to_signed_bytes_be(),
461        ));
462        let mut buffer = Vec::<u8>::new();
463
464        encode(&value, &schema, &mut buffer).expect(&success(&value, &schema));
465        let mut bytes: &[u8] = &buffer[..];
466        let result = decode(&schema, &mut bytes)?;
467        assert_eq!(result, value);
468
469        Ok(())
470    }
471
472    #[test]
473    fn test_avro_3448_recursive_definition_decode_union() -> TestResult {
474        // if encoding fails in this test check the corresponding test in encode
475        let schema = Schema::parse_str(
476            r#"
477        {
478            "type":"record",
479            "name":"TestStruct",
480            "fields": [
481                {
482                    "name":"a",
483                    "type":[ "null", {
484                        "type":"record",
485                        "name": "Inner",
486                        "fields": [ {
487                            "name":"z",
488                            "type":"int"
489                        }]
490                    }]
491                },
492                {
493                    "name":"b",
494                    "type":"Inner"
495                }
496            ]
497        }"#,
498        )?;
499
500        let inner_value1 = Value::Record(vec![("z".into(), Value::Int(3))]);
501        let inner_value2 = Value::Record(vec![("z".into(), Value::Int(6))]);
502        let outer_value1 = Value::Record(vec![
503            ("a".into(), Value::Union(1, Box::new(inner_value1))),
504            ("b".into(), inner_value2.clone()),
505        ]);
506        let mut buf = Vec::new();
507        encode(&outer_value1, &schema, &mut buf).expect(&success(&outer_value1, &schema));
508        assert!(!buf.is_empty());
509        let mut bytes = &buf[..];
510        assert_eq!(
511            outer_value1,
512            decode(&schema, &mut bytes).expect(&format!(
513                "Failed to decode using recursive definitions with schema:\n {:?}\n",
514                &schema
515            ))
516        );
517
518        let mut buf = Vec::new();
519        let outer_value2 = Value::Record(vec![
520            ("a".into(), Value::Union(0, Box::new(Value::Null))),
521            ("b".into(), inner_value2),
522        ]);
523        encode(&outer_value2, &schema, &mut buf).expect(&success(&outer_value2, &schema));
524        let mut bytes = &buf[..];
525        assert_eq!(
526            outer_value2,
527            decode(&schema, &mut bytes).expect(&format!(
528                "Failed to decode using recursive definitions with schema:\n {:?}\n",
529                &schema
530            ))
531        );
532
533        Ok(())
534    }
535
536    #[test]
537    fn test_avro_3448_recursive_definition_decode_array() -> TestResult {
538        let schema = Schema::parse_str(
539            r#"
540        {
541            "type":"record",
542            "name":"TestStruct",
543            "fields": [
544                {
545                    "name":"a",
546                    "type":{
547                        "type":"array",
548                        "items": {
549                            "type":"record",
550                            "name": "Inner",
551                            "fields": [ {
552                                "name":"z",
553                                "type":"int"
554                            }]
555                        }
556                    }
557                },
558                {
559                    "name":"b",
560                    "type": "Inner"
561                }
562            ]
563        }"#,
564        )?;
565
566        let inner_value1 = Value::Record(vec![("z".into(), Value::Int(3))]);
567        let inner_value2 = Value::Record(vec![("z".into(), Value::Int(6))]);
568        let outer_value = Value::Record(vec![
569            ("a".into(), Value::Array(vec![inner_value1])),
570            ("b".into(), inner_value2),
571        ]);
572        let mut buf = Vec::new();
573        encode(&outer_value, &schema, &mut buf).expect(&success(&outer_value, &schema));
574        let mut bytes = &buf[..];
575        assert_eq!(
576            outer_value,
577            decode(&schema, &mut bytes).expect(&format!(
578                "Failed to decode using recursive definitions with schema:\n {:?}\n",
579                &schema
580            ))
581        );
582
583        Ok(())
584    }
585
586    #[test]
587    fn test_avro_3448_recursive_definition_decode_map() -> TestResult {
588        let schema = Schema::parse_str(
589            r#"
590        {
591            "type":"record",
592            "name":"TestStruct",
593            "fields": [
594                {
595                    "name":"a",
596                    "type":{
597                        "type":"map",
598                        "values": {
599                            "type":"record",
600                            "name": "Inner",
601                            "fields": [ {
602                                "name":"z",
603                                "type":"int"
604                            }]
605                        }
606                    }
607                },
608                {
609                    "name":"b",
610                    "type": "Inner"
611                }
612            ]
613        }"#,
614        )?;
615
616        let inner_value1 = Value::Record(vec![("z".into(), Value::Int(3))]);
617        let inner_value2 = Value::Record(vec![("z".into(), Value::Int(6))]);
618        let outer_value = Value::Record(vec![
619            (
620                "a".into(),
621                Value::Map(vec![("akey".into(), inner_value1)].into_iter().collect()),
622            ),
623            ("b".into(), inner_value2),
624        ]);
625        let mut buf = Vec::new();
626        encode(&outer_value, &schema, &mut buf).expect(&success(&outer_value, &schema));
627        let mut bytes = &buf[..];
628        assert_eq!(
629            outer_value,
630            decode(&schema, &mut bytes).expect(&format!(
631                "Failed to decode using recursive definitions with schema:\n {:?}\n",
632                &schema
633            ))
634        );
635
636        Ok(())
637    }
638
639    #[test]
640    fn test_avro_3448_proper_multi_level_decoding_middle_namespace() -> TestResult {
641        // if encoding fails in this test check the corresponding test in encode
642        let schema = r#"
643        {
644          "name": "record_name",
645          "namespace": "space",
646          "type": "record",
647          "fields": [
648            {
649              "name": "outer_field_1",
650              "type": [
651                        "null",
652                        {
653                            "type": "record",
654                            "name": "middle_record_name",
655                            "namespace":"middle_namespace",
656                            "fields":[
657                                {
658                                    "name":"middle_field_1",
659                                    "type":[
660                                        "null",
661                                        {
662                                            "type":"record",
663                                            "name":"inner_record_name",
664                                            "fields":[
665                                                {
666                                                    "name":"inner_field_1",
667                                                    "type":"double"
668                                                }
669                                            ]
670                                        }
671                                    ]
672                                }
673                            ]
674                        }
675                    ]
676            },
677            {
678                "name": "outer_field_2",
679                "type" : "middle_namespace.inner_record_name"
680            }
681          ]
682        }
683        "#;
684        let schema = Schema::parse_str(schema)?;
685        let inner_record = Value::Record(vec![("inner_field_1".into(), Value::Double(5.4))]);
686        let middle_record_variation_1 = Value::Record(vec![(
687            "middle_field_1".into(),
688            Value::Union(0, Box::new(Value::Null)),
689        )]);
690        let middle_record_variation_2 = Value::Record(vec![(
691            "middle_field_1".into(),
692            Value::Union(1, Box::new(inner_record.clone())),
693        )]);
694        let outer_record_variation_1 = Value::Record(vec![
695            (
696                "outer_field_1".into(),
697                Value::Union(0, Box::new(Value::Null)),
698            ),
699            ("outer_field_2".into(), inner_record.clone()),
700        ]);
701        let outer_record_variation_2 = Value::Record(vec![
702            (
703                "outer_field_1".into(),
704                Value::Union(1, Box::new(middle_record_variation_1)),
705            ),
706            ("outer_field_2".into(), inner_record.clone()),
707        ]);
708        let outer_record_variation_3 = Value::Record(vec![
709            (
710                "outer_field_1".into(),
711                Value::Union(1, Box::new(middle_record_variation_2)),
712            ),
713            ("outer_field_2".into(), inner_record),
714        ]);
715
716        let mut buf = Vec::new();
717        encode(&outer_record_variation_1, &schema, &mut buf)
718            .expect(&success(&outer_record_variation_1, &schema));
719        let mut bytes = &buf[..];
720        assert_eq!(
721            outer_record_variation_1,
722            decode(&schema, &mut bytes).expect(&format!(
723                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
724                &schema
725            ))
726        );
727
728        let mut buf = Vec::new();
729        encode(&outer_record_variation_2, &schema, &mut buf)
730            .expect(&success(&outer_record_variation_2, &schema));
731        let mut bytes = &buf[..];
732        assert_eq!(
733            outer_record_variation_2,
734            decode(&schema, &mut bytes).expect(&format!(
735                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
736                &schema
737            ))
738        );
739
740        let mut buf = Vec::new();
741        encode(&outer_record_variation_3, &schema, &mut buf)
742            .expect(&success(&outer_record_variation_3, &schema));
743        let mut bytes = &buf[..];
744        assert_eq!(
745            outer_record_variation_3,
746            decode(&schema, &mut bytes).expect(&format!(
747                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
748                &schema
749            ))
750        );
751
752        Ok(())
753    }
754
755    #[test]
756    fn test_avro_3448_proper_multi_level_decoding_inner_namespace() -> TestResult {
757        // if encoding fails in this test check the corresponding test in encode
758        let schema = r#"
759        {
760          "name": "record_name",
761          "namespace": "space",
762          "type": "record",
763          "fields": [
764            {
765              "name": "outer_field_1",
766              "type": [
767                        "null",
768                        {
769                            "type": "record",
770                            "name": "middle_record_name",
771                            "namespace":"middle_namespace",
772                            "fields":[
773                                {
774                                    "name":"middle_field_1",
775                                    "type":[
776                                        "null",
777                                        {
778                                            "type":"record",
779                                            "name":"inner_record_name",
780                                            "namespace":"inner_namespace",
781                                            "fields":[
782                                                {
783                                                    "name":"inner_field_1",
784                                                    "type":"double"
785                                                }
786                                            ]
787                                        }
788                                    ]
789                                }
790                            ]
791                        }
792                    ]
793            },
794            {
795                "name": "outer_field_2",
796                "type" : "inner_namespace.inner_record_name"
797            }
798          ]
799        }
800        "#;
801        let schema = Schema::parse_str(schema)?;
802        let inner_record = Value::Record(vec![("inner_field_1".into(), Value::Double(5.4))]);
803        let middle_record_variation_1 = Value::Record(vec![(
804            "middle_field_1".into(),
805            Value::Union(0, Box::new(Value::Null)),
806        )]);
807        let middle_record_variation_2 = Value::Record(vec![(
808            "middle_field_1".into(),
809            Value::Union(1, Box::new(inner_record.clone())),
810        )]);
811        let outer_record_variation_1 = Value::Record(vec![
812            (
813                "outer_field_1".into(),
814                Value::Union(0, Box::new(Value::Null)),
815            ),
816            ("outer_field_2".into(), inner_record.clone()),
817        ]);
818        let outer_record_variation_2 = Value::Record(vec![
819            (
820                "outer_field_1".into(),
821                Value::Union(1, Box::new(middle_record_variation_1)),
822            ),
823            ("outer_field_2".into(), inner_record.clone()),
824        ]);
825        let outer_record_variation_3 = Value::Record(vec![
826            (
827                "outer_field_1".into(),
828                Value::Union(1, Box::new(middle_record_variation_2)),
829            ),
830            ("outer_field_2".into(), inner_record),
831        ]);
832
833        let mut buf = Vec::new();
834        encode(&outer_record_variation_1, &schema, &mut buf)
835            .expect(&success(&outer_record_variation_1, &schema));
836        let mut bytes = &buf[..];
837        assert_eq!(
838            outer_record_variation_1,
839            decode(&schema, &mut bytes).expect(&format!(
840                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
841                &schema
842            ))
843        );
844
845        let mut buf = Vec::new();
846        encode(&outer_record_variation_2, &schema, &mut buf)
847            .expect(&success(&outer_record_variation_2, &schema));
848        let mut bytes = &buf[..];
849        assert_eq!(
850            outer_record_variation_2,
851            decode(&schema, &mut bytes).expect(&format!(
852                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
853                &schema
854            ))
855        );
856
857        let mut buf = Vec::new();
858        encode(&outer_record_variation_3, &schema, &mut buf)
859            .expect(&success(&outer_record_variation_3, &schema));
860        let mut bytes = &buf[..];
861        assert_eq!(
862            outer_record_variation_3,
863            decode(&schema, &mut bytes).expect(&format!(
864                "Failed to Decode with recursively defined namespace with schema:\n {:?}\n",
865                &schema
866            ))
867        );
868
869        Ok(())
870    }
871
872    #[test]
873    fn avro_3926_encode_decode_uuid_to_string() -> TestResult {
874        use crate::encode::encode;
875
876        let schema = Schema::String;
877        let value = Value::Uuid(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000")?);
878
879        let mut buffer = Vec::new();
880        encode(&value, &schema, &mut buffer).expect(&success(&value, &schema));
881
882        let result = decode(&Schema::Uuid(UuidSchema::String), &mut &buffer[..])?;
883        assert_eq!(result, value);
884
885        Ok(())
886    }
887
888    #[test]
889    fn avro_3926_encode_decode_uuid_to_fixed() -> TestResult {
890        use crate::encode::encode;
891
892        let fixed = FixedSchema {
893            size: 16,
894            name: "uuid".try_into()?,
895            aliases: None,
896            doc: None,
897            default: None,
898            attributes: Default::default(),
899        };
900
901        let schema = Schema::Fixed(fixed.clone());
902        let value = Value::Uuid(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000")?);
903
904        let mut buffer = Vec::new();
905        encode(&value, &schema, &mut buffer).expect(&success(&value, &schema));
906
907        let result = decode(&Schema::Uuid(UuidSchema::Fixed(fixed)), &mut &buffer[..])?;
908        assert_eq!(result, value);
909
910        Ok(())
911    }
912
913    #[test]
914    fn encode_decode_uuid_to_bytes() -> TestResult {
915        use crate::encode::encode;
916
917        let schema = Schema::Bytes;
918        let value = Value::Uuid(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000")?);
919
920        let mut buffer = Vec::new();
921        encode(&value, &schema, &mut buffer).expect(&success(&value, &schema));
922
923        let result = decode(&Schema::Uuid(UuidSchema::Bytes), &mut &buffer[..])?;
924        assert_eq!(result, value);
925
926        Ok(())
927    }
928}