1use std::cell::Cell;
19
20thread_local! {
21 pub(crate) static SER_BYTES_TYPE: Cell<BytesType> = const { Cell::new(BytesType::Bytes) };
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 Bytes,
37 Fixed,
38}
39
40struct BytesTypeGuard(BytesType);
41impl BytesTypeGuard {
42 fn set(temp: BytesType) -> Self {
43 let prev = SER_BYTES_TYPE.get();
44 SER_BYTES_TYPE.set(temp);
45 Self(prev)
46 }
47}
48
49impl Drop for BytesTypeGuard {
50 fn drop(&mut self) {
51 SER_BYTES_TYPE.set(self.0);
52 }
53}
54
55struct BorrowedGuard(bool);
56impl BorrowedGuard {
57 fn set(temp: bool) -> Self {
58 let prev = DE_BYTES_BORROWED.get();
59 DE_BYTES_BORROWED.set(temp);
60 Self(prev)
61 }
62}
63
64impl Drop for BorrowedGuard {
65 fn drop(&mut self) {
66 DE_BYTES_BORROWED.set(self.0);
67 }
68}
69
70pub mod bytes {
94 use serde::{Deserializer, Serializer};
95
96 use crate::{
97 Schema,
98 schema::{Names, Namespace},
99 };
100
101 pub fn get_schema_in_ctxt(_names: &mut Names, _enclosing_namespace: &Namespace) -> Schema {
103 Schema::Bytes
104 }
105
106 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
107 where
108 S: Serializer,
109 {
110 serde_bytes::serialize(bytes, serializer)
111 }
112
113 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
114 where
115 D: Deserializer<'de>,
116 {
117 serde_bytes::deserialize(deserializer)
118 }
119}
120
121pub mod bytes_opt {
145 use serde::{Deserializer, Serializer};
146 use std::borrow::Borrow;
147
148 use crate::{
149 Schema,
150 schema::{Names, Namespace, UnionSchema},
151 };
152
153 pub fn get_schema_in_ctxt(_names: &mut Names, _enclosing_namespace: &Namespace) -> Schema {
155 Schema::Union(
156 UnionSchema::new(vec![Schema::Null, Schema::Bytes]).expect("This is a valid union"),
157 )
158 }
159
160 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
161 where
162 S: Serializer,
163 B: Borrow<[u8]> + serde_bytes::Serialize,
164 {
165 serde_bytes::serialize(bytes, serializer)
166 }
167
168 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
169 where
170 D: Deserializer<'de>,
171 {
172 serde_bytes::deserialize(deserializer)
173 }
174}
175
176pub mod fixed {
200 use super::BytesType;
201 use serde::{Deserializer, Serializer};
202
203 use crate::{
204 Schema,
205 schema::{FixedSchema, Name, Names, Namespace},
206 };
207
208 #[expect(clippy::map_entry, reason = "We don't use the value from the map")]
210 pub fn get_schema_in_ctxt<const N: usize>(
211 named_schemas: &mut Names,
212 enclosing_namespace: &Namespace,
213 ) -> Schema {
214 let name = Name::new(&format!("serde_avro_fixed_{N}"))
215 .expect("Name is valid")
216 .fully_qualified_name(enclosing_namespace);
217 if named_schemas.contains_key(&name) {
218 Schema::Ref { name }
219 } else {
220 let schema = Schema::Fixed(FixedSchema::builder().name(name.clone()).size(N).build());
221 named_schemas.insert(name, schema.clone());
222 schema
223 }
224 }
225
226 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
227 where
228 S: Serializer,
229 {
230 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
231 serde_bytes::serialize(bytes, serializer)
232 }
233
234 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
235 where
236 D: Deserializer<'de>,
237 {
238 serde_bytes::deserialize(deserializer)
239 }
240}
241
242pub mod fixed_opt {
266 use super::BytesType;
267 use serde::{Deserializer, Serializer};
268 use std::borrow::Borrow;
269
270 use crate::{
271 Schema,
272 schema::{Names, Namespace, UnionSchema},
273 };
274
275 pub fn get_schema_in_ctxt<const N: usize>(
277 named_schemas: &mut Names,
278 enclosing_namespace: &Namespace,
279 ) -> Schema {
280 Schema::Union(
281 UnionSchema::new(vec![
282 Schema::Null,
283 super::fixed::get_schema_in_ctxt::<N>(named_schemas, enclosing_namespace),
284 ])
285 .expect("This is a valid union"),
286 )
287 }
288
289 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
290 where
291 S: Serializer,
292 B: Borrow<[u8]> + serde_bytes::Serialize,
293 {
294 let _guard = super::BytesTypeGuard::set(BytesType::Fixed);
295 serde_bytes::serialize(bytes, serializer)
296 }
297
298 pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<Option<[u8; N]>, D::Error>
299 where
300 D: Deserializer<'de>,
301 {
302 serde_bytes::deserialize(deserializer)
303 }
304}
305
306pub mod slice {
332 use serde::{Deserializer, Serializer};
333
334 use crate::{
335 Schema,
336 schema::{Names, Namespace},
337 };
338
339 pub fn get_schema_in_ctxt(_names: &mut Names, _enclosing_namespace: &Namespace) -> Schema {
341 Schema::Bytes
342 }
343
344 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
345 where
346 S: Serializer,
347 {
348 serde_bytes::serialize(bytes, serializer)
349 }
350
351 pub fn deserialize<'de, D>(deserializer: D) -> Result<&'de [u8], D::Error>
352 where
353 D: Deserializer<'de>,
354 {
355 let _guard = super::BorrowedGuard::set(true);
356 serde_bytes::deserialize(deserializer)
357 }
358}
359
360pub mod slice_opt {
386 use serde::{Deserializer, Serializer};
387 use std::borrow::Borrow;
388
389 use crate::{
390 Schema,
391 schema::{Names, Namespace, UnionSchema},
392 };
393
394 pub fn get_schema_in_ctxt(_names: &mut Names, _enclosing_namespace: &Namespace) -> Schema {
396 Schema::Union(
397 UnionSchema::new(vec![Schema::Null, Schema::Bytes]).expect("This is a valid union"),
398 )
399 }
400
401 pub fn serialize<S, B>(bytes: &Option<B>, serializer: S) -> Result<S::Ok, S::Error>
402 where
403 S: Serializer,
404 B: Borrow<[u8]> + serde_bytes::Serialize,
405 {
406 serde_bytes::serialize(&bytes, serializer)
407 }
408
409 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<&'de [u8]>, D::Error>
410 where
411 D: Deserializer<'de>,
412 {
413 let _guard = super::BorrowedGuard::set(true);
414 serde_bytes::deserialize(deserializer)
415 }
416}
417
418#[cfg(test)]
419mod tests {
420 use crate::{Schema, from_value, to_value, types::Value};
421 use serde::{Deserialize, Serialize};
422
423 #[test]
424 fn avro_3631_validate_schema_for_struct_with_byte_types() {
425 #[derive(Debug, Serialize)]
426 struct TestStructWithBytes<'a> {
427 #[serde(with = "crate::serde::bytes")]
428 vec_field: Vec<u8>,
429 #[serde(with = "crate::serde::bytes_opt")]
430 vec_field_opt: Option<Vec<u8>>,
431
432 #[serde(with = "crate::serde::fixed")]
433 fixed_field: [u8; 6],
434 #[serde(with = "crate::serde::fixed_opt")]
435 fixed_field_opt: Option<[u8; 7]>,
436
437 #[serde(with = "crate::serde::slice")]
438 slice_field: &'a [u8],
439 #[serde(with = "crate::serde::slice_opt")]
440 slice_field_opt: Option<&'a [u8]>,
441 }
442
443 let test = TestStructWithBytes {
444 vec_field: vec![2, 3, 4],
445 vec_field_opt: Some(vec![2, 3, 4]),
446 fixed_field: [1; 6],
447 fixed_field_opt: Some([1; 7]),
448 slice_field: &[1, 2, 3],
449 slice_field_opt: Some(&[1, 2, 3]),
450 };
451 let value: Value = to_value(test).unwrap();
452 let schema = Schema::parse_str(
453 r#"
454 {
455 "type": "record",
456 "name": "TestStructWithBytes",
457 "fields": [ {
458 "name": "vec_field",
459 "type": "bytes"
460 }, {
461 "name": "vec_field_opt",
462 "type": ["null", "bytes"]
463 }, {
464 "name": "fixed_field",
465 "type": {
466 "name": "ByteData",
467 "type": "fixed",
468 "size": 6
469 }
470 }, {
471 "name": "fixed_field_opt",
472 "type": ["null", {
473 "name": "ByteData2",
474 "type": "fixed",
475 "size": 7
476 } ]
477 }, {
478 "name": "slice_field",
479 "type": "bytes"
480 }, {
481 "name": "slice_field_opt",
482 "type": ["null", "bytes"]
483 } ]
484 }"#,
485 )
486 .unwrap();
487 assert!(value.validate(&schema));
488 }
489
490 #[test]
491 fn avro_3631_deserialize_value_to_struct_with_byte_types() {
492 #[derive(Debug, Deserialize, PartialEq)]
493 struct TestStructWithBytes<'a> {
494 #[serde(with = "crate::serde::bytes")]
495 vec_field: Vec<u8>,
496 #[serde(with = "crate::serde::bytes_opt")]
497 vec_field_opt: Option<Vec<u8>>,
498 #[serde(with = "crate::serde::bytes_opt")]
499 vec_field_opt2: Option<Vec<u8>>,
500
501 #[serde(with = "crate::serde::fixed")]
502 fixed_field: [u8; 6],
503 #[serde(with = "crate::serde::fixed_opt")]
504 fixed_field_opt: Option<[u8; 7]>,
505 #[serde(with = "crate::serde::fixed_opt")]
506 fixed_field_opt2: Option<[u8; 8]>,
507
508 #[serde(with = "crate::serde::slice")]
509 slice_bytes_field: &'a [u8],
510 #[serde(with = "crate::serde::slice_opt")]
511 slice_bytes_field_opt: Option<&'a [u8]>,
512 #[serde(with = "crate::serde::slice_opt")]
513 slice_bytes_field_opt2: Option<&'a [u8]>,
514
515 #[serde(with = "crate::serde::slice")]
516 slice_fixed_field: &'a [u8],
517 #[serde(with = "crate::serde::slice_opt")]
518 slice_fixed_field_opt: Option<&'a [u8]>,
519 #[serde(with = "crate::serde::slice_opt")]
520 slice_fixed_field_opt2: Option<&'a [u8]>,
521 }
522
523 let expected = TestStructWithBytes {
524 vec_field: vec![3, 33],
525 vec_field_opt: Some(vec![4, 44]),
526 vec_field_opt2: None,
527 fixed_field: [1; 6],
528 fixed_field_opt: Some([7; 7]),
529 fixed_field_opt2: None,
530 slice_bytes_field: &[1, 11, 111],
531 slice_bytes_field_opt: Some(&[5, 5, 5, 5, 5]),
532 slice_bytes_field_opt2: None,
533 slice_fixed_field: &[2, 22, 222],
534 slice_fixed_field_opt: Some(&[3, 3, 3]),
535 slice_fixed_field_opt2: None,
536 };
537
538 let value = Value::Record(vec![
539 (
540 "vec_field".to_owned(),
541 Value::Bytes(expected.vec_field.clone()),
542 ),
543 (
544 "vec_field_opt".to_owned(),
545 Value::Union(
546 1,
547 Box::new(Value::Bytes(
548 expected.vec_field_opt.as_ref().unwrap().clone(),
549 )),
550 ),
551 ),
552 (
553 "vec_field_opt2".to_owned(),
554 Value::Union(0, Box::new(Value::Null)),
555 ),
556 (
557 "fixed_field".to_owned(),
558 Value::Fixed(expected.fixed_field.len(), expected.fixed_field.to_vec()),
559 ),
560 (
561 "fixed_field_opt".to_owned(),
562 Value::Union(
563 1,
564 Box::new(Value::Fixed(
565 expected.fixed_field_opt.as_ref().unwrap().len(),
566 expected.fixed_field_opt.as_ref().unwrap().to_vec(),
567 )),
568 ),
569 ),
570 (
571 "fixed_field_opt2".to_owned(),
572 Value::Union(0, Box::new(Value::Null)),
573 ),
574 (
575 "slice_bytes_field".to_owned(),
576 Value::Bytes(expected.slice_bytes_field.to_vec()),
577 ),
578 (
579 "slice_bytes_field_opt".to_owned(),
580 Value::Union(
581 1,
582 Box::new(Value::Bytes(
583 expected.slice_bytes_field_opt.as_ref().unwrap().to_vec(),
584 )),
585 ),
586 ),
587 (
588 "slice_bytes_field_opt2".to_owned(),
589 Value::Union(0, Box::new(Value::Null)),
590 ),
591 (
592 "slice_fixed_field".to_owned(),
593 Value::Fixed(
594 expected.slice_fixed_field.len(),
595 expected.slice_fixed_field.to_vec(),
596 ),
597 ),
598 (
599 "slice_fixed_field_opt".to_owned(),
600 Value::Union(
601 1,
602 Box::new(Value::Fixed(
603 expected.slice_fixed_field_opt.as_ref().unwrap().len(),
604 expected.slice_fixed_field_opt.as_ref().unwrap().to_vec(),
605 )),
606 ),
607 ),
608 (
609 "slice_fixed_field_opt2".to_owned(),
610 Value::Union(1, Box::new(Value::Null)),
611 ),
612 ]);
613 assert_eq!(expected, from_value(&value).unwrap());
614 }
615
616 #[test]
617 fn avro_3631_serialize_struct_to_value_with_byte_types() {
618 #[derive(Debug, Serialize)]
619 struct TestStructWithBytes<'a> {
620 array_field: &'a [u8],
621 vec_field: Vec<u8>,
622
623 #[serde(with = "crate::serde::fixed")]
624 vec_field2: Vec<u8>,
625 #[serde(with = "crate::serde::fixed_opt")]
626 vec_field2_opt: Option<Vec<u8>>,
627 #[serde(with = "crate::serde::fixed_opt")]
628 vec_field2_opt2: Option<Vec<u8>>,
629
630 #[serde(with = "crate::serde::bytes")]
631 vec_field3: Vec<u8>,
632 #[serde(with = "crate::serde::bytes_opt")]
633 vec_field3_opt: Option<Vec<u8>>,
634 #[serde(with = "crate::serde::bytes_opt")]
635 vec_field3_opt2: Option<Vec<u8>>,
636
637 #[serde(with = "crate::serde::fixed")]
638 fixed_field: [u8; 6],
639 #[serde(with = "crate::serde::fixed_opt")]
640 fixed_field_opt: Option<[u8; 5]>,
641 #[serde(with = "crate::serde::fixed_opt")]
642 fixed_field_opt2: Option<[u8; 4]>,
643
644 #[serde(with = "crate::serde::fixed")]
645 fixed_field2: &'a [u8],
646 #[serde(with = "crate::serde::fixed_opt")]
647 fixed_field2_opt: Option<&'a [u8]>,
648 #[serde(with = "crate::serde::fixed_opt")]
649 fixed_field2_opt2: Option<&'a [u8]>,
650
651 #[serde(with = "crate::serde::bytes")]
652 bytes_field: &'a [u8],
653 #[serde(with = "crate::serde::bytes_opt")]
654 bytes_field_opt: Option<&'a [u8]>,
655 #[serde(with = "crate::serde::bytes_opt")]
656 bytes_field_opt2: Option<&'a [u8]>,
657
658 #[serde(with = "crate::serde::bytes")]
659 bytes_field2: [u8; 6],
660 #[serde(with = "crate::serde::bytes_opt")]
661 bytes_field2_opt: Option<[u8; 7]>,
662 #[serde(with = "crate::serde::bytes_opt")]
663 bytes_field2_opt2: Option<[u8; 8]>,
664 }
665
666 let test = TestStructWithBytes {
667 array_field: &[1, 11, 111],
668 vec_field: vec![3, 33],
669 vec_field2: vec![4, 44],
670 vec_field2_opt: Some(vec![14, 144]),
671 vec_field2_opt2: None,
672 vec_field3: vec![5, 55],
673 vec_field3_opt: Some(vec![15, 155]),
674 vec_field3_opt2: None,
675 fixed_field: [1; 6],
676 fixed_field_opt: Some([6; 5]),
677 fixed_field_opt2: None,
678 fixed_field2: &[6, 66],
679 fixed_field2_opt: Some(&[7, 77]),
680 fixed_field2_opt2: None,
681 bytes_field: &[2, 22, 222],
682 bytes_field_opt: Some(&[3, 33, 233]),
683 bytes_field_opt2: None,
684 bytes_field2: [2; 6],
685 bytes_field2_opt: Some([2; 7]),
686 bytes_field2_opt2: None,
687 };
688 let expected = Value::Record(vec![
689 (
690 "array_field".to_owned(),
691 Value::Array(
692 test.array_field
693 .iter()
694 .map(|&i| Value::Int(i as i32))
695 .collect(),
696 ),
697 ),
698 (
699 "vec_field".to_owned(),
700 Value::Array(
701 test.vec_field
702 .iter()
703 .map(|&i| Value::Int(i as i32))
704 .collect(),
705 ),
706 ),
707 (
708 "vec_field2".to_owned(),
709 Value::Fixed(test.vec_field2.len(), test.vec_field2.clone()),
710 ),
711 (
712 "vec_field2_opt".to_owned(),
713 Value::Union(
714 1,
715 Box::new(Value::Fixed(
716 test.vec_field2_opt.as_ref().unwrap().len(),
717 test.vec_field2_opt.as_ref().unwrap().to_vec(),
718 )),
719 ),
720 ),
721 (
722 "vec_field2_opt2".to_owned(),
723 Value::Union(0, Box::new(Value::Null)),
724 ),
725 (
726 "vec_field3".to_owned(),
727 Value::Bytes(test.vec_field3.clone()),
728 ),
729 (
730 "vec_field3_opt".to_owned(),
731 Value::Union(
732 1,
733 Box::new(Value::Bytes(test.vec_field3_opt.as_ref().unwrap().clone())),
734 ),
735 ),
736 (
737 "vec_field3_opt2".to_owned(),
738 Value::Union(0, Box::new(Value::Null)),
739 ),
740 (
741 "fixed_field".to_owned(),
742 Value::Fixed(test.fixed_field.len(), test.fixed_field.to_vec()),
743 ),
744 (
745 "fixed_field_opt".to_owned(),
746 Value::Union(
747 1,
748 Box::new(Value::Fixed(
749 test.fixed_field_opt.as_ref().unwrap().len(),
750 test.fixed_field_opt.as_ref().unwrap().to_vec(),
751 )),
752 ),
753 ),
754 (
755 "fixed_field_opt2".to_owned(),
756 Value::Union(0, Box::new(Value::Null)),
757 ),
758 (
759 "fixed_field2".to_owned(),
760 Value::Fixed(test.fixed_field2.len(), test.fixed_field2.to_vec()),
761 ),
762 (
763 "fixed_field2_opt".to_owned(),
764 Value::Union(
765 1,
766 Box::new(Value::Fixed(
767 test.fixed_field2_opt.as_ref().unwrap().len(),
768 test.fixed_field2_opt.as_ref().unwrap().to_vec(),
769 )),
770 ),
771 ),
772 (
773 "fixed_field2_opt2".to_owned(),
774 Value::Union(0, Box::new(Value::Null)),
775 ),
776 (
777 "bytes_field".to_owned(),
778 Value::Bytes(test.bytes_field.to_vec()),
779 ),
780 (
781 "bytes_field_opt".to_owned(),
782 Value::Union(
783 1,
784 Box::new(Value::Bytes(
785 test.bytes_field_opt.as_ref().unwrap().to_vec(),
786 )),
787 ),
788 ),
789 (
790 "bytes_field_opt2".to_owned(),
791 Value::Union(0, Box::new(Value::Null)),
792 ),
793 (
794 "bytes_field2".to_owned(),
795 Value::Bytes(test.bytes_field2.to_vec()),
796 ),
797 (
798 "bytes_field2_opt".to_owned(),
799 Value::Union(
800 1,
801 Box::new(Value::Bytes(
802 test.bytes_field2_opt.as_ref().unwrap().to_vec(),
803 )),
804 ),
805 ),
806 (
807 "bytes_field2_opt2".to_owned(),
808 Value::Union(0, Box::new(Value::Null)),
809 ),
810 ]);
811 assert_eq!(expected, to_value(test).unwrap());
812 }
813}