1use 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
55fn 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
74pub 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 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 let mut items = Vec::with_capacity(fields.len());
309 for field in fields {
310 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 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 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 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}