Skip to main content

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