1#[cfg(feature = "std")]
14use std::{
15 collections::{HashMap, HashSet},
16 hash::Hash,
17};
18use {
19 crate::{
20 containers::SliceDropGuard,
21 error::{
22 invalid_bool_encoding, invalid_char_lead, invalid_tag_encoding, invalid_utf8_encoding,
23 pointer_sized_decode_error, read_length_encoding_overflow, unaligned_pointer_read,
24 ReadResult, WriteResult,
25 },
26 io::{Reader, Writer},
27 len::{BincodeLen, SeqLen},
28 schema::{size_of_elem_slice, write_elem_slice, SchemaRead, SchemaWrite, ZeroCopy},
29 TypeMeta,
30 },
31 core::{
32 marker::PhantomData,
33 mem::{self, transmute, MaybeUninit},
34 },
35};
36#[cfg(feature = "alloc")]
37use {
38 crate::{
39 containers::{self},
40 error::WriteError,
41 schema::{size_of_elem_iter, write_elem_iter},
42 },
43 alloc::{
44 boxed::Box,
45 collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
46 rc::Rc,
47 string::String,
48 sync::Arc,
49 vec::Vec,
50 },
51};
52
53macro_rules! impl_int {
54 ($type:ty, zero_copy: $zero_copy:expr) => {
55 impl SchemaWrite for $type {
56 type Src = $type;
57
58 const TYPE_META: TypeMeta = TypeMeta::Static {
59 size: size_of::<$type>(),
60 #[cfg(target_endian = "little")]
61 zero_copy: true,
62 #[cfg(not(target_endian = "little"))]
63 zero_copy: $zero_copy,
64 };
65
66 #[inline(always)]
67 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
68 Ok(size_of::<$type>())
69 }
70
71 #[inline(always)]
72 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
73 Ok(writer.write(&src.to_le_bytes())?)
74 }
75 }
76
77 impl<'de> SchemaRead<'de> for $type {
78 type Dst = $type;
79
80 const TYPE_META: TypeMeta = TypeMeta::Static {
81 size: size_of::<$type>(),
82 #[cfg(target_endian = "little")]
83 zero_copy: true,
84 #[cfg(not(target_endian = "little"))]
85 zero_copy: $zero_copy,
86 };
87
88 #[inline(always)]
89 fn read(
90 reader: &mut impl Reader<'de>,
91 dst: &mut MaybeUninit<Self::Dst>,
92 ) -> ReadResult<()> {
93 let bytes = reader.fill_array::<{ size_of::<$type>() }>()?;
95 dst.write(<$type>::from_le_bytes(*bytes));
97 unsafe { reader.consume_unchecked(size_of::<$type>()) };
98
99 Ok(())
100 }
101 }
102 };
103
104 ($type:ty as $cast:ty) => {
105 impl SchemaWrite for $type {
106 type Src = $type;
107
108 const TYPE_META: TypeMeta = TypeMeta::Static {
109 size: size_of::<$cast>(),
110 zero_copy: false,
111 };
112
113 #[inline]
114 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
115 Ok(size_of::<$cast>())
116 }
117
118 #[inline]
119 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
120 let src = *src as $cast;
121 Ok(writer.write(&src.to_le_bytes())?)
124 }
125 }
126
127 impl<'de> SchemaRead<'de> for $type {
128 type Dst = $type;
129
130 const TYPE_META: TypeMeta = TypeMeta::Static {
131 size: size_of::<$cast>(),
132 zero_copy: false,
133 };
134
135 #[inline]
136 fn read(
137 reader: &mut impl Reader<'de>,
138 dst: &mut MaybeUninit<Self::Dst>,
139 ) -> ReadResult<()> {
140 let casted = <$cast>::get(reader)?;
141 let val = casted
142 .try_into()
143 .map_err(|_| pointer_sized_decode_error())?;
144
145 dst.write(val);
146
147 Ok(())
148 }
149 }
150 };
151}
152
153unsafe impl ZeroCopy for u8 {}
156
157unsafe impl ZeroCopy for i8 {}
160
161macro_rules! impl_numeric_zero_copy {
162 ($($ty:ty),+ $(,)?) => {
163 $(
164 unsafe impl ZeroCopy for $ty {}
165 )+
166 };
167}
168
169#[cfg(target_endian = "little")]
172impl_numeric_zero_copy!(u16, i16, u32, i32, u64, i64, u128, i128, f32, f64);
173
174impl_int!(u8, zero_copy: true);
175impl_int!(i8, zero_copy: true);
176impl_int!(u16, zero_copy: false);
177impl_int!(i16, zero_copy: false);
178impl_int!(u32, zero_copy: false);
179impl_int!(i32, zero_copy: false);
180impl_int!(u64, zero_copy: false);
181impl_int!(i64, zero_copy: false);
182impl_int!(u128, zero_copy: false);
183impl_int!(i128, zero_copy: false);
184impl_int!(f32, zero_copy: false);
185impl_int!(f64, zero_copy: false);
186impl_int!(usize as u64);
187impl_int!(isize as i64);
188
189impl SchemaWrite for bool {
190 type Src = bool;
191
192 const TYPE_META: TypeMeta = TypeMeta::Static {
193 size: size_of::<bool>(),
194 zero_copy: false,
195 };
196
197 #[inline]
198 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
199 Ok(size_of::<u8>())
200 }
201
202 #[inline]
203 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
204 unsafe { Ok(writer.write_t(&(*src as u8))?) }
205 }
206}
207
208impl<'de> SchemaRead<'de> for bool {
209 type Dst = bool;
210
211 const TYPE_META: TypeMeta = TypeMeta::Static {
212 size: size_of::<bool>(),
213 zero_copy: false,
214 };
215
216 #[inline]
217 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
218 let byte = u8::get(reader)?;
220 match byte {
221 0 => {
222 dst.write(false);
223 }
224 1 => {
225 dst.write(true);
226 }
227 _ => return Err(invalid_bool_encoding(byte)),
228 }
229 Ok(())
230 }
231}
232
233impl SchemaWrite for char {
234 type Src = char;
235
236 #[inline]
237 fn size_of(src: &Self::Src) -> WriteResult<usize> {
238 let mut buf = [0; 4];
239 let str = src.encode_utf8(&mut buf);
240 Ok(str.len())
241 }
242
243 #[inline]
244 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
245 let mut buf = [0; 4];
246 let str = src.encode_utf8(&mut buf);
247 writer.write(str.as_bytes())?;
248 Ok(())
249 }
250}
251
252impl<'de> SchemaRead<'de> for char {
253 type Dst = char;
254
255 #[inline]
256 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
257 let b0 = *reader.peek()?;
258
259 let len = match b0 {
260 0x00..=0x7F => 1,
261 0xC2..=0xDF => 2,
262 0xE0..=0xEF => 3,
263 0xF0..=0xF4 => 4,
264 _ => return Err(invalid_char_lead(b0)),
265 };
266
267 if len == 1 {
268 unsafe { reader.consume_unchecked(1) };
269 dst.write(b0 as char);
270 return Ok(());
271 }
272
273 let buf = reader.fill_exact(len)?;
274 let str = core::str::from_utf8(buf).map_err(invalid_utf8_encoding)?;
279 let c = str.chars().next().unwrap();
280 unsafe { reader.consume_unchecked(len) };
281 dst.write(c);
282 Ok(())
283 }
284}
285
286impl<T> SchemaWrite for PhantomData<T> {
287 type Src = PhantomData<T>;
288
289 const TYPE_META: TypeMeta = TypeMeta::Static {
290 size: 0,
291 zero_copy: true,
292 };
293
294 #[inline]
295 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
296 Ok(0)
297 }
298
299 #[inline]
300 fn write(_writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
301 Ok(())
302 }
303}
304
305impl<'de, T> SchemaRead<'de> for PhantomData<T> {
306 type Dst = PhantomData<T>;
307
308 const TYPE_META: TypeMeta = TypeMeta::Static {
309 size: 0,
310 zero_copy: true,
311 };
312
313 #[inline]
314 fn read(_reader: &mut impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
315 Ok(())
316 }
317}
318
319impl SchemaWrite for () {
320 type Src = ();
321
322 const TYPE_META: TypeMeta = TypeMeta::Static {
323 size: 0,
324 zero_copy: true,
325 };
326
327 #[inline]
328 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
329 Ok(0)
330 }
331
332 #[inline]
333 fn write(_writer: &mut impl Writer, _src: &Self::Src) -> WriteResult<()> {
334 Ok(())
335 }
336}
337
338impl<'de> SchemaRead<'de> for () {
339 type Dst = ();
340
341 const TYPE_META: TypeMeta = TypeMeta::Static {
342 size: 0,
343 zero_copy: true,
344 };
345
346 #[inline]
347 fn read(_reader: &mut impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
348 Ok(())
349 }
350}
351
352#[cfg(feature = "alloc")]
353impl<T> SchemaWrite for Vec<T>
354where
355 T: SchemaWrite,
356 T::Src: Sized,
357{
358 type Src = Vec<T::Src>;
359
360 #[inline]
361 fn size_of(value: &Self::Src) -> WriteResult<usize> {
362 <containers::Vec<T, BincodeLen<{ 1 << 27 }>>>::size_of(value)
363 }
364
365 #[inline]
366 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
367 <containers::Vec<T, BincodeLen<{ 1 << 27 }>>>::write(writer, value)
368 }
369}
370
371#[cfg(feature = "alloc")]
372impl<'de, T> SchemaRead<'de> for Vec<T>
373where
374 T: SchemaRead<'de>,
375{
376 type Dst = Vec<T::Dst>;
377
378 #[inline]
379 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
380 <containers::Vec<T, BincodeLen<{ 1 << 27 }>>>::read(reader, dst)
381 }
382}
383
384#[cfg(feature = "alloc")]
385impl<T> SchemaWrite for VecDeque<T>
386where
387 T: SchemaWrite,
388 T::Src: Sized,
389{
390 type Src = VecDeque<T::Src>;
391
392 #[inline]
393 fn size_of(value: &Self::Src) -> WriteResult<usize> {
394 <containers::VecDeque<T, BincodeLen>>::size_of(value)
395 }
396
397 #[inline]
398 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
399 <containers::VecDeque<T, BincodeLen>>::write(writer, value)
400 }
401}
402
403#[cfg(feature = "alloc")]
404impl<'de, T> SchemaRead<'de> for VecDeque<T>
405where
406 T: SchemaRead<'de>,
407{
408 type Dst = VecDeque<T::Dst>;
409
410 #[inline]
411 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
412 <containers::VecDeque<T, BincodeLen>>::read(reader, dst)
413 }
414}
415
416impl<T> SchemaWrite for [T]
417where
418 T: SchemaWrite,
419 T::Src: Sized,
420{
421 type Src = [T::Src];
422
423 #[inline]
424 fn size_of(value: &Self::Src) -> WriteResult<usize> {
425 size_of_elem_slice::<T, BincodeLen>(value)
426 }
427
428 #[inline]
429 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
430 write_elem_slice::<T, BincodeLen>(writer, value)
431 }
432}
433
434unsafe impl<const N: usize, T> ZeroCopy for [T; N] where T: ZeroCopy {}
438
439impl<'de, T, const N: usize> SchemaRead<'de> for [T; N]
440where
441 T: SchemaRead<'de>,
442{
443 type Dst = [T::Dst; N];
444
445 const TYPE_META: TypeMeta = const {
446 match T::TYPE_META {
447 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
448 size: N * size,
449 zero_copy,
450 },
451 TypeMeta::Dynamic => TypeMeta::Dynamic,
452 }
453 };
454
455 #[inline]
456 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
457 if let TypeMeta::Static {
458 zero_copy: true, ..
459 } = T::TYPE_META
460 {
461 unsafe { reader.copy_into_t(dst)? };
463 return Ok(());
464 }
465
466 let dst =
468 unsafe { transmute::<&mut MaybeUninit<Self::Dst>, &mut [MaybeUninit<T::Dst>; N]>(dst) };
469 let base = dst.as_mut_ptr();
470 let mut guard = SliceDropGuard::<T::Dst>::new(base);
471 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
472 let reader = &mut unsafe { reader.as_trusted_for(size) }?;
475 for i in 0..N {
476 let slot = unsafe { &mut *base.add(i) };
477 T::read(reader, slot)?;
478 guard.inc_len();
479 }
480 } else {
481 for i in 0..N {
482 let slot = unsafe { &mut *base.add(i) };
483 T::read(reader, slot)?;
484 guard.inc_len();
485 }
486 }
487 mem::forget(guard);
488 Ok(())
489 }
490}
491
492impl<T, const N: usize> SchemaWrite for [T; N]
493where
494 T: SchemaWrite,
495 T::Src: Sized,
496{
497 type Src = [T::Src; N];
498
499 const TYPE_META: TypeMeta = const {
500 match T::TYPE_META {
501 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
502 size: N * size,
503 zero_copy,
504 },
505 TypeMeta::Dynamic => TypeMeta::Dynamic,
506 }
507 };
508
509 #[inline]
510 #[allow(clippy::arithmetic_side_effects)]
511 fn size_of(value: &Self::Src) -> WriteResult<usize> {
512 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
513 return Ok(size);
514 }
515 value
517 .iter()
518 .map(T::size_of)
519 .try_fold(0usize, |acc, x| x.map(|x| acc + x))
520 }
521
522 #[inline]
523 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
524 match Self::TYPE_META {
525 TypeMeta::Static {
526 zero_copy: true, ..
527 } => {
528 unsafe { writer.write_slice_t(value)? };
530 }
531 TypeMeta::Static {
532 size,
533 zero_copy: false,
534 } => {
535 let writer = &mut unsafe { writer.as_trusted_for(size) }?;
538 for item in value {
539 T::write(writer, item)?;
540 }
541 writer.finish()?;
542 }
543 TypeMeta::Dynamic => {
544 for item in value {
545 T::write(writer, item)?;
546 }
547 }
548 }
549
550 Ok(())
551 }
552}
553
554impl<'de, T> SchemaRead<'de> for Option<T>
555where
556 T: SchemaRead<'de>,
557{
558 type Dst = Option<T::Dst>;
559
560 #[inline]
561 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
562 let variant = u8::get(reader)?;
563 match variant {
564 0 => dst.write(Option::None),
565 1 => dst.write(Option::Some(T::get(reader)?)),
566 _ => return Err(invalid_tag_encoding(variant as usize)),
567 };
568
569 Ok(())
570 }
571}
572
573impl<T> SchemaWrite for Option<T>
574where
575 T: SchemaWrite,
576 T::Src: Sized,
577{
578 type Src = Option<T::Src>;
579
580 #[inline]
581 #[allow(clippy::arithmetic_side_effects)]
582 fn size_of(src: &Self::Src) -> WriteResult<usize> {
583 match src {
584 Option::Some(value) => Ok(1 + T::size_of(value)?),
586 Option::None => Ok(1),
587 }
588 }
589
590 #[inline]
591 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
592 match value {
593 Option::Some(value) => {
594 u8::write(writer, &1)?;
595 T::write(writer, value)
596 }
597 Option::None => u8::write(writer, &0),
598 }
599 }
600}
601
602impl<'de, T, E> SchemaRead<'de> for Result<T, E>
603where
604 T: SchemaRead<'de>,
605 E: SchemaRead<'de>,
606{
607 type Dst = Result<T::Dst, E::Dst>;
608
609 const TYPE_META: TypeMeta = match (T::TYPE_META, E::TYPE_META) {
610 (TypeMeta::Static { size: t_size, .. }, TypeMeta::Static { size: e_size, .. })
611 if t_size == e_size =>
612 {
613 TypeMeta::Static {
614 size: size_of::<u32>() + t_size,
615 zero_copy: false,
616 }
617 }
618 _ => TypeMeta::Dynamic,
619 };
620
621 #[inline]
622 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
623 let variant = u32::get(reader)?;
624 match variant {
625 0 => dst.write(Result::Ok(T::get(reader)?)),
626 1 => dst.write(Result::Err(E::get(reader)?)),
627 _ => return Err(invalid_tag_encoding(variant as usize)),
628 };
629
630 Ok(())
631 }
632}
633
634impl<T, E> SchemaWrite for Result<T, E>
635where
636 T: SchemaWrite,
637 E: SchemaWrite,
638 T::Src: Sized,
639 E::Src: Sized,
640{
641 type Src = Result<T::Src, E::Src>;
642
643 const TYPE_META: TypeMeta = match (T::TYPE_META, E::TYPE_META) {
644 (TypeMeta::Static { size: t_size, .. }, TypeMeta::Static { size: e_size, .. })
645 if t_size == e_size =>
646 {
647 TypeMeta::Static {
648 size: size_of::<u32>() + t_size,
649 zero_copy: false,
650 }
651 }
652 _ => TypeMeta::Dynamic,
653 };
654
655 #[inline]
656 #[allow(clippy::arithmetic_side_effects)]
657 fn size_of(src: &Self::Src) -> WriteResult<usize> {
658 match src {
659 Result::Ok(value) => Ok(size_of::<u32>() + T::size_of(value)?),
661 Result::Err(error) => Ok(size_of::<u32>() + E::size_of(error)?),
662 }
663 }
664
665 #[inline]
666 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
667 match value {
668 Result::Ok(value) => {
669 u32::write(writer, &0)?;
670 T::write(writer, value)
671 }
672 Result::Err(error) => {
673 u32::write(writer, &1)?;
674 E::write(writer, error)
675 }
676 }
677 }
678}
679
680impl<'a, T> SchemaWrite for &'a T
681where
682 T: SchemaWrite,
683 T: ?Sized,
684{
685 type Src = &'a T::Src;
686
687 const TYPE_META: TypeMeta = T::TYPE_META;
688
689 #[inline]
690 fn size_of(src: &Self::Src) -> WriteResult<usize> {
691 T::size_of(*src)
692 }
693
694 #[inline]
695 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
696 T::write(writer, *value)
697 }
698}
699
700macro_rules! impl_heap_container {
701 ($container:ident) => {
702 #[cfg(feature = "alloc")]
703 impl<T> SchemaWrite for $container<T>
704 where
705 T: SchemaWrite,
706 {
707 type Src = $container<T::Src>;
708
709 const TYPE_META: TypeMeta = const {
710 match T::TYPE_META {
711 TypeMeta::Static { size, .. } => TypeMeta::Static {
712 size,
713 zero_copy: false,
714 },
715 TypeMeta::Dynamic => TypeMeta::Dynamic,
716 }
717 };
718
719 #[inline]
720 fn size_of(src: &Self::Src) -> WriteResult<usize> {
721 T::size_of(src)
722 }
723
724 #[inline]
725 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
726 T::write(writer, value)
727 }
728 }
729
730 #[cfg(feature = "alloc")]
731 impl<'de, T> SchemaRead<'de> for $container<T>
732 where
733 T: SchemaRead<'de>,
734 {
735 type Dst = $container<T::Dst>;
736
737 const TYPE_META: TypeMeta = const {
738 match T::TYPE_META {
739 TypeMeta::Static { size, .. } => TypeMeta::Static {
740 size,
741 zero_copy: false,
742 },
743 TypeMeta::Dynamic => TypeMeta::Dynamic,
744 }
745 };
746
747 #[inline]
748 fn read(
749 reader: &mut impl Reader<'de>,
750 dst: &mut MaybeUninit<Self::Dst>,
751 ) -> ReadResult<()> {
752 struct DropGuard<T>(*mut MaybeUninit<T>);
753 impl<T> Drop for DropGuard<T> {
754 #[inline]
755 fn drop(&mut self) {
756 drop(unsafe { $container::from_raw(self.0) });
757 }
758 }
759
760 let mem = $container::<T::Dst>::new_uninit();
761 let ptr = $container::into_raw(mem) as *mut _;
762 let guard: DropGuard<T::Dst> = DropGuard(ptr);
763 T::read(reader, unsafe { &mut *ptr })?;
764
765 mem::forget(guard);
766
767 unsafe {
768 dst.write($container::from_raw(ptr).assume_init());
770 }
771 Ok(())
772 }
773 }
774 };
775}
776
777impl_heap_container!(Box);
778impl_heap_container!(Rc);
779impl_heap_container!(Arc);
780
781#[cfg(feature = "alloc")]
782impl<T> SchemaWrite for Box<[T]>
783where
784 T: SchemaWrite,
785 T::Src: Sized,
786{
787 type Src = Box<[T::Src]>;
788
789 #[inline]
790 fn size_of(src: &Self::Src) -> WriteResult<usize> {
791 <containers::Box<[T], BincodeLen>>::size_of(src)
792 }
793
794 #[inline]
795 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
796 <containers::Box<[T], BincodeLen>>::write(writer, value)
797 }
798}
799
800#[cfg(feature = "alloc")]
801impl<T> SchemaWrite for Rc<[T]>
802where
803 T: SchemaWrite,
804 T::Src: Sized,
805{
806 type Src = Rc<[T::Src]>;
807
808 #[inline]
809 fn size_of(src: &Self::Src) -> WriteResult<usize> {
810 <containers::Rc<[T], BincodeLen>>::size_of(src)
811 }
812
813 #[inline]
814 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
815 <containers::Rc<[T], BincodeLen>>::write(writer, value)
816 }
817}
818
819#[cfg(feature = "alloc")]
820impl<T> SchemaWrite for Arc<[T]>
821where
822 T: SchemaWrite,
823 T::Src: Sized,
824{
825 type Src = Arc<[T::Src]>;
826
827 #[inline]
828 fn size_of(src: &Self::Src) -> WriteResult<usize> {
829 <containers::Arc<[T], BincodeLen>>::size_of(src)
830 }
831
832 #[inline]
833 fn write(writer: &mut impl Writer, value: &Self::Src) -> WriteResult<()> {
834 <containers::Arc<[T], BincodeLen>>::write(writer, value)
835 }
836}
837
838#[cfg(feature = "alloc")]
839impl<'de, T> SchemaRead<'de> for Box<[T]>
840where
841 T: SchemaRead<'de>,
842{
843 type Dst = Box<[T::Dst]>;
844
845 #[inline]
846 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
847 <containers::Box<[T], BincodeLen>>::read(reader, dst)
848 }
849}
850
851#[cfg(feature = "alloc")]
852impl<'de, T> SchemaRead<'de> for Rc<[T]>
853where
854 T: SchemaRead<'de>,
855{
856 type Dst = Rc<[T::Dst]>;
857
858 #[inline]
859 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
860 <containers::Rc<[T], BincodeLen>>::read(reader, dst)
861 }
862}
863
864#[cfg(feature = "alloc")]
865impl<'de, T> SchemaRead<'de> for Arc<[T]>
866where
867 T: SchemaRead<'de>,
868{
869 type Dst = Arc<[T::Dst]>;
870
871 #[inline]
872 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
873 <containers::Arc<[T], BincodeLen>>::read(reader, dst)
874 }
875}
876
877impl SchemaWrite for str {
878 type Src = str;
879
880 #[inline]
881 #[allow(clippy::arithmetic_side_effects)]
882 fn size_of(src: &Self::Src) -> WriteResult<usize> {
883 Ok(<BincodeLen>::write_bytes_needed(src.len())? + src.len())
885 }
886
887 #[inline]
888 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
889 <BincodeLen>::write(writer, src.len())?;
890 writer.write(src.as_bytes())?;
891 Ok(())
892 }
893}
894
895#[cfg(feature = "alloc")]
896impl SchemaWrite for String {
897 type Src = String;
898
899 #[inline]
900 fn size_of(src: &Self::Src) -> WriteResult<usize> {
901 <str>::size_of(src)
902 }
903
904 #[inline]
905 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
906 <str>::write(writer, src)
907 }
908}
909
910impl<'de> SchemaRead<'de> for &'de str {
911 type Dst = &'de str;
912
913 #[inline]
914 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
915 let len = <BincodeLen>::read::<u8>(reader)?;
916 let bytes = reader.borrow_exact(len)?;
917 match core::str::from_utf8(bytes) {
918 Ok(s) => {
919 dst.write(s);
920 Ok(())
921 }
922 Err(e) => Err(invalid_utf8_encoding(e)),
923 }
924 }
925}
926
927#[cfg(feature = "alloc")]
928impl<'de> SchemaRead<'de> for String {
929 type Dst = String;
930
931 #[inline]
932 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
933 let len = <BincodeLen>::read::<u8>(reader)?;
934 let bytes = reader.fill_exact(len)?.to_vec();
935 unsafe { reader.consume_unchecked(len) };
936 match String::from_utf8(bytes) {
937 Ok(s) => {
938 dst.write(s);
939 Ok(())
940 }
941 Err(e) => Err(invalid_utf8_encoding(e.utf8_error())),
942 }
943 }
944}
945
946#[cfg(feature = "bytes")]
947impl SchemaWrite for bytes::Bytes {
948 type Src = bytes::Bytes;
949
950 #[inline]
951 fn size_of(src: &Self::Src) -> WriteResult<usize> {
952 <containers::Bytes<BincodeLen>>::size_of(src)
953 }
954
955 #[inline]
956 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
957 <containers::Bytes<BincodeLen>>::write(writer, src)
958 }
959}
960
961#[cfg(feature = "bytes")]
962impl<'de> SchemaRead<'de> for bytes::Bytes {
963 type Dst = bytes::Bytes;
964
965 #[inline]
966 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
967 <containers::Bytes<BincodeLen>>::read(reader, dst)
968 }
969}
970
971#[cfg(feature = "bytes")]
972impl SchemaWrite for bytes::BytesMut {
973 type Src = bytes::BytesMut;
974
975 #[inline]
976 fn size_of(src: &Self::Src) -> WriteResult<usize> {
977 <containers::BytesMut<BincodeLen>>::size_of(src)
978 }
979
980 #[inline]
981 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
982 <containers::BytesMut<BincodeLen>>::write(writer, src)
983 }
984}
985
986#[cfg(feature = "bytes")]
987impl<'de> SchemaRead<'de> for bytes::BytesMut {
988 type Dst = bytes::BytesMut;
989
990 #[inline]
991 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
992 <containers::BytesMut<BincodeLen>>::read(reader, dst)
993 }
994}
995
996macro_rules! impl_seq {
1002 ($feature: literal, $target: ident<$key: ident : $($constraint:path)|*, $value: ident>, $with_capacity: expr) => {
1003 #[cfg(feature = $feature)]
1004 impl<$key, $value> SchemaWrite for $target<$key, $value>
1005 where
1006 $key: SchemaWrite,
1007 $key::Src: Sized,
1008 $value: SchemaWrite,
1009 $value::Src: Sized,
1010 {
1011 type Src = $target<$key::Src, $value::Src>;
1012
1013 #[inline]
1014 #[allow(clippy::arithmetic_side_effects)]
1015 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1016 if let (TypeMeta::Static { size: key_size, .. }, TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1017 return Ok(<BincodeLen>::write_bytes_needed(src.len())? + (key_size + value_size) * src.len());
1018 }
1019 Ok(<BincodeLen>::write_bytes_needed(src.len())? +
1020 src
1021 .iter()
1022 .try_fold(
1023 0usize,
1024 |acc, (k, v)|
1025 Ok::<_, WriteError>(
1026 acc
1027 + $key::size_of(k)?
1028 + $value::size_of(v)?
1029 )
1030 )?
1031 )
1032 }
1033
1034 #[inline]
1035 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
1036 if let (TypeMeta::Static { size: key_size, .. }, TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1037 let len = src.len();
1038 #[allow(clippy::arithmetic_side_effects)]
1039 let needed = <BincodeLen>::write_bytes_needed(len)? + (key_size + value_size) * len;
1040 let writer = &mut unsafe { writer.as_trusted_for(needed) }?;
1043 <BincodeLen>::write(writer, len)?;
1044 for (k, v) in src.iter() {
1045 $key::write(writer, k)?;
1046 $value::write(writer, v)?;
1047 }
1048 writer.finish()?;
1049 return Ok(());
1050 }
1051 <BincodeLen>::write(writer, src.len())?;
1052 for (k, v) in src.iter() {
1053 $key::write(writer, k)?;
1054 $value::write(writer, v)?;
1055 }
1056 Ok(())
1057 }
1058 }
1059
1060 #[cfg(feature = $feature)]
1061 impl<'de, $key, $value> SchemaRead<'de> for $target<$key, $value>
1062 where
1063 $key: SchemaRead<'de>,
1064 $value: SchemaRead<'de>
1065 $(,$key::Dst: $constraint+)*,
1066 {
1067 type Dst = $target<$key::Dst, $value::Dst>;
1068
1069 #[inline]
1070 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1071 let len = <BincodeLen>::read::<($key::Dst, $value::Dst)>(reader)?;
1072
1073 let map = if let (TypeMeta::Static { size: key_size, .. }, TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1074 #[allow(clippy::arithmetic_side_effects)]
1075 let reader = &mut unsafe { reader.as_trusted_for((key_size + value_size) * len) }?;
1078 let mut map = $with_capacity(len);
1079 for _ in 0..len {
1080 let k = $key::get(reader)?;
1081 let v = $value::get(reader)?;
1082 map.insert(k, v);
1083 }
1084 map
1085 } else {
1086 let mut map = $with_capacity(len);
1087 for _ in 0..len {
1088 let k = $key::get(reader)?;
1089 let v = $value::get(reader)?;
1090 map.insert(k, v);
1091 }
1092 map
1093 };
1094
1095 dst.write(map);
1096 Ok(())
1097 }
1098 }
1099 };
1100
1101 ($feature: literal, $target: ident <$key: ident : $($constraint:path)|*>, $with_capacity: expr, $insert: ident) => {
1102 #[cfg(feature = $feature)]
1103 impl<$key: SchemaWrite> SchemaWrite for $target<$key>
1104 where
1105 $key::Src: Sized,
1106 {
1107 type Src = $target<$key::Src>;
1108
1109 #[inline]
1110 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1111 size_of_elem_iter::<$key, BincodeLen>(src.iter())
1112 }
1113
1114 #[inline]
1115 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
1116 write_elem_iter::<$key, BincodeLen>(writer, src.iter())
1117 }
1118 }
1119
1120 #[cfg(feature = $feature)]
1121 impl<'de, $key> SchemaRead<'de> for $target<$key>
1122 where
1123 $key: SchemaRead<'de>
1124 $(,$key::Dst: $constraint+)*,
1125 {
1126 type Dst = $target<$key::Dst>;
1127
1128 #[inline]
1129 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1130 let len = <BincodeLen>::read::<$key::Dst>(reader)?;
1131
1132 let map = match $key::TYPE_META {
1133 TypeMeta::Static { size, .. } => {
1134 #[allow(clippy::arithmetic_side_effects)]
1135 let reader = &mut unsafe { reader.as_trusted_for(size * len) }?;
1138 let mut set = $with_capacity(len);
1139 for _ in 0..len {
1140 set.$insert($key::get(reader)?);
1141 }
1142 set
1143 }
1144 TypeMeta::Dynamic => {
1145 let mut set = $with_capacity(len);
1146 for _ in 0..len {
1147 set.$insert($key::get(reader)?);
1148 }
1149 set
1150 }
1151 };
1152
1153 dst.write(map);
1154 Ok(())
1155 }
1156 }
1157 };
1158}
1159
1160impl_seq! { "alloc", BTreeMap<K: Ord, V>, |_| BTreeMap::new() }
1161impl_seq! { "std", HashMap<K: Hash | Eq, V>, HashMap::with_capacity }
1162impl_seq! { "alloc", BTreeSet<K: Ord>, |_| BTreeSet::new(), insert }
1163impl_seq! { "std", HashSet<K: Hash | Eq>, HashSet::with_capacity, insert }
1164impl_seq! { "alloc", LinkedList<K:>, |_| LinkedList::new(), push_back }
1165
1166#[cfg(feature = "alloc")]
1167impl<T> SchemaWrite for BinaryHeap<T>
1168where
1169 T: SchemaWrite,
1170 T::Src: Sized,
1171{
1172 type Src = BinaryHeap<T::Src>;
1173
1174 #[inline]
1175 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1176 <containers::BinaryHeap<T, BincodeLen>>::size_of(src)
1177 }
1178
1179 #[inline]
1180 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
1181 <containers::BinaryHeap<T, BincodeLen>>::write(writer, src)
1182 }
1183}
1184
1185#[cfg(feature = "alloc")]
1186impl<'de, T> SchemaRead<'de> for BinaryHeap<T>
1187where
1188 T: SchemaRead<'de>,
1189 T::Dst: Ord,
1190{
1191 type Dst = BinaryHeap<T::Dst>;
1192
1193 #[inline]
1194 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1195 <containers::BinaryHeap<T, BincodeLen>>::read(reader, dst)
1196 }
1197}
1198
1199mod zero_copy {
1200 use {
1201 super::*,
1202 core::slice::{from_raw_parts, from_raw_parts_mut},
1203 };
1204
1205 #[inline(always)]
1216 fn cast_ensure_aligned<T, U>(ptr: *const T) -> ReadResult<*const U> {
1217 let ptr = ptr.cast::<U>();
1218 if align_of::<U>() > 1 && !ptr.is_aligned() {
1219 return Err(unaligned_pointer_read());
1220 }
1221 Ok(ptr)
1222 }
1223
1224 #[inline(always)]
1229 fn cast_ensure_aligned_mut<T, U>(ptr: *mut T) -> ReadResult<*mut U> {
1230 let ptr = ptr.cast::<U>();
1231 if align_of::<U>() > 1 && !ptr.is_aligned() {
1232 return Err(unaligned_pointer_read());
1233 }
1234 Ok(ptr)
1235 }
1236
1237 #[inline(always)]
1250 pub(super) unsafe fn cast_slice_to_t<T>(bytes: &[u8]) -> ReadResult<&T> {
1251 debug_assert_eq!(bytes.len(), size_of::<T>());
1252 let ptr = cast_ensure_aligned::<u8, T>(bytes.as_ptr())?;
1253 let val = unsafe { &*ptr };
1257 Ok(val)
1258 }
1259
1260 #[inline(always)]
1264 pub(super) unsafe fn cast_slice_to_t_mut<T>(bytes: &mut [u8]) -> ReadResult<&mut T> {
1265 debug_assert_eq!(bytes.len(), size_of::<T>());
1266 let ptr = cast_ensure_aligned_mut::<u8, T>(bytes.as_mut_ptr())?;
1267 let val = unsafe { &mut *ptr };
1271 Ok(val)
1272 }
1273
1274 #[inline(always)]
1287 pub(super) unsafe fn cast_slice_to_slice_t<T>(bytes: &[u8], len: usize) -> ReadResult<&[T]> {
1288 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1289 let ptr = cast_ensure_aligned::<u8, T>(bytes.as_ptr())?;
1290 let slice = unsafe { from_raw_parts(ptr, len) };
1294 Ok(slice)
1295 }
1296
1297 #[inline(always)]
1301 pub(super) unsafe fn cast_slice_to_slice_t_mut<T>(
1302 bytes: &mut [u8],
1303 len: usize,
1304 ) -> ReadResult<&mut [T]> {
1305 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1306 let ptr = cast_ensure_aligned_mut::<u8, T>(bytes.as_mut_ptr())?;
1307 let slice = unsafe { from_raw_parts_mut(ptr, len) };
1311 Ok(slice)
1312 }
1313
1314 pub(super) const fn type_meta_t<'de, T>() -> TypeMeta
1316 where
1317 T: SchemaRead<'de> + ZeroCopy,
1318 {
1319 match T::TYPE_META {
1320 TypeMeta::Static {
1321 size,
1322 zero_copy: true,
1323 } => TypeMeta::Static {
1324 size,
1325 zero_copy: false,
1342 },
1343 _ => panic!("Type is not zero-copy"),
1345 }
1346 }
1347
1348 pub(super) const fn type_meta_slice<'de, T>() -> TypeMeta
1354 where
1355 T: SchemaRead<'de> + ZeroCopy,
1356 {
1357 match T::TYPE_META {
1358 TypeMeta::Static {
1359 zero_copy: true, ..
1360 } => TypeMeta::Dynamic,
1361 _ => panic!("Type is not zero-copy"),
1362 }
1363 }
1364
1365 #[inline(always)]
1371 pub(super) fn read_slice_len_checked<'de>(
1372 reader: &mut impl Reader<'de>,
1373 size: usize,
1374 ) -> ReadResult<(usize, usize)> {
1375 let Ok(len): Result<usize, _> = u64::get(reader)?.try_into() else {
1376 return Err(pointer_sized_decode_error());
1377 };
1378 let Some(total_size) = len.checked_mul(size) else {
1379 return Err(read_length_encoding_overflow("usize::MAX"));
1380 };
1381 Ok((len, total_size))
1382 }
1383}
1384
1385impl<'de, T> SchemaRead<'de> for &'de T
1386where
1387 T: SchemaRead<'de> + ZeroCopy,
1388{
1389 type Dst = &'de T::Dst;
1390
1391 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T>();
1392
1393 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1394 let size = T::TYPE_META.size_assert_zero_copy();
1395 let bytes = reader.borrow_exact(size)?;
1396 let val = unsafe { zero_copy::cast_slice_to_t::<T::Dst>(bytes)? };
1400 dst.write(val);
1401 Ok(())
1402 }
1403}
1404
1405impl<'de, T> SchemaRead<'de> for &'de mut T
1406where
1407 T: SchemaRead<'de> + ZeroCopy,
1408{
1409 type Dst = &'de mut T::Dst;
1410
1411 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T>();
1412
1413 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1414 let size = T::TYPE_META.size_assert_zero_copy();
1415 let bytes = reader.borrow_exact_mut(size)?;
1416 let val = unsafe { zero_copy::cast_slice_to_t_mut::<T::Dst>(bytes)? };
1420 dst.write(val);
1421 Ok(())
1422 }
1423}
1424
1425impl<'de, T> SchemaRead<'de> for &'de [T]
1426where
1427 T: SchemaRead<'de> + ZeroCopy,
1428{
1429 type Dst = &'de [T::Dst];
1430
1431 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T>();
1432
1433 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1434 let size = T::TYPE_META.size_assert_zero_copy();
1435 let (len, total_size) = zero_copy::read_slice_len_checked(reader, size)?;
1436 let bytes = reader.borrow_exact(total_size)?;
1437 let slice = unsafe { zero_copy::cast_slice_to_slice_t::<T::Dst>(bytes, len)? };
1441 dst.write(slice);
1442 Ok(())
1443 }
1444}
1445
1446impl<'de, T> SchemaRead<'de> for &'de mut [T]
1447where
1448 T: SchemaRead<'de> + ZeroCopy,
1449{
1450 type Dst = &'de mut [T::Dst];
1451
1452 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T>();
1453
1454 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1455 let size = T::TYPE_META.size_assert_zero_copy();
1456 let (len, total_size) = zero_copy::read_slice_len_checked(reader, size)?;
1457 let bytes = reader.borrow_exact_mut(total_size)?;
1458 let slice = unsafe { zero_copy::cast_slice_to_slice_t_mut::<T::Dst>(bytes, len)? };
1462 dst.write(slice);
1463 Ok(())
1464 }
1465}