1use std::cell::Cell;
19
20thread_local! {
21 pub(crate) static SER_BYTES_TYPE: Cell<BytesType> = const { Cell::new(BytesType::Unset) };
26
27 pub(crate) static DE_BYTES_BORROWED: Cell<bool> = const { Cell::new(false) };
32}
33
34#[derive(Debug, Clone, Copy)]
35pub(crate) enum BytesType {
36 Unset,
37 Bytes,
38 Fixed,
39}
40
41struct BytesTypeGuard(BytesType);
42impl BytesTypeGuard {
43 fn set(temp: BytesType) -> Self {
44 let prev = SER_BYTES_TYPE.get();
45 SER_BYTES_TYPE.set(temp);
46 Self(prev)
47 }
48}
49
50impl Drop for BytesTypeGuard {
51 fn drop(&mut self) {
52 SER_BYTES_TYPE.set(self.0);
53 }
54}
55
56struct BorrowedGuard(bool);
57impl BorrowedGuard {
58 fn set(temp: bool) -> Self {
59 let prev = DE_BYTES_BORROWED.get();
60 DE_BYTES_BORROWED.set(temp);
61 Self(prev)
62 }
63}
64
65impl Drop for BorrowedGuard {
66 fn drop(&mut self) {
67 DE_BYTES_BORROWED.set(self.0);
68 }
69}
70
71pub mod bytes {
96 use std::collections::HashSet;
97
98 use serde::{Deserializer, Serializer};
99
100 use super::BytesType;
101 use crate::{
102 Schema,
103 schema::{Name, NamespaceRef, RecordField},
104 };
105
106 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
108 Schema::Bytes
109 }
110
111 pub fn get_record_fields_in_ctxt(
113 _: usize,
114 _: &mut HashSet<Name>,
115 _: NamespaceRef,
116 ) -> Option<Vec<RecordField>> {
117 None
118 }
119
120 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
121 where
122 S: Serializer,
123 {
124 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
125 serde_bytes::serialize(bytes, serializer)
126 }
127
128 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
129 where
130 D: Deserializer<'de>,
131 {
132 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
133 serde_bytes::deserialize(deserializer)
134 }
135}
136
137pub mod bytes_opt {
162 use std::{borrow::Borrow, collections::HashSet};
163
164 use serde::{Deserializer, Serializer};
165
166 use super::BytesType;
167 use crate::{
168 Schema,
169 schema::{Name, NamespaceRef, RecordField, UnionSchema},
170 };
171
172 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
174 Schema::Union(
175 UnionSchema::new(vec![Schema::Null, Schema::Bytes])
176 .unwrap_or_else(|_| unreachable!("This is a valid union")),
177 )
178 }
179
180 pub fn get_record_fields_in_ctxt(
182 _: usize,
183 _: &mut HashSet<Name>,
184 _: NamespaceRef,
185 ) -> Option<Vec<RecordField>> {
186 None
187 }
188
189 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
190 where
191 S: Serializer,
192 B: Borrow<[u8]> + serde_bytes::Serialize,
193 {
194 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
195 serde_bytes::serialize(bytes, serializer)
196 }
197
198 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
199 where
200 D: Deserializer<'de>,
201 {
202 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
203 serde_bytes::deserialize(deserializer)
204 }
205}
206
207pub mod fixed {
232 use std::collections::HashSet;
233
234 use serde::{Deserializer, Serializer};
235
236 use super::BytesType;
237 use crate::{
238 Schema,
239 schema::{FixedSchema, Name, NamespaceRef, RecordField},
240 };
241
242 pub fn get_schema_in_ctxt<const N: usize>(
244 named_schemas: &mut HashSet<Name>,
245 enclosing_namespace: NamespaceRef,
246 ) -> Schema {
247 let name = Name::new_with_enclosing_namespace(
248 format!("serde_avro_fixed_{N}"),
249 enclosing_namespace,
250 )
251 .unwrap_or_else(|_| unreachable!("Name is valid"));
252 if named_schemas.contains(&name) {
253 Schema::Ref { name }
254 } else {
255 let schema = Schema::Fixed(FixedSchema::builder().name(name.clone()).size(N).build());
256 named_schemas.insert(name);
257 schema
258 }
259 }
260
261 pub fn get_record_fields_in_ctxt(
263 _: usize,
264 _: &mut HashSet<Name>,
265 _: NamespaceRef,
266 ) -> Option<Vec<RecordField>> {
267 None
268 }
269
270 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
271 where
272 S: Serializer,
273 {
274 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
275 serde_bytes::serialize(bytes, serializer)
276 }
277
278 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
279 where
280 D: Deserializer<'de>,
281 {
282 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
283 serde_bytes::deserialize(deserializer)
284 }
285}
286
287pub mod fixed_opt {
312 use std::{borrow::Borrow, collections::HashSet};
313
314 use serde::{Deserializer, Serializer};
315
316 use super::BytesType;
317 use crate::{
318 Schema,
319 schema::{Name, NamespaceRef, RecordField, UnionSchema},
320 };
321
322 pub fn get_schema_in_ctxt<const N: usize>(
324 named_schemas: &mut HashSet<Name>,
325 enclosing_namespace: NamespaceRef,
326 ) -> Schema {
327 Schema::Union(
328 UnionSchema::new(vec![
329 Schema::Null,
330 super::fixed::get_schema_in_ctxt::<N>(named_schemas, enclosing_namespace),
331 ])
332 .unwrap_or_else(|_| unreachable!("This is a valid union")),
333 )
334 }
335
336 pub fn get_record_fields_in_ctxt(
338 _: usize,
339 _: &mut HashSet<Name>,
340 _: NamespaceRef,
341 ) -> Option<Vec<RecordField>> {
342 None
343 }
344
345 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
346 where
347 S: Serializer,
348 B: Borrow<[u8]> + serde_bytes::Serialize,
349 {
350 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
351 serde_bytes::serialize(bytes, serializer)
352 }
353
354 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<Option<[u8; N]>, D::Error>
355 where
356 D: Deserializer<'de>,
357 {
358 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
359 serde_bytes::deserialize(deserializer)
360 }
361}
362
363pub mod slice {
390 use std::collections::HashSet;
391
392 use serde::{Deserializer, Serializer};
393
394 use super::BytesType;
395 use crate::{
396 Schema,
397 schema::{Name, NamespaceRef, RecordField},
398 };
399
400 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
402 Schema::Bytes
403 }
404
405 pub fn get_record_fields_in_ctxt(
407 _: usize,
408 _: &mut HashSet<Name>,
409 _: NamespaceRef,
410 ) -> Option<Vec<RecordField>> {
411 None
412 }
413
414 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
415 where
416 S: Serializer,
417 {
418 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
419 serde_bytes::serialize(bytes, serializer)
420 }
421
422 pub fn deserialize<'de, D>(deserializer: D) -> Result<&'de [u8], D::Error>
423 where
424 D: Deserializer<'de>,
425 {
426 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
427 let _guard = super::BorrowedGuard::set(true);
428 serde_bytes::deserialize(deserializer)
429 }
430}
431
432pub mod slice_opt {
459 use std::{borrow::Borrow, collections::HashSet};
460
461 use serde::{Deserializer, Serializer};
462
463 use super::BytesType;
464 use crate::{
465 Schema,
466 schema::{Name, NamespaceRef, RecordField, UnionSchema},
467 };
468
469 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
471 Schema::Union(
472 UnionSchema::new(vec![Schema::Null, Schema::Bytes])
473 .unwrap_or_else(|_| unreachable!("This is a valid union")),
474 )
475 }
476
477 pub fn get_record_fields_in_ctxt(
479 _: usize,
480 _: &mut HashSet<Name>,
481 _: NamespaceRef,
482 ) -> Option<Vec<RecordField>> {
483 None
484 }
485
486 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
487 where
488 S: Serializer,
489 B: Borrow<[u8]> + serde_bytes::Serialize,
490 {
491 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
492 serde_bytes::serialize(&bytes, serializer)
493 }
494
495 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<&'de [u8]>, D::Error>
496 where
497 D: Deserializer<'de>,
498 {
499 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
500 let _guard = super::BorrowedGuard::set(true);
501 serde_bytes::deserialize(deserializer)
502 }
503}
504
505pub mod bigdecimal {
530 use std::collections::HashSet;
531
532 use bigdecimal::BigDecimal;
533 use serde::{Deserializer, Serializer, de::Error as _, ser::Error as _};
534
535 use crate::{
536 Schema,
537 bigdecimal::{big_decimal_as_bytes, deserialize_big_decimal},
538 schema::{Name, NamespaceRef, RecordField},
539 serde::with::BytesType,
540 };
541
542 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
544 Schema::BigDecimal
545 }
546
547 pub fn get_record_fields_in_ctxt(
549 _: &mut HashSet<Name>,
550 _: NamespaceRef,
551 ) -> Option<Vec<RecordField>> {
552 None
553 }
554
555 pub fn serialize<S>(decimal: &BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
556 where
557 S: Serializer,
558 {
559 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
560 let decimal_bytes = big_decimal_as_bytes(decimal).map_err(S::Error::custom)?;
561 serde_bytes::serialize(&decimal_bytes, serializer)
562 }
563
564 pub fn deserialize<'de, D>(deserializer: D) -> Result<BigDecimal, D::Error>
565 where
566 D: Deserializer<'de>,
567 {
568 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
569 let _guard = super::BorrowedGuard::set(true);
570 let bytes: Vec<u8> = serde_bytes::deserialize(deserializer)?;
572
573 deserialize_big_decimal(&bytes).map_err(D::Error::custom)
574 }
575}
576
577pub mod bigdecimal_opt {
600 use std::collections::HashSet;
601
602 use bigdecimal::BigDecimal;
603 use serde::{Deserializer, Serializer, de::Error as _, ser::Error as _};
604
605 use crate::{
606 Schema,
607 bigdecimal::{big_decimal_as_bytes, deserialize_big_decimal},
608 schema::{Name, NamespaceRef, RecordField, UnionSchema},
609 serde::with::BytesType,
610 };
611
612 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
614 Schema::Union(
615 UnionSchema::new(vec![Schema::Null, Schema::BigDecimal])
616 .unwrap_or_else(|_| unreachable!("This is a valid union")),
617 )
618 }
619
620 pub fn get_record_fields_in_ctxt(
622 _: &mut HashSet<Name>,
623 _: NamespaceRef,
624 ) -> Option<Vec<RecordField>> {
625 None
626 }
627
628 pub fn serialize<S>(decimal: &Option<BigDecimal>, serializer: S) -> Result<S::Ok, S::Error>
629 where
630 S: Serializer,
631 {
632 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
633 if let Some(decimal) = decimal {
634 let decimal_bytes = big_decimal_as_bytes(decimal).map_err(S::Error::custom)?;
635 serde_bytes::serialize(&Some(decimal_bytes), serializer)
636 } else {
637 serde_bytes::serialize(&None::<Vec<u8>>, serializer)
638 }
639 }
640
641 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<BigDecimal>, D::Error>
642 where
643 D: Deserializer<'de>,
644 {
645 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
646 let _guard = super::BorrowedGuard::set(true);
647 let bytes: Option<Vec<u8>> = serde_bytes::deserialize(deserializer)?;
648 if let Some(bytes) = bytes {
649 deserialize_big_decimal(&bytes)
650 .map(Some)
651 .map_err(D::Error::custom)
652 } else {
653 Ok(None)
654 }
655 }
656}
657
658pub mod array {
679 use std::collections::HashSet;
680
681 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
682
683 use crate::{
684 AvroSchemaComponent, Schema,
685 schema::{Name, NamespaceRef, RecordField},
686 };
687
688 pub fn get_schema_in_ctxt<T: AvroSchemaComponent>(
690 named_schemas: &mut HashSet<Name>,
691 enclosing_namespace: NamespaceRef,
692 ) -> Schema {
693 Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)).build()
694 }
695
696 pub fn get_record_fields_in_ctxt(
698 _: &mut HashSet<Name>,
699 _: NamespaceRef,
700 ) -> Option<Vec<RecordField>> {
701 None
702 }
703
704 pub fn serialize<const N: usize, S, T>(value: &[T; N], serializer: S) -> Result<S::Ok, S::Error>
705 where
706 S: Serializer,
707 T: Serialize,
708 {
709 value.as_slice().serialize(serializer)
710 }
711
712 pub fn deserialize<'de, const N: usize, D, T>(deserializer: D) -> Result<[T; N], D::Error>
713 where
714 D: Deserializer<'de>,
715 T: Deserialize<'de>,
716 {
717 let bytes = <Vec<T> as Deserialize>::deserialize(deserializer)?;
718 bytes.try_into().map_err(|v: Vec<T>| {
719 D::Error::custom(format!(
720 "Deserialized array has length {} which does not match array length of {N}",
721 v.len()
722 ))
723 })
724 }
725}
726
727pub mod array_opt {
747 use std::collections::HashSet;
748
749 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
750
751 use crate::{
752 AvroSchemaComponent, Schema,
753 schema::{Name, NamespaceRef, RecordField, UnionSchema},
754 };
755
756 pub fn get_schema_in_ctxt<T: AvroSchemaComponent>(
758 named_schemas: &mut HashSet<Name>,
759 enclosing_namespace: NamespaceRef,
760 ) -> Schema {
761 Schema::Union(
762 UnionSchema::new(vec![
763 Schema::Null,
764 Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)).build(),
765 ])
766 .unwrap_or_else(|_| unreachable!("This is a valid union")),
767 )
768 }
769
770 pub fn get_record_fields_in_ctxt(
772 _: &mut HashSet<Name>,
773 _: NamespaceRef,
774 ) -> Option<Vec<RecordField>> {
775 None
776 }
777
778 pub fn serialize<const N: usize, S, T>(
779 value: &Option<[T; N]>,
780 serializer: S,
781 ) -> Result<S::Ok, S::Error>
782 where
783 S: Serializer,
784 T: Serialize,
785 {
786 if let Some(array) = value {
787 Some(array.as_slice()).serialize(serializer)
788 } else {
789 None::<Vec<T>>.serialize(serializer)
790 }
791 }
792
793 pub fn deserialize<'de, const N: usize, D, T>(
794 deserializer: D,
795 ) -> Result<Option<[T; N]>, D::Error>
796 where
797 D: Deserializer<'de>,
798 T: Deserialize<'de>,
799 {
800 let bytes = <Option<Vec<T>> as Deserialize>::deserialize(deserializer)?;
801 if let Some(bytes) = bytes {
802 Ok(Some(bytes.try_into().map_err(|v: Vec<T>| {
803 D::Error::custom(format!(
804 "Deserialized array has length {} which does not match array length of {N}",
805 v.len()
806 ))
807 })?))
808 } else {
809 Ok(None)
810 }
811 }
812}
813
814#[cfg(test)]
815mod tests {
816 use serde::{Deserialize, Serialize};
817
818 use crate::{Schema, from_value, to_value, types::Value};
819
820 #[test]
821 fn avro_3631_validate_schema_for_struct_with_byte_types() {
822 #[derive(Debug, Serialize)]
823 struct TestStructWithBytes<'a> {
824 #[serde(with = "crate::serde::bytes")]
825 vec_field: Vec<u8>,
826 #[serde(with = "crate::serde::bytes_opt")]
827 vec_field_opt: Option<Vec<u8>>,
828
829 #[serde(with = "crate::serde::fixed")]
830 fixed_field: [u8; 6],
831 #[serde(with = "crate::serde::fixed_opt")]
832 fixed_field_opt: Option<[u8; 7]>,
833
834 #[serde(with = "crate::serde::slice")]
835 slice_field: &'a [u8],
836 #[serde(with = "crate::serde::slice_opt")]
837 slice_field_opt: Option<&'a [u8]>,
838 }
839
840 let test = TestStructWithBytes {
841 vec_field: vec![2, 3, 4],
842 vec_field_opt: Some(vec![2, 3, 4]),
843 fixed_field: [1; 6],
844 fixed_field_opt: Some([1; 7]),
845 slice_field: &[1, 2, 3],
846 slice_field_opt: Some(&[1, 2, 3]),
847 };
848 let value: Value = to_value(test).unwrap();
849 let schema = Schema::parse_str(
850 r#"
851 {
852 "type": "record",
853 "name": "TestStructWithBytes",
854 "fields": [ {
855 "name": "vec_field",
856 "type": "bytes"
857 }, {
858 "name": "vec_field_opt",
859 "type": ["null", "bytes"]
860 }, {
861 "name": "fixed_field",
862 "type": {
863 "name": "ByteData",
864 "type": "fixed",
865 "size": 6
866 }
867 }, {
868 "name": "fixed_field_opt",
869 "type": ["null", {
870 "name": "ByteData2",
871 "type": "fixed",
872 "size": 7
873 } ]
874 }, {
875 "name": "slice_field",
876 "type": "bytes"
877 }, {
878 "name": "slice_field_opt",
879 "type": ["null", "bytes"]
880 } ]
881 }"#,
882 )
883 .unwrap();
884 assert!(value.validate(&schema));
885 }
886
887 #[test]
888 fn avro_3631_deserialize_value_to_struct_with_byte_types() {
889 #[derive(Debug, Deserialize, PartialEq)]
890 struct TestStructWithBytes<'a> {
891 #[serde(with = "crate::serde::bytes")]
892 vec_field: Vec<u8>,
893 #[serde(with = "crate::serde::bytes_opt")]
894 vec_field_opt: Option<Vec<u8>>,
895 #[serde(with = "crate::serde::bytes_opt")]
896 vec_field_opt2: Option<Vec<u8>>,
897
898 #[serde(with = "crate::serde::fixed")]
899 fixed_field: [u8; 6],
900 #[serde(with = "crate::serde::fixed_opt")]
901 fixed_field_opt: Option<[u8; 7]>,
902 #[serde(with = "crate::serde::fixed_opt")]
903 fixed_field_opt2: Option<[u8; 8]>,
904
905 #[serde(with = "crate::serde::slice")]
906 slice_bytes_field: &'a [u8],
907 #[serde(with = "crate::serde::slice_opt")]
908 slice_bytes_field_opt: Option<&'a [u8]>,
909 #[serde(with = "crate::serde::slice_opt")]
910 slice_bytes_field_opt2: Option<&'a [u8]>,
911
912 #[serde(with = "crate::serde::slice")]
913 slice_fixed_field: &'a [u8],
914 #[serde(with = "crate::serde::slice_opt")]
915 slice_fixed_field_opt: Option<&'a [u8]>,
916 #[serde(with = "crate::serde::slice_opt")]
917 slice_fixed_field_opt2: Option<&'a [u8]>,
918 }
919
920 let expected = TestStructWithBytes {
921 vec_field: vec![3, 33],
922 vec_field_opt: Some(vec![4, 44]),
923 vec_field_opt2: None,
924 fixed_field: [1; 6],
925 fixed_field_opt: Some([7; 7]),
926 fixed_field_opt2: None,
927 slice_bytes_field: &[1, 11, 111],
928 slice_bytes_field_opt: Some(&[5, 5, 5, 5, 5]),
929 slice_bytes_field_opt2: None,
930 slice_fixed_field: &[2, 22, 222],
931 slice_fixed_field_opt: Some(&[3, 3, 3]),
932 slice_fixed_field_opt2: None,
933 };
934
935 let value = Value::Record(vec![
936 (
937 "vec_field".to_owned(),
938 Value::Bytes(expected.vec_field.clone()),
939 ),
940 (
941 "vec_field_opt".to_owned(),
942 Value::Union(
943 1,
944 Box::new(Value::Bytes(
945 expected.vec_field_opt.as_ref().unwrap().clone(),
946 )),
947 ),
948 ),
949 (
950 "vec_field_opt2".to_owned(),
951 Value::Union(0, Box::new(Value::Null)),
952 ),
953 (
954 "fixed_field".to_owned(),
955 Value::Fixed(expected.fixed_field.len(), expected.fixed_field.to_vec()),
956 ),
957 (
958 "fixed_field_opt".to_owned(),
959 Value::Union(
960 1,
961 Box::new(Value::Fixed(
962 expected.fixed_field_opt.as_ref().unwrap().len(),
963 expected.fixed_field_opt.as_ref().unwrap().to_vec(),
964 )),
965 ),
966 ),
967 (
968 "fixed_field_opt2".to_owned(),
969 Value::Union(0, Box::new(Value::Null)),
970 ),
971 (
972 "slice_bytes_field".to_owned(),
973 Value::Bytes(expected.slice_bytes_field.to_vec()),
974 ),
975 (
976 "slice_bytes_field_opt".to_owned(),
977 Value::Union(
978 1,
979 Box::new(Value::Bytes(
980 expected.slice_bytes_field_opt.as_ref().unwrap().to_vec(),
981 )),
982 ),
983 ),
984 (
985 "slice_bytes_field_opt2".to_owned(),
986 Value::Union(0, Box::new(Value::Null)),
987 ),
988 (
989 "slice_fixed_field".to_owned(),
990 Value::Fixed(
991 expected.slice_fixed_field.len(),
992 expected.slice_fixed_field.to_vec(),
993 ),
994 ),
995 (
996 "slice_fixed_field_opt".to_owned(),
997 Value::Union(
998 1,
999 Box::new(Value::Fixed(
1000 expected.slice_fixed_field_opt.as_ref().unwrap().len(),
1001 expected.slice_fixed_field_opt.as_ref().unwrap().to_vec(),
1002 )),
1003 ),
1004 ),
1005 (
1006 "slice_fixed_field_opt2".to_owned(),
1007 Value::Union(1, Box::new(Value::Null)),
1008 ),
1009 ]);
1010 assert_eq!(expected, from_value(&value).unwrap());
1011 }
1012
1013 #[test]
1014 fn avro_3631_serialize_struct_to_value_with_byte_types() {
1015 #[derive(Debug, Serialize)]
1016 struct TestStructWithBytes<'a> {
1017 array_field: &'a [u8],
1018 vec_field: Vec<u8>,
1019
1020 #[serde(with = "crate::serde::fixed")]
1021 vec_field2: Vec<u8>,
1022 #[serde(with = "crate::serde::fixed_opt")]
1023 vec_field2_opt: Option<Vec<u8>>,
1024 #[serde(with = "crate::serde::fixed_opt")]
1025 vec_field2_opt2: Option<Vec<u8>>,
1026
1027 #[serde(with = "crate::serde::bytes")]
1028 vec_field3: Vec<u8>,
1029 #[serde(with = "crate::serde::bytes_opt")]
1030 vec_field3_opt: Option<Vec<u8>>,
1031 #[serde(with = "crate::serde::bytes_opt")]
1032 vec_field3_opt2: Option<Vec<u8>>,
1033
1034 #[serde(with = "crate::serde::fixed")]
1035 fixed_field: [u8; 6],
1036 #[serde(with = "crate::serde::fixed_opt")]
1037 fixed_field_opt: Option<[u8; 5]>,
1038 #[serde(with = "crate::serde::fixed_opt")]
1039 fixed_field_opt2: Option<[u8; 4]>,
1040
1041 #[serde(with = "crate::serde::fixed")]
1042 fixed_field2: &'a [u8],
1043 #[serde(with = "crate::serde::fixed_opt")]
1044 fixed_field2_opt: Option<&'a [u8]>,
1045 #[serde(with = "crate::serde::fixed_opt")]
1046 fixed_field2_opt2: Option<&'a [u8]>,
1047
1048 #[serde(with = "crate::serde::bytes")]
1049 bytes_field: &'a [u8],
1050 #[serde(with = "crate::serde::bytes_opt")]
1051 bytes_field_opt: Option<&'a [u8]>,
1052 #[serde(with = "crate::serde::bytes_opt")]
1053 bytes_field_opt2: Option<&'a [u8]>,
1054
1055 #[serde(with = "crate::serde::bytes")]
1056 bytes_field2: [u8; 6],
1057 #[serde(with = "crate::serde::bytes_opt")]
1058 bytes_field2_opt: Option<[u8; 7]>,
1059 #[serde(with = "crate::serde::bytes_opt")]
1060 bytes_field2_opt2: Option<[u8; 8]>,
1061 }
1062
1063 let test = TestStructWithBytes {
1064 array_field: &[1, 11, 111],
1065 vec_field: vec![3, 33],
1066 vec_field2: vec![4, 44],
1067 vec_field2_opt: Some(vec![14, 144]),
1068 vec_field2_opt2: None,
1069 vec_field3: vec![5, 55],
1070 vec_field3_opt: Some(vec![15, 155]),
1071 vec_field3_opt2: None,
1072 fixed_field: [1; 6],
1073 fixed_field_opt: Some([6; 5]),
1074 fixed_field_opt2: None,
1075 fixed_field2: &[6, 66],
1076 fixed_field2_opt: Some(&[7, 77]),
1077 fixed_field2_opt2: None,
1078 bytes_field: &[2, 22, 222],
1079 bytes_field_opt: Some(&[3, 33, 233]),
1080 bytes_field_opt2: None,
1081 bytes_field2: [2; 6],
1082 bytes_field2_opt: Some([2; 7]),
1083 bytes_field2_opt2: None,
1084 };
1085 let expected = Value::Record(vec![
1086 (
1087 "array_field".to_owned(),
1088 Value::Array(
1089 test.array_field
1090 .iter()
1091 .map(|&i| Value::Int(i as i32))
1092 .collect(),
1093 ),
1094 ),
1095 (
1096 "vec_field".to_owned(),
1097 Value::Array(
1098 test.vec_field
1099 .iter()
1100 .map(|&i| Value::Int(i as i32))
1101 .collect(),
1102 ),
1103 ),
1104 (
1105 "vec_field2".to_owned(),
1106 Value::Fixed(test.vec_field2.len(), test.vec_field2.clone()),
1107 ),
1108 (
1109 "vec_field2_opt".to_owned(),
1110 Value::Union(
1111 1,
1112 Box::new(Value::Fixed(
1113 test.vec_field2_opt.as_ref().unwrap().len(),
1114 test.vec_field2_opt.as_ref().unwrap().to_vec(),
1115 )),
1116 ),
1117 ),
1118 (
1119 "vec_field2_opt2".to_owned(),
1120 Value::Union(0, Box::new(Value::Null)),
1121 ),
1122 (
1123 "vec_field3".to_owned(),
1124 Value::Bytes(test.vec_field3.clone()),
1125 ),
1126 (
1127 "vec_field3_opt".to_owned(),
1128 Value::Union(
1129 1,
1130 Box::new(Value::Bytes(test.vec_field3_opt.as_ref().unwrap().clone())),
1131 ),
1132 ),
1133 (
1134 "vec_field3_opt2".to_owned(),
1135 Value::Union(0, Box::new(Value::Null)),
1136 ),
1137 (
1138 "fixed_field".to_owned(),
1139 Value::Fixed(test.fixed_field.len(), test.fixed_field.to_vec()),
1140 ),
1141 (
1142 "fixed_field_opt".to_owned(),
1143 Value::Union(
1144 1,
1145 Box::new(Value::Fixed(
1146 test.fixed_field_opt.as_ref().unwrap().len(),
1147 test.fixed_field_opt.as_ref().unwrap().to_vec(),
1148 )),
1149 ),
1150 ),
1151 (
1152 "fixed_field_opt2".to_owned(),
1153 Value::Union(0, Box::new(Value::Null)),
1154 ),
1155 (
1156 "fixed_field2".to_owned(),
1157 Value::Fixed(test.fixed_field2.len(), test.fixed_field2.to_vec()),
1158 ),
1159 (
1160 "fixed_field2_opt".to_owned(),
1161 Value::Union(
1162 1,
1163 Box::new(Value::Fixed(
1164 test.fixed_field2_opt.as_ref().unwrap().len(),
1165 test.fixed_field2_opt.as_ref().unwrap().to_vec(),
1166 )),
1167 ),
1168 ),
1169 (
1170 "fixed_field2_opt2".to_owned(),
1171 Value::Union(0, Box::new(Value::Null)),
1172 ),
1173 (
1174 "bytes_field".to_owned(),
1175 Value::Bytes(test.bytes_field.to_vec()),
1176 ),
1177 (
1178 "bytes_field_opt".to_owned(),
1179 Value::Union(
1180 1,
1181 Box::new(Value::Bytes(
1182 test.bytes_field_opt.as_ref().unwrap().to_vec(),
1183 )),
1184 ),
1185 ),
1186 (
1187 "bytes_field_opt2".to_owned(),
1188 Value::Union(0, Box::new(Value::Null)),
1189 ),
1190 (
1191 "bytes_field2".to_owned(),
1192 Value::Bytes(test.bytes_field2.to_vec()),
1193 ),
1194 (
1195 "bytes_field2_opt".to_owned(),
1196 Value::Union(
1197 1,
1198 Box::new(Value::Bytes(
1199 test.bytes_field2_opt.as_ref().unwrap().to_vec(),
1200 )),
1201 ),
1202 ),
1203 (
1204 "bytes_field2_opt2".to_owned(),
1205 Value::Union(0, Box::new(Value::Null)),
1206 ),
1207 ]);
1208 assert_eq!(expected, to_value(test).unwrap());
1209 }
1210}