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 super::BytesType;
97 use std::collections::HashSet;
98
99 use serde::{Deserializer, Serializer};
100
101 use crate::schema::NamespaceRef;
102 use crate::{
103 Schema,
104 schema::{Name, RecordField},
105 };
106
107 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
109 Schema::Bytes
110 }
111
112 pub fn get_record_fields_in_ctxt(
114 _: usize,
115 _: &mut HashSet<Name>,
116 _: NamespaceRef,
117 ) -> Option<Vec<RecordField>> {
118 None
119 }
120
121 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
122 where
123 S: Serializer,
124 {
125 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
126 serde_bytes::serialize(bytes, serializer)
127 }
128
129 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
130 where
131 D: Deserializer<'de>,
132 {
133 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
134 serde_bytes::deserialize(deserializer)
135 }
136}
137
138pub mod bytes_opt {
163 use super::BytesType;
164 use serde::{Deserializer, Serializer};
165 use std::{borrow::Borrow, collections::HashSet};
166
167 use crate::schema::NamespaceRef;
168 use crate::{
169 Schema,
170 schema::{Name, RecordField, UnionSchema},
171 };
172
173 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
175 Schema::Union(
176 UnionSchema::new(vec![Schema::Null, Schema::Bytes]).expect("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 super::BytesType;
235 use serde::{Deserializer, Serializer};
236
237 use crate::schema::NamespaceRef;
238 use crate::{
239 Schema,
240 schema::{FixedSchema, Name, RecordField},
241 };
242
243 pub fn get_schema_in_ctxt<const N: usize>(
245 named_schemas: &mut HashSet<Name>,
246 enclosing_namespace: NamespaceRef,
247 ) -> Schema {
248 let name = Name::new_with_enclosing_namespace(
249 format!("serde_avro_fixed_{N}"),
250 enclosing_namespace,
251 )
252 .expect("Name is valid");
253 if named_schemas.contains(&name) {
254 Schema::Ref { name }
255 } else {
256 let schema = Schema::Fixed(FixedSchema::builder().name(name.clone()).size(N).build());
257 named_schemas.insert(name);
258 schema
259 }
260 }
261
262 pub fn get_record_fields_in_ctxt(
264 _: usize,
265 _: &mut HashSet<Name>,
266 _: NamespaceRef,
267 ) -> Option<Vec<RecordField>> {
268 None
269 }
270
271 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
272 where
273 S: Serializer,
274 {
275 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
276 serde_bytes::serialize(bytes, serializer)
277 }
278
279 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
280 where
281 D: Deserializer<'de>,
282 {
283 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
284 serde_bytes::deserialize(deserializer)
285 }
286}
287
288pub mod fixed_opt {
313 use super::BytesType;
314 use serde::{Deserializer, Serializer};
315 use std::{borrow::Borrow, collections::HashSet};
316
317 use crate::schema::NamespaceRef;
318 use crate::{
319 Schema,
320 schema::{Name, RecordField, UnionSchema},
321 };
322
323 pub fn get_schema_in_ctxt<const N: usize>(
325 named_schemas: &mut HashSet<Name>,
326 enclosing_namespace: NamespaceRef,
327 ) -> Schema {
328 Schema::Union(
329 UnionSchema::new(vec![
330 Schema::Null,
331 super::fixed::get_schema_in_ctxt::<N>(named_schemas, enclosing_namespace),
332 ])
333 .expect("This is a valid union"),
334 )
335 }
336
337 pub fn get_record_fields_in_ctxt(
339 _: usize,
340 _: &mut HashSet<Name>,
341 _: NamespaceRef,
342 ) -> Option<Vec<RecordField>> {
343 None
344 }
345
346 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
347 where
348 S: Serializer,
349 B: Borrow<[u8]> + serde_bytes::Serialize,
350 {
351 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
352 serde_bytes::serialize(bytes, serializer)
353 }
354
355 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<Option<[u8; N]>, D::Error>
356 where
357 D: Deserializer<'de>,
358 {
359 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
360 serde_bytes::deserialize(deserializer)
361 }
362}
363
364pub mod slice {
391 use super::BytesType;
392 use std::collections::HashSet;
393
394 use serde::{Deserializer, Serializer};
395
396 use crate::schema::NamespaceRef;
397 use crate::{
398 Schema,
399 schema::{Name, RecordField},
400 };
401
402 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
404 Schema::Bytes
405 }
406
407 pub fn get_record_fields_in_ctxt(
409 _: usize,
410 _: &mut HashSet<Name>,
411 _: NamespaceRef,
412 ) -> Option<Vec<RecordField>> {
413 None
414 }
415
416 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
417 where
418 S: Serializer,
419 {
420 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
421 serde_bytes::serialize(bytes, serializer)
422 }
423
424 pub fn deserialize<'de, D>(deserializer: D) -> Result<&'de [u8], D::Error>
425 where
426 D: Deserializer<'de>,
427 {
428 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
429 let _guard = super::BorrowedGuard::set(true);
430 serde_bytes::deserialize(deserializer)
431 }
432}
433
434pub mod slice_opt {
461 use super::BytesType;
462 use serde::{Deserializer, Serializer};
463 use std::{borrow::Borrow, collections::HashSet};
464
465 use crate::schema::NamespaceRef;
466 use crate::{
467 Schema,
468 schema::{Name, RecordField, UnionSchema},
469 };
470
471 pub fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
473 Schema::Union(
474 UnionSchema::new(vec![Schema::Null, Schema::Bytes]).expect("This is a valid union"),
475 )
476 }
477
478 pub fn get_record_fields_in_ctxt(
480 _: usize,
481 _: &mut HashSet<Name>,
482 _: NamespaceRef,
483 ) -> Option<Vec<RecordField>> {
484 None
485 }
486
487 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
488 where
489 S: Serializer,
490 B: Borrow<[u8]> + serde_bytes::Serialize,
491 {
492 let _guard = super::BytesTypeGuard::set(BytesType::Bytes);
493 serde_bytes::serialize(&bytes, serializer)
494 }
495
496 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<&'de [u8]>, D::Error>
497 where
498 D: Deserializer<'de>,
499 {
500 let _bytes_guard = super::BytesTypeGuard::set(BytesType::Bytes);
501 let _guard = super::BorrowedGuard::set(true);
502 serde_bytes::deserialize(deserializer)
503 }
504}
505
506#[cfg(test)]
507mod tests {
508 use crate::{Schema, from_value, to_value, types::Value};
509 use serde::{Deserialize, Serialize};
510
511 #[test]
512 fn avro_3631_validate_schema_for_struct_with_byte_types() {
513 #[derive(Debug, Serialize)]
514 struct TestStructWithBytes<'a> {
515 #[serde(with = "crate::serde::bytes")]
516 vec_field: Vec<u8>,
517 #[serde(with = "crate::serde::bytes_opt")]
518 vec_field_opt: Option<Vec<u8>>,
519
520 #[serde(with = "crate::serde::fixed")]
521 fixed_field: [u8; 6],
522 #[serde(with = "crate::serde::fixed_opt")]
523 fixed_field_opt: Option<[u8; 7]>,
524
525 #[serde(with = "crate::serde::slice")]
526 slice_field: &'a [u8],
527 #[serde(with = "crate::serde::slice_opt")]
528 slice_field_opt: Option<&'a [u8]>,
529 }
530
531 let test = TestStructWithBytes {
532 vec_field: vec![2, 3, 4],
533 vec_field_opt: Some(vec![2, 3, 4]),
534 fixed_field: [1; 6],
535 fixed_field_opt: Some([1; 7]),
536 slice_field: &[1, 2, 3],
537 slice_field_opt: Some(&[1, 2, 3]),
538 };
539 let value: Value = to_value(test).unwrap();
540 let schema = Schema::parse_str(
541 r#"
542 {
543 "type": "record",
544 "name": "TestStructWithBytes",
545 "fields": [ {
546 "name": "vec_field",
547 "type": "bytes"
548 }, {
549 "name": "vec_field_opt",
550 "type": ["null", "bytes"]
551 }, {
552 "name": "fixed_field",
553 "type": {
554 "name": "ByteData",
555 "type": "fixed",
556 "size": 6
557 }
558 }, {
559 "name": "fixed_field_opt",
560 "type": ["null", {
561 "name": "ByteData2",
562 "type": "fixed",
563 "size": 7
564 } ]
565 }, {
566 "name": "slice_field",
567 "type": "bytes"
568 }, {
569 "name": "slice_field_opt",
570 "type": ["null", "bytes"]
571 } ]
572 }"#,
573 )
574 .unwrap();
575 assert!(value.validate(&schema));
576 }
577
578 #[test]
579 fn avro_3631_deserialize_value_to_struct_with_byte_types() {
580 #[derive(Debug, Deserialize, PartialEq)]
581 struct TestStructWithBytes<'a> {
582 #[serde(with = "crate::serde::bytes")]
583 vec_field: Vec<u8>,
584 #[serde(with = "crate::serde::bytes_opt")]
585 vec_field_opt: Option<Vec<u8>>,
586 #[serde(with = "crate::serde::bytes_opt")]
587 vec_field_opt2: Option<Vec<u8>>,
588
589 #[serde(with = "crate::serde::fixed")]
590 fixed_field: [u8; 6],
591 #[serde(with = "crate::serde::fixed_opt")]
592 fixed_field_opt: Option<[u8; 7]>,
593 #[serde(with = "crate::serde::fixed_opt")]
594 fixed_field_opt2: Option<[u8; 8]>,
595
596 #[serde(with = "crate::serde::slice")]
597 slice_bytes_field: &'a [u8],
598 #[serde(with = "crate::serde::slice_opt")]
599 slice_bytes_field_opt: Option<&'a [u8]>,
600 #[serde(with = "crate::serde::slice_opt")]
601 slice_bytes_field_opt2: Option<&'a [u8]>,
602
603 #[serde(with = "crate::serde::slice")]
604 slice_fixed_field: &'a [u8],
605 #[serde(with = "crate::serde::slice_opt")]
606 slice_fixed_field_opt: Option<&'a [u8]>,
607 #[serde(with = "crate::serde::slice_opt")]
608 slice_fixed_field_opt2: Option<&'a [u8]>,
609 }
610
611 let expected = TestStructWithBytes {
612 vec_field: vec![3, 33],
613 vec_field_opt: Some(vec![4, 44]),
614 vec_field_opt2: None,
615 fixed_field: [1; 6],
616 fixed_field_opt: Some([7; 7]),
617 fixed_field_opt2: None,
618 slice_bytes_field: &[1, 11, 111],
619 slice_bytes_field_opt: Some(&[5, 5, 5, 5, 5]),
620 slice_bytes_field_opt2: None,
621 slice_fixed_field: &[2, 22, 222],
622 slice_fixed_field_opt: Some(&[3, 3, 3]),
623 slice_fixed_field_opt2: None,
624 };
625
626 let value = Value::Record(vec![
627 (
628 "vec_field".to_owned(),
629 Value::Bytes(expected.vec_field.clone()),
630 ),
631 (
632 "vec_field_opt".to_owned(),
633 Value::Union(
634 1,
635 Box::new(Value::Bytes(
636 expected.vec_field_opt.as_ref().unwrap().clone(),
637 )),
638 ),
639 ),
640 (
641 "vec_field_opt2".to_owned(),
642 Value::Union(0, Box::new(Value::Null)),
643 ),
644 (
645 "fixed_field".to_owned(),
646 Value::Fixed(expected.fixed_field.len(), expected.fixed_field.to_vec()),
647 ),
648 (
649 "fixed_field_opt".to_owned(),
650 Value::Union(
651 1,
652 Box::new(Value::Fixed(
653 expected.fixed_field_opt.as_ref().unwrap().len(),
654 expected.fixed_field_opt.as_ref().unwrap().to_vec(),
655 )),
656 ),
657 ),
658 (
659 "fixed_field_opt2".to_owned(),
660 Value::Union(0, Box::new(Value::Null)),
661 ),
662 (
663 "slice_bytes_field".to_owned(),
664 Value::Bytes(expected.slice_bytes_field.to_vec()),
665 ),
666 (
667 "slice_bytes_field_opt".to_owned(),
668 Value::Union(
669 1,
670 Box::new(Value::Bytes(
671 expected.slice_bytes_field_opt.as_ref().unwrap().to_vec(),
672 )),
673 ),
674 ),
675 (
676 "slice_bytes_field_opt2".to_owned(),
677 Value::Union(0, Box::new(Value::Null)),
678 ),
679 (
680 "slice_fixed_field".to_owned(),
681 Value::Fixed(
682 expected.slice_fixed_field.len(),
683 expected.slice_fixed_field.to_vec(),
684 ),
685 ),
686 (
687 "slice_fixed_field_opt".to_owned(),
688 Value::Union(
689 1,
690 Box::new(Value::Fixed(
691 expected.slice_fixed_field_opt.as_ref().unwrap().len(),
692 expected.slice_fixed_field_opt.as_ref().unwrap().to_vec(),
693 )),
694 ),
695 ),
696 (
697 "slice_fixed_field_opt2".to_owned(),
698 Value::Union(1, Box::new(Value::Null)),
699 ),
700 ]);
701 assert_eq!(expected, from_value(&value).unwrap());
702 }
703
704 #[test]
705 fn avro_3631_serialize_struct_to_value_with_byte_types() {
706 #[derive(Debug, Serialize)]
707 struct TestStructWithBytes<'a> {
708 array_field: &'a [u8],
709 vec_field: Vec<u8>,
710
711 #[serde(with = "crate::serde::fixed")]
712 vec_field2: Vec<u8>,
713 #[serde(with = "crate::serde::fixed_opt")]
714 vec_field2_opt: Option<Vec<u8>>,
715 #[serde(with = "crate::serde::fixed_opt")]
716 vec_field2_opt2: Option<Vec<u8>>,
717
718 #[serde(with = "crate::serde::bytes")]
719 vec_field3: Vec<u8>,
720 #[serde(with = "crate::serde::bytes_opt")]
721 vec_field3_opt: Option<Vec<u8>>,
722 #[serde(with = "crate::serde::bytes_opt")]
723 vec_field3_opt2: Option<Vec<u8>>,
724
725 #[serde(with = "crate::serde::fixed")]
726 fixed_field: [u8; 6],
727 #[serde(with = "crate::serde::fixed_opt")]
728 fixed_field_opt: Option<[u8; 5]>,
729 #[serde(with = "crate::serde::fixed_opt")]
730 fixed_field_opt2: Option<[u8; 4]>,
731
732 #[serde(with = "crate::serde::fixed")]
733 fixed_field2: &'a [u8],
734 #[serde(with = "crate::serde::fixed_opt")]
735 fixed_field2_opt: Option<&'a [u8]>,
736 #[serde(with = "crate::serde::fixed_opt")]
737 fixed_field2_opt2: Option<&'a [u8]>,
738
739 #[serde(with = "crate::serde::bytes")]
740 bytes_field: &'a [u8],
741 #[serde(with = "crate::serde::bytes_opt")]
742 bytes_field_opt: Option<&'a [u8]>,
743 #[serde(with = "crate::serde::bytes_opt")]
744 bytes_field_opt2: Option<&'a [u8]>,
745
746 #[serde(with = "crate::serde::bytes")]
747 bytes_field2: [u8; 6],
748 #[serde(with = "crate::serde::bytes_opt")]
749 bytes_field2_opt: Option<[u8; 7]>,
750 #[serde(with = "crate::serde::bytes_opt")]
751 bytes_field2_opt2: Option<[u8; 8]>,
752 }
753
754 let test = TestStructWithBytes {
755 array_field: &[1, 11, 111],
756 vec_field: vec![3, 33],
757 vec_field2: vec![4, 44],
758 vec_field2_opt: Some(vec![14, 144]),
759 vec_field2_opt2: None,
760 vec_field3: vec![5, 55],
761 vec_field3_opt: Some(vec![15, 155]),
762 vec_field3_opt2: None,
763 fixed_field: [1; 6],
764 fixed_field_opt: Some([6; 5]),
765 fixed_field_opt2: None,
766 fixed_field2: &[6, 66],
767 fixed_field2_opt: Some(&[7, 77]),
768 fixed_field2_opt2: None,
769 bytes_field: &[2, 22, 222],
770 bytes_field_opt: Some(&[3, 33, 233]),
771 bytes_field_opt2: None,
772 bytes_field2: [2; 6],
773 bytes_field2_opt: Some([2; 7]),
774 bytes_field2_opt2: None,
775 };
776 let expected = Value::Record(vec![
777 (
778 "array_field".to_owned(),
779 Value::Array(
780 test.array_field
781 .iter()
782 .map(|&i| Value::Int(i as i32))
783 .collect(),
784 ),
785 ),
786 (
787 "vec_field".to_owned(),
788 Value::Array(
789 test.vec_field
790 .iter()
791 .map(|&i| Value::Int(i as i32))
792 .collect(),
793 ),
794 ),
795 (
796 "vec_field2".to_owned(),
797 Value::Fixed(test.vec_field2.len(), test.vec_field2.clone()),
798 ),
799 (
800 "vec_field2_opt".to_owned(),
801 Value::Union(
802 1,
803 Box::new(Value::Fixed(
804 test.vec_field2_opt.as_ref().unwrap().len(),
805 test.vec_field2_opt.as_ref().unwrap().to_vec(),
806 )),
807 ),
808 ),
809 (
810 "vec_field2_opt2".to_owned(),
811 Value::Union(0, Box::new(Value::Null)),
812 ),
813 (
814 "vec_field3".to_owned(),
815 Value::Bytes(test.vec_field3.clone()),
816 ),
817 (
818 "vec_field3_opt".to_owned(),
819 Value::Union(
820 1,
821 Box::new(Value::Bytes(test.vec_field3_opt.as_ref().unwrap().clone())),
822 ),
823 ),
824 (
825 "vec_field3_opt2".to_owned(),
826 Value::Union(0, Box::new(Value::Null)),
827 ),
828 (
829 "fixed_field".to_owned(),
830 Value::Fixed(test.fixed_field.len(), test.fixed_field.to_vec()),
831 ),
832 (
833 "fixed_field_opt".to_owned(),
834 Value::Union(
835 1,
836 Box::new(Value::Fixed(
837 test.fixed_field_opt.as_ref().unwrap().len(),
838 test.fixed_field_opt.as_ref().unwrap().to_vec(),
839 )),
840 ),
841 ),
842 (
843 "fixed_field_opt2".to_owned(),
844 Value::Union(0, Box::new(Value::Null)),
845 ),
846 (
847 "fixed_field2".to_owned(),
848 Value::Fixed(test.fixed_field2.len(), test.fixed_field2.to_vec()),
849 ),
850 (
851 "fixed_field2_opt".to_owned(),
852 Value::Union(
853 1,
854 Box::new(Value::Fixed(
855 test.fixed_field2_opt.as_ref().unwrap().len(),
856 test.fixed_field2_opt.as_ref().unwrap().to_vec(),
857 )),
858 ),
859 ),
860 (
861 "fixed_field2_opt2".to_owned(),
862 Value::Union(0, Box::new(Value::Null)),
863 ),
864 (
865 "bytes_field".to_owned(),
866 Value::Bytes(test.bytes_field.to_vec()),
867 ),
868 (
869 "bytes_field_opt".to_owned(),
870 Value::Union(
871 1,
872 Box::new(Value::Bytes(
873 test.bytes_field_opt.as_ref().unwrap().to_vec(),
874 )),
875 ),
876 ),
877 (
878 "bytes_field_opt2".to_owned(),
879 Value::Union(0, Box::new(Value::Null)),
880 ),
881 (
882 "bytes_field2".to_owned(),
883 Value::Bytes(test.bytes_field2.to_vec()),
884 ),
885 (
886 "bytes_field2_opt".to_owned(),
887 Value::Union(
888 1,
889 Box::new(Value::Bytes(
890 test.bytes_field2_opt.as_ref().unwrap().to_vec(),
891 )),
892 ),
893 ),
894 (
895 "bytes_field2_opt2".to_owned(),
896 Value::Union(0, Box::new(Value::Null)),
897 ),
898 ]);
899 assert_eq!(expected, to_value(test).unwrap());
900 }
901}