1use 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
52fn 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
71pub 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 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 let mut items = Vec::with_capacity(fields.len());
306 for field in fields {
307 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 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 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 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}