1#[cfg(all(feature = "alloc", not(feature = "std")))]
3use alloc::borrow::ToOwned;
4#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
5use alloc::sync::Arc;
6use {
7 crate::{
8 TypeMeta,
9 config::{Config, ConfigCore, ZeroCopy},
10 containers::decode_into_slice_t,
11 context,
12 error::{
13 ReadResult, WriteError, WriteResult, invalid_bool_encoding, invalid_char_lead,
14 invalid_tag_encoding, invalid_utf8_encoding, invalid_value, pointer_sized_decode_error,
15 read_length_encoding_overflow, unaligned_pointer_read,
16 },
17 int_encoding::{ByteOrder, Endian, IntEncoding, PlatformEndian},
18 io::{Reader, Writer},
19 len::SeqLen,
20 schema::{
21 SchemaRead, SchemaReadContext, SchemaWrite, size_of_elem_slice, write_elem_slice,
22 },
23 tag_encoding::TagEncoding,
24 },
25 core::{
26 cell::{Cell, RefCell},
27 marker::PhantomData,
28 mem::{MaybeUninit, transmute},
29 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
30 num::{
31 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
32 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
33 },
34 ops::{Bound, Range, RangeInclusive},
35 time::Duration,
36 },
37 pastey::paste,
38};
39#[cfg(feature = "alloc")]
40use {
41 crate::{containers, io::BorrowKind},
42 alloc::{
43 borrow::Cow,
44 boxed::Box,
45 collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
46 rc::Rc,
47 string::String,
48 vec::Vec,
49 },
50 core::mem,
51};
52#[cfg(feature = "std")]
53use {
54 core::hash::{BuildHasher, Hash},
55 std::{
56 collections::{HashMap, HashSet},
57 sync::{Mutex, RwLock},
58 time::{SystemTime, UNIX_EPOCH},
59 },
60};
61
62macro_rules! impl_int_config_dependent {
63 ($($type:ty),*) => {
64 paste! {
65 $(
66 unsafe impl<C: ConfigCore> ZeroCopy<C> for $type where C::IntEncoding: ZeroCopy<C> {}
67
68 unsafe impl<C: ConfigCore> SchemaWrite<C> for $type {
69 type Src = $type;
70
71 const TYPE_META: TypeMeta = if C::IntEncoding::STATIC {
72 TypeMeta::Static {
73 size: size_of::<$type>(),
74 zero_copy: C::IntEncoding::ZERO_COPY,
75 }
76 } else {
77 TypeMeta::Dynamic
78 };
79
80 #[inline(always)]
81 fn size_of(src: &Self::Src) -> WriteResult<usize> {
82 Ok(C::IntEncoding::[<size_of_ $type>](*src))
83 }
84
85 #[inline(always)]
86 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
87 C::IntEncoding::[<encode_ $type>](*src, writer)
88 }
89 }
90
91 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $type {
92 type Dst = $type;
93
94 const TYPE_META: TypeMeta = if C::IntEncoding::STATIC {
95 TypeMeta::Static {
96 size: size_of::<$type>(),
97 zero_copy: C::IntEncoding::ZERO_COPY,
98 }
99 } else {
100 TypeMeta::Dynamic
101 };
102
103 #[inline(always)]
104 fn read(
105 reader: impl Reader<'de>,
106 dst: &mut MaybeUninit<Self::Dst>,
107 ) -> ReadResult<()> {
108 let val = C::IntEncoding::[<decode_ $type>](reader)?;
109 dst.write(val);
110 Ok(())
111 }
112 }
113 )*
114 }
115 };
116}
117
118impl_int_config_dependent!(u16, u32, u64, u128, i16, i32, i64, i128);
119
120macro_rules! impl_float {
130 ($($ty:ty),*) => {
131 $(
132 unsafe impl<C: ConfigCore> ZeroCopy<C> for $ty where C::ByteOrder: PlatformEndian {}
133
134 unsafe impl<C: ConfigCore> SchemaWrite<C> for $ty {
135 type Src = $ty;
136
137 const TYPE_META: TypeMeta = TypeMeta::Static {
138 size: size_of::<$ty>(),
139 #[cfg(target_endian = "big")]
140 zero_copy: matches!(C::ByteOrder::ENDIAN, Endian::Big),
141 #[cfg(target_endian = "little")]
142 zero_copy: matches!(C::ByteOrder::ENDIAN, Endian::Little),
143 };
144
145 #[inline(always)]
146 fn size_of(_val: &Self::Src) -> WriteResult<usize> {
147 Ok(size_of::<$ty>())
148 }
149
150 #[inline(always)]
151 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
152 let bytes = match C::ByteOrder::ENDIAN {
153 Endian::Big => src.to_be_bytes(),
154 Endian::Little => src.to_le_bytes(),
155 };
156 writer.write(&bytes)?;
157 Ok(())
158 }
159 }
160
161 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $ty {
162 type Dst = $ty;
163
164 const TYPE_META: TypeMeta = TypeMeta::Static {
165 size: size_of::<$ty>(),
166 #[cfg(target_endian = "big")]
167 zero_copy: matches!(C::ByteOrder::ENDIAN, Endian::Big),
168 #[cfg(target_endian = "little")]
169 zero_copy: matches!(C::ByteOrder::ENDIAN, Endian::Little),
170 };
171
172 #[inline(always)]
173 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
174 let bytes = reader.take_array::<{ size_of::<$ty>() }>()?;
175 let val = match C::ByteOrder::ENDIAN {
176 Endian::Big => <$ty>::from_be_bytes(bytes),
177 Endian::Little => <$ty>::from_le_bytes(bytes),
178 };
179 dst.write(val);
180 Ok(())
181 }
182 }
183 )*
184 };
185}
186
187impl_float!(f32, f64);
188
189macro_rules! impl_pointer_width {
190 ($($type:ty => $target:ty),*) => {
191 $(
192 #[cfg(target_pointer_width = "64")]
193 unsafe impl<C: ConfigCore> ZeroCopy<C> for $type where C::IntEncoding: ZeroCopy<C> {}
194
195 unsafe impl<C: ConfigCore> SchemaWrite<C> for $type {
196 type Src = $type;
197
198 const TYPE_META: TypeMeta = if C::IntEncoding::STATIC {
199 TypeMeta::Static {
200 size: size_of::<$target>(),
201 #[cfg(target_pointer_width = "64")]
202 zero_copy: C::IntEncoding::ZERO_COPY,
203 #[cfg(not(target_pointer_width = "64"))]
204 zero_copy: false,
205 }
206 } else {
207 TypeMeta::Dynamic
208 };
209
210 #[inline(always)]
211 fn size_of(val: &Self::Src) -> WriteResult<usize> {
212 <$target as SchemaWrite<C>>::size_of(&(*val as $target))
213 }
214
215 #[inline(always)]
216 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
217 <$target as SchemaWrite<C>>::write(writer, &(*src as $target))
218 }
219 }
220
221 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $type {
222 type Dst = $type;
223
224 const TYPE_META: TypeMeta = if C::IntEncoding::STATIC {
225 TypeMeta::Static {
226 size: size_of::<$target>(),
227 #[cfg(target_pointer_width = "64")]
228 zero_copy: C::IntEncoding::ZERO_COPY,
229 #[cfg(not(target_pointer_width = "64"))]
230 zero_copy: false,
231 }
232 } else {
233 TypeMeta::Dynamic
234 };
235
236 #[inline(always)]
237 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
238 let target = <$target as SchemaRead<C>>::get(reader)?;
239 let val = target.try_into().map_err(|_| pointer_sized_decode_error())?;
240 dst.write(val);
241 Ok(())
242 }
243 }
244 )*
245 };
246}
247
248impl_pointer_width!(usize => u64, isize => i64);
249
250macro_rules! impl_byte {
251 ($($type:ty),*) => {
252 $(
253 unsafe impl<C: ConfigCore> ZeroCopy<C> for $type {}
256
257 unsafe impl<C: ConfigCore> SchemaWrite<C> for $type {
258 type Src = $type;
259
260 const TYPE_META: TypeMeta = TypeMeta::Static {
261 size: size_of::<$type>(),
262 zero_copy: true,
263 };
264
265 #[inline(always)]
266 fn size_of(_val: &Self::Src) -> WriteResult<usize> {
267 Ok(size_of::<$type>())
268 }
269
270 #[inline(always)]
271 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
272 writer.write(&[*src as u8])?;
273 Ok(())
274 }
275 }
276
277 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $type {
278 type Dst = $type;
279
280 const TYPE_META: TypeMeta = TypeMeta::Static {
281 size: size_of::<$type>(),
282 zero_copy: true,
283 };
284
285 #[inline(always)]
286 fn read(
287 mut reader: impl Reader<'de>,
288 dst: &mut MaybeUninit<Self::Dst>,
289 ) -> ReadResult<()> {
290 let byte = reader.take_array::<{ 1 }>()?;
291 dst.write(byte[0] as $type);
292 Ok(())
293 }
294 }
295 )*
296 };
297}
298
299impl_byte!(u8, i8);
300
301unsafe impl<C: ConfigCore> SchemaWrite<C> for bool {
302 type Src = bool;
303
304 const TYPE_META: TypeMeta = TypeMeta::Static {
308 size: size_of::<bool>(),
309 zero_copy: true,
310 };
311
312 #[inline]
313 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
314 Ok(size_of::<u8>())
315 }
316
317 #[inline]
318 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
319 unsafe { Ok(writer.write_t(&(*src as u8))?) }
320 }
321}
322
323unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for bool {
324 type Dst = bool;
325
326 const TYPE_META: TypeMeta = TypeMeta::Static {
327 size: size_of::<bool>(),
328 zero_copy: false,
329 };
330
331 #[inline]
332 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
333 let byte = <u8 as SchemaRead<'de, C>>::get(reader)?;
335 match byte {
336 0 => {
337 dst.write(false);
338 }
339 1 => {
340 dst.write(true);
341 }
342 _ => return Err(invalid_bool_encoding(byte)),
343 }
344 Ok(())
345 }
346}
347
348unsafe impl<C: ConfigCore> SchemaWrite<C> for char {
349 type Src = char;
350
351 #[inline]
352 fn size_of(src: &Self::Src) -> WriteResult<usize> {
353 let mut buf = [0; 4];
354 let str = src.encode_utf8(&mut buf);
355 Ok(str.len())
356 }
357
358 #[inline]
359 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
360 let mut buf = [0; 4];
361 let str = src.encode_utf8(&mut buf);
362 writer.write(str.as_bytes())?;
363 Ok(())
364 }
365}
366
367unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for char {
368 type Dst = char;
369
370 #[inline]
371 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
372 use crate::error::ReadError;
373
374 #[cold]
376 fn utf8_error(buf: &[u8]) -> ReadError {
377 invalid_utf8_encoding(core::str::from_utf8(buf).unwrap_err())
378 }
379 let b0 = reader.take_byte()?;
380 let code_point = match b0 {
381 0x00..=0x7F => {
382 dst.write(b0 as char);
383 return Ok(());
384 }
385 0xC2..=0xDF => {
386 let b1 = reader.take_byte()?;
387 if (b1 & 0xC0) != 0x80 {
389 return Err(utf8_error(&[b0, b1]));
390 }
391 ((b0 & 0x1F) as u32) << 6 | ((b1 & 0x3F) as u32)
392 }
393 0xE0..=0xEF => {
394 let [b1, b2] = reader.take_array()?;
395 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 {
396 return Err(utf8_error(&[b0, b1, b2]));
397 }
398 if (b0 == 0xE0 && b1 < 0xA0) || (b0 == 0xED && b1 >= 0xA0) {
400 return Err(utf8_error(&[b0, b1, b2]));
401 }
402 ((b0 & 0x0F) as u32) << 12 | ((b1 & 0x3F) as u32) << 6 | ((b2 & 0x3F) as u32)
403 }
404 0xF0..=0xF4 => {
405 let [b1, b2, b3] = reader.take_array()?;
406 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80 {
407 return Err(utf8_error(&[b0, b1, b2, b3]));
408 }
409 if (b0 == 0xF0 && b1 < 0x90) || (b0 == 0xF4 && b1 > 0x8F) {
410 return Err(utf8_error(&[b0, b1, b2, b3]));
411 }
412 ((b0 & 0x07) as u32) << 18
413 | ((b1 & 0x3F) as u32) << 12
414 | ((b2 & 0x3F) as u32) << 6
415 | ((b3 & 0x3F) as u32)
416 }
417 _ => return Err(invalid_char_lead(b0)),
418 };
419
420 let c = char::from_u32(code_point).ok_or(ReadError::InvalidUtf8Code(code_point))?;
421 dst.write(c);
422 Ok(())
423 }
424}
425
426unsafe impl<T, C: ConfigCore> SchemaWrite<C> for PhantomData<T> {
427 type Src = PhantomData<T>;
428
429 const TYPE_META: TypeMeta = TypeMeta::Static {
430 size: 0,
431 zero_copy: true,
432 };
433
434 #[inline]
435 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
436 Ok(0)
437 }
438
439 #[inline]
440 fn write(_writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
441 Ok(())
442 }
443}
444
445unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for PhantomData<T> {
446 type Dst = PhantomData<T>;
447
448 const TYPE_META: TypeMeta = TypeMeta::Static {
449 size: 0,
450 zero_copy: true,
451 };
452
453 #[inline]
454 fn read(_reader: impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
455 Ok(())
456 }
457}
458
459unsafe impl<C: ConfigCore> SchemaWrite<C> for () {
460 type Src = ();
461
462 const TYPE_META: TypeMeta = TypeMeta::Static {
463 size: 0,
464 zero_copy: true,
465 };
466
467 #[inline]
468 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
469 Ok(0)
470 }
471
472 #[inline]
473 fn write(_writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
474 Ok(())
475 }
476}
477
478unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for () {
479 type Dst = ();
480
481 const TYPE_META: TypeMeta = TypeMeta::Static {
482 size: 0,
483 zero_copy: true,
484 };
485
486 #[inline]
487 fn read(_reader: impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
488 Ok(())
489 }
490}
491
492unsafe impl<T, C: ConfigCore> SchemaWrite<C> for (T,)
493where
494 T: SchemaWrite<C>,
495 T::Src: Sized,
496{
497 type Src = (T::Src,);
498
499 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
500
501 #[inline]
502 fn size_of(value: &Self::Src) -> WriteResult<usize> {
503 T::size_of(&value.0)
504 }
505
506 #[inline]
507 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
508 T::write(writer, &value.0)
509 }
510}
511
512unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for (T,)
513where
514 T: SchemaRead<'de, C>,
515{
516 type Dst = (T::Dst,);
517
518 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
519
520 #[inline]
521 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
522 let slot = unsafe { &mut *(&raw mut (*dst.as_mut_ptr()).0).cast() };
523 T::read(reader, slot)
524 }
525}
526
527#[cfg(feature = "alloc")]
528unsafe impl<T, C: Config> SchemaWrite<C> for Vec<T>
529where
530 T: SchemaWrite<C>,
531 T::Src: Sized,
532{
533 type Src = Vec<T::Src>;
534
535 #[inline]
536 fn size_of(value: &Self::Src) -> WriteResult<usize> {
537 <containers::Vec<T, C::LengthEncoding>>::size_of(value)
538 }
539
540 #[inline]
541 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
542 <containers::Vec<T, C::LengthEncoding>>::write(writer, value)
543 }
544}
545
546#[cfg(feature = "alloc")]
547unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Vec<T>
548where
549 T: SchemaRead<'de, C>,
550{
551 type Dst = Vec<T::Dst>;
552
553 #[inline]
554 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
555 <containers::Vec<T, C::LengthEncoding>>::read(reader, dst)
556 }
557}
558
559#[cfg(feature = "alloc")]
560unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for Vec<T>
561where
562 T: SchemaRead<'de, C>,
563{
564 type Dst = Vec<T::Dst>;
565
566 #[inline]
567 fn read_with_context(
568 ctx: context::Len,
569 mut reader: impl Reader<'de>,
570 dst: &mut MaybeUninit<Self::Dst>,
571 ) -> ReadResult<()> {
572 let len = ctx.0;
573 let mut vec = Vec::with_capacity(len);
574 decode_into_slice_t::<T, C>(reader.by_ref(), &mut vec.spare_capacity_mut()[..len])?;
575 unsafe { vec.set_len(len) };
577 dst.write(vec);
578 Ok(())
579 }
580}
581
582#[cfg(feature = "alloc")]
583unsafe impl<T, C: Config> SchemaWrite<C> for VecDeque<T>
584where
585 T: SchemaWrite<C>,
586 T::Src: Sized,
587{
588 type Src = VecDeque<T::Src>;
589
590 #[inline]
591 fn size_of(value: &Self::Src) -> WriteResult<usize> {
592 <containers::VecDeque<T, C::LengthEncoding>>::size_of(value)
593 }
594
595 #[inline]
596 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
597 <containers::VecDeque<T, C::LengthEncoding>>::write(writer, value)
598 }
599}
600
601#[cfg(feature = "alloc")]
602unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for VecDeque<T>
603where
604 T: SchemaRead<'de, C>,
605{
606 type Dst = VecDeque<T::Dst>;
607
608 #[inline]
609 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
610 <containers::VecDeque<T, C::LengthEncoding>>::read(reader, dst)
611 }
612}
613
614unsafe impl<T, C: Config> SchemaWrite<C> for [T]
615where
616 T: SchemaWrite<C>,
617 T::Src: Sized,
618{
619 type Src = [T::Src];
620
621 #[inline]
622 fn size_of(value: &Self::Src) -> WriteResult<usize> {
623 size_of_elem_slice::<T, C::LengthEncoding, C>(value)
624 }
625
626 #[inline]
627 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
628 write_elem_slice::<T, C::LengthEncoding, C>(writer, value)
629 }
630}
631
632unsafe impl<const N: usize, C: ConfigCore, T> ZeroCopy<C> for [T; N] where T: ZeroCopy<C> {}
636
637unsafe impl<'de, T, const N: usize, C: ConfigCore> SchemaRead<'de, C> for [T; N]
638where
639 T: SchemaRead<'de, C>,
640{
641 type Dst = [T::Dst; N];
642
643 const TYPE_META: TypeMeta = const {
644 match T::TYPE_META {
645 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
646 size: N * size,
647 zero_copy,
648 },
649 TypeMeta::Dynamic => TypeMeta::Dynamic,
650 }
651 };
652
653 #[inline]
654 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
655 let dst =
657 unsafe { transmute::<&mut MaybeUninit<Self::Dst>, &mut [MaybeUninit<T::Dst>; N]>(dst) };
658 decode_into_slice_t::<T, C>(reader, dst)
659 }
660}
661
662unsafe impl<T, const N: usize, C: ConfigCore> SchemaWrite<C> for [T; N]
663where
664 T: SchemaWrite<C>,
665 T::Src: Sized,
666{
667 type Src = [T::Src; N];
668
669 const TYPE_META: TypeMeta = const {
670 match T::TYPE_META {
671 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
672 size: N * size,
673 zero_copy,
674 },
675 TypeMeta::Dynamic => TypeMeta::Dynamic,
676 }
677 };
678
679 #[inline]
680 #[allow(clippy::arithmetic_side_effects)]
681 fn size_of(value: &Self::Src) -> WriteResult<usize> {
682 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
683 return Ok(size);
684 }
685 value
687 .iter()
688 .map(T::size_of)
689 .try_fold(0usize, |acc, x| x.map(|x| acc + x))
690 }
691
692 #[inline]
693 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
694 match Self::TYPE_META {
695 TypeMeta::Static {
696 zero_copy: true, ..
697 } => {
698 unsafe { writer.write_slice_t(value)? };
700 }
701 TypeMeta::Static {
702 size,
703 zero_copy: false,
704 } => {
705 let mut writer = unsafe { writer.as_trusted_for(size) }?;
708 for item in value {
709 T::write(writer.by_ref(), item)?;
710 }
711 writer.finish()?;
712 }
713 TypeMeta::Dynamic => {
714 for item in value {
715 T::write(writer.by_ref(), item)?;
716 }
717 }
718 }
719
720 Ok(())
721 }
722}
723
724unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for Option<T>
725where
726 T: SchemaRead<'de, C>,
727{
728 type Dst = Option<T::Dst>;
729
730 #[inline]
731 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
732 let variant = <u8 as SchemaRead<'de, C>>::get(reader.by_ref())?;
733 match variant {
734 0 => dst.write(Option::None),
735 1 => dst.write(Option::Some(T::get(reader)?)),
736 _ => return Err(invalid_tag_encoding(variant as usize)),
737 };
738
739 Ok(())
740 }
741}
742
743unsafe impl<T, C: ConfigCore> SchemaWrite<C> for Option<T>
744where
745 T: SchemaWrite<C>,
746 T::Src: Sized,
747{
748 type Src = Option<T::Src>;
749
750 #[inline]
751 #[allow(clippy::arithmetic_side_effects)]
752 fn size_of(src: &Self::Src) -> WriteResult<usize> {
753 match src {
754 Option::Some(value) => Ok(1 + T::size_of(value)?),
756 Option::None => Ok(1),
757 }
758 }
759
760 #[inline]
761 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
762 match value {
763 Option::Some(value) => {
764 <u8 as SchemaWrite<C>>::write(writer.by_ref(), &1)?;
765 T::write(writer, value)
766 }
767 Option::None => <u8 as SchemaWrite<C>>::write(writer, &0),
768 }
769 }
770}
771
772unsafe impl<'de, T, E, C: Config> SchemaRead<'de, C> for Result<T, E>
773where
774 T: SchemaRead<'de, C>,
775 E: SchemaRead<'de, C>,
776{
777 type Dst = Result<T::Dst, E::Dst>;
778
779 const TYPE_META: TypeMeta = match (
780 T::TYPE_META,
781 E::TYPE_META,
782 <C::TagEncoding as SchemaRead<C>>::TYPE_META,
783 ) {
784 (
785 TypeMeta::Static { size: t_size, .. },
786 TypeMeta::Static { size: e_size, .. },
787 TypeMeta::Static {
788 size: disc_size, ..
789 },
790 ) if t_size == e_size => TypeMeta::Static {
791 size: disc_size + t_size,
792 zero_copy: false,
793 },
794 _ => TypeMeta::Dynamic,
795 };
796
797 #[inline]
798 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
799 let disc = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
800 match disc {
801 0 => dst.write(Result::Ok(T::get(reader)?)),
802 1 => dst.write(Result::Err(E::get(reader)?)),
803 _ => return Err(invalid_tag_encoding(disc as usize)),
804 };
805
806 Ok(())
807 }
808}
809
810unsafe impl<T, E, C: Config> SchemaWrite<C> for Result<T, E>
811where
812 T: SchemaWrite<C>,
813 E: SchemaWrite<C>,
814 T::Src: Sized,
815 E::Src: Sized,
816{
817 type Src = Result<T::Src, E::Src>;
818
819 const TYPE_META: TypeMeta = match (
820 T::TYPE_META,
821 E::TYPE_META,
822 <C::TagEncoding as SchemaWrite<C>>::TYPE_META,
823 ) {
824 (
825 TypeMeta::Static { size: t_size, .. },
826 TypeMeta::Static { size: e_size, .. },
827 TypeMeta::Static {
828 size: disc_size, ..
829 },
830 ) if t_size == e_size => TypeMeta::Static {
831 size: disc_size + t_size,
832 zero_copy: false,
833 },
834 _ => TypeMeta::Dynamic,
835 };
836
837 #[inline]
838 #[allow(clippy::arithmetic_side_effects)]
839 fn size_of(src: &Self::Src) -> WriteResult<usize> {
840 match src {
841 Result::Ok(value) => Ok(C::TagEncoding::size_of_from_u32(0)? + T::size_of(value)?),
843 Result::Err(error) => Ok(C::TagEncoding::size_of_from_u32(1)? + E::size_of(error)?),
844 }
845 }
846
847 #[inline]
848 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
849 match value {
850 Result::Ok(value) => {
851 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
852 T::write(writer, value)
853 }
854 Result::Err(error) => {
855 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
856 E::write(writer, error)
857 }
858 }
859 }
860}
861
862unsafe impl<'a, T, C: ConfigCore> SchemaWrite<C> for &'a T
863where
864 T: SchemaWrite<C>,
865 T: ?Sized,
866{
867 type Src = &'a T::Src;
868
869 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
870
871 #[inline]
872 fn size_of(src: &Self::Src) -> WriteResult<usize> {
873 T::size_of(*src)
874 }
875
876 #[inline]
877 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
878 T::write(writer, *value)
879 }
880}
881
882macro_rules! impl_heap_container {
883 ($container:ident) => {
884 #[cfg(feature = "alloc")]
885 unsafe impl<T, C: ConfigCore> SchemaWrite<C> for $container<T>
886 where
887 T: SchemaWrite<C>,
888 {
889 type Src = $container<T::Src>;
890
891 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
892
893 #[inline]
894 fn size_of(src: &Self::Src) -> WriteResult<usize> {
895 T::size_of(src)
896 }
897
898 #[inline]
899 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
900 T::write(writer, value)
901 }
902 }
903
904 #[cfg(feature = "alloc")]
905 unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for $container<T>
906 where
907 T: SchemaRead<'de, C>,
908 {
909 type Dst = $container<T::Dst>;
910
911 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
912
913 #[inline]
914 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
915 struct DropGuard<T>(*mut MaybeUninit<T>);
916 impl<T> Drop for DropGuard<T> {
917 #[inline]
918 fn drop(&mut self) {
919 drop(unsafe { $container::from_raw(self.0) });
920 }
921 }
922
923 let mem = $container::<T::Dst>::new_uninit();
924 let ptr = $container::into_raw(mem) as *mut _;
925 let guard: DropGuard<T::Dst> = DropGuard(ptr);
926 T::read(reader, unsafe { &mut *ptr })?;
927
928 mem::forget(guard);
929
930 unsafe {
931 dst.write($container::from_raw(ptr).assume_init());
933 }
934 Ok(())
935 }
936 }
937 };
938}
939
940impl_heap_container!(Box);
941impl_heap_container!(Rc);
942#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
943impl_heap_container!(Arc);
944
945#[cfg(feature = "alloc")]
946unsafe impl<T, C: Config> SchemaWrite<C> for Box<[T]>
947where
948 T: SchemaWrite<C>,
949 T::Src: Sized,
950{
951 type Src = Box<[T::Src]>;
952
953 #[inline]
954 fn size_of(src: &Self::Src) -> WriteResult<usize> {
955 <containers::Box<[T], C::LengthEncoding>>::size_of(src)
956 }
957
958 #[inline]
959 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
960 <containers::Box<[T], C::LengthEncoding>>::write(writer, value)
961 }
962}
963
964#[cfg(feature = "alloc")]
965unsafe impl<T, C: Config> SchemaWrite<C> for Rc<[T]>
966where
967 T: SchemaWrite<C>,
968 T::Src: Sized,
969{
970 type Src = Rc<[T::Src]>;
971
972 #[inline]
973 fn size_of(src: &Self::Src) -> WriteResult<usize> {
974 <containers::Rc<[T], C::LengthEncoding>>::size_of(src)
975 }
976
977 #[inline]
978 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
979 <containers::Rc<[T], C::LengthEncoding>>::write(writer, value)
980 }
981}
982
983#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
984unsafe impl<T, C: Config> SchemaWrite<C> for Arc<[T]>
985where
986 T: SchemaWrite<C>,
987 T::Src: Sized,
988{
989 type Src = Arc<[T::Src]>;
990
991 #[inline]
992 fn size_of(src: &Self::Src) -> WriteResult<usize> {
993 <containers::Arc<[T], C::LengthEncoding>>::size_of(src)
994 }
995
996 #[inline]
997 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
998 <containers::Arc<[T], C::LengthEncoding>>::write(writer, value)
999 }
1000}
1001
1002#[cfg(feature = "alloc")]
1003unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Box<[T]>
1004where
1005 T: SchemaRead<'de, C>,
1006{
1007 type Dst = Box<[T::Dst]>;
1008
1009 #[inline]
1010 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1011 <containers::Box<[T], C::LengthEncoding>>::read(reader, dst)
1012 }
1013}
1014
1015#[cfg(feature = "alloc")]
1016unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Rc<[T]>
1017where
1018 T: SchemaRead<'de, C>,
1019{
1020 type Dst = Rc<[T::Dst]>;
1021
1022 #[inline]
1023 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1024 <containers::Rc<[T], C::LengthEncoding>>::read(reader, dst)
1025 }
1026}
1027
1028#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
1029unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Arc<[T]>
1030where
1031 T: SchemaRead<'de, C>,
1032{
1033 type Dst = Arc<[T::Dst]>;
1034
1035 #[inline]
1036 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1037 <containers::Arc<[T], C::LengthEncoding>>::read(reader, dst)
1038 }
1039}
1040
1041unsafe impl<C: Config> SchemaWrite<C> for str {
1042 type Src = str;
1043
1044 #[inline]
1045 #[allow(clippy::arithmetic_side_effects)]
1046 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1047 Ok(C::LengthEncoding::write_bytes_needed(src.len())? + src.len())
1049 }
1050
1051 #[inline]
1052 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1053 C::LengthEncoding::write(writer.by_ref(), src.len())?;
1054 writer.write(src.as_bytes())?;
1055 Ok(())
1056 }
1057}
1058
1059#[cfg(feature = "alloc")]
1060unsafe impl<C: Config> SchemaWrite<C> for String {
1061 type Src = String;
1062
1063 #[inline]
1064 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1065 <str as SchemaWrite<C>>::size_of(src)
1066 }
1067
1068 #[inline]
1069 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1070 C::LengthEncoding::prealloc_check::<u8>(src.len())?;
1071 <str as SchemaWrite<C>>::write(writer, src)
1072 }
1073}
1074
1075unsafe impl<'de, C: Config> SchemaRead<'de, C> for &'de str {
1076 type Dst = &'de str;
1077
1078 #[inline]
1079 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1080 let len = C::LengthEncoding::read(reader.by_ref())?;
1081 <&'de str as SchemaReadContext<C, _>>::read_with_context(context::Len(len), reader, dst)
1082 }
1083}
1084
1085unsafe impl<'de, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for &'de str {
1086 type Dst = &'de str;
1087
1088 #[inline]
1089 fn read_with_context(
1090 context::Len(len): context::Len,
1091 mut reader: impl Reader<'de>,
1092 dst: &mut MaybeUninit<Self::Dst>,
1093 ) -> ReadResult<()> {
1094 let bytes = reader.take_borrowed(len)?;
1095 match core::str::from_utf8(bytes) {
1096 Ok(s) => {
1097 dst.write(s);
1098 Ok(())
1099 }
1100 Err(e) => Err(invalid_utf8_encoding(e)),
1101 }
1102 }
1103}
1104
1105#[cfg(feature = "alloc")]
1106unsafe impl<'de, C: Config> SchemaRead<'de, C> for String {
1107 type Dst = String;
1108
1109 #[inline]
1110 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1111 let len = C::LengthEncoding::read_prealloc_check::<u8>(reader.by_ref())?;
1112 <String as SchemaReadContext<C, _>>::read_with_context(context::Len(len), reader, dst)
1113 }
1114}
1115
1116#[cfg(feature = "alloc")]
1117unsafe impl<'de, C: Config> SchemaReadContext<'de, C, context::Len> for String {
1118 type Dst = String;
1119
1120 #[inline]
1121 fn read_with_context(
1122 ctx: context::Len,
1123 reader: impl Reader<'de>,
1124 dst: &mut MaybeUninit<Self::Dst>,
1125 ) -> ReadResult<()> {
1126 let bytes = <Vec<u8> as SchemaReadContext<C, _>>::get_with_context(ctx, reader)?;
1127 match String::from_utf8(bytes) {
1128 Ok(s) => {
1129 dst.write(s);
1130 Ok(())
1131 }
1132 Err(e) => Err(invalid_utf8_encoding(e.utf8_error())),
1133 }
1134 }
1135}
1136
1137#[cfg(feature = "alloc")]
1143macro_rules! seq_capacity {
1144 ($key: ty, $len: expr) => {
1145 $len
1146 };
1147 ($key: ty, $len: expr, cap_unique_keys) => {
1148 $crate::len::unique_key_capacity::<$key>($len)
1149 };
1150}
1151
1152#[cfg(feature = "alloc")]
1153pub(crate) use seq_capacity;
1154
1155macro_rules! impl_seq_kv {
1163 ($feature: literal,
1164 $target: ident<$key: ident : $($constraint:path)|*, $value: ident $(, $state:ident : $($state_constraint:path)|* )?>,
1165 $with_capacity: expr
1166 $(, $cap_unique_keys: ident)?) => {
1167 #[cfg(feature = $feature)]
1168 unsafe impl<C: $crate::config::Config, $key, $value $(, $state)?> $crate::schema::SchemaWrite<C> for $target<$key, $value $(, $state)?>
1169 where
1170 $key: $crate::schema::SchemaWrite<C>,
1171 $key::Src: Sized,
1172 $value: $crate::schema::SchemaWrite<C>,
1173 $value::Src: Sized
1174 $($(, $state: $state_constraint+)*)?
1175 {
1176 type Src = $target<$key::Src, $value::Src $(, $state)?>;
1177
1178 #[inline]
1179 #[allow(clippy::arithmetic_side_effects)]
1180 fn size_of(src: &Self::Src) -> $crate::error::WriteResult<usize> {
1181 if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1182 return Ok(C::LengthEncoding::write_bytes_needed(src.len())? + (key_size + value_size) * src.len());
1183 }
1184 Ok(C::LengthEncoding::write_bytes_needed(src.len())? +
1185 src
1186 .iter()
1187 .try_fold(
1188 0usize,
1189 |acc, (k, v)|
1190 Ok::<_, $crate::error::WriteError>(
1191 acc
1192 + $key::size_of(k)?
1193 + $value::size_of(v)?
1194 )
1195 )?
1196 )
1197 }
1198
1199 #[inline]
1200 fn write(mut writer: impl $crate::io::Writer, src: &Self::Src) -> $crate::error::WriteResult<()> {
1201 if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1202 let len = src.len();
1203 #[allow(clippy::arithmetic_side_effects)]
1204 let needed = C::LengthEncoding::write_bytes_needed_prealloc_check::<($key::Src, $value::Src)>(len)? + (key_size + value_size) * len;
1205 let mut writer = unsafe { writer.as_trusted_for(needed) }?;
1208 C::LengthEncoding::write(writer.by_ref(), len)?;
1209 for (k, v) in src.iter() {
1210 $key::write(writer.by_ref(), k)?;
1211 $value::write(writer.by_ref(), v)?;
1212 }
1213 writer.finish()?;
1214 return Ok(());
1215 }
1216 let len = src.len();
1217 C::LengthEncoding::prealloc_check::<($key::Src, $value::Src)>(len)?;
1218 C::LengthEncoding::write(writer.by_ref(), len)?;
1219 for (k, v) in src.iter() {
1220 $key::write(writer.by_ref(), k)?;
1221 $value::write(writer.by_ref(), v)?;
1222 }
1223 Ok(())
1224 }
1225 }
1226
1227 #[cfg(feature = $feature)]
1228 unsafe impl<'de, C: $crate::config::Config, $key, $value $(, $state)?> $crate::schema::SchemaRead<'de, C> for $target<$key, $value $(, $state)?>
1229 where
1230 $key: $crate::schema::SchemaRead<'de, C>,
1231 $value: $crate::schema::SchemaRead<'de, C>
1232 $(,$key::Dst: $constraint+)*
1233 $($(, $state: $state_constraint+)* )?
1234 {
1235 type Dst = $target<$key::Dst, $value::Dst $(, $state)?>;
1236
1237 #[inline]
1238 fn read(mut reader: impl $crate::io::Reader<'de>, dst: &mut core::mem::MaybeUninit<Self::Dst>) -> $crate::error::ReadResult<()> {
1239 let len = C::LengthEncoding::read_prealloc_check::<($key::Dst, $value::Dst)>(reader.by_ref())?;
1240 let capacity = $crate::schema::impls::seq_capacity!($key::Dst, len $(, $cap_unique_keys)?);
1242
1243 let map = if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1244 let Some(el_size) = key_size.checked_add(value_size) else {
1247 return Err($crate::error::read_length_encoding_overflow("usize::MAX"));
1248 };
1249 let mut reader = unsafe { reader.as_trusted_for_seq(len, el_size) }?;
1250 let mut map = $with_capacity(capacity $(, $state::default())?);
1251 for _ in 0..len {
1252 let k = $key::get(reader.by_ref())?;
1253 let v = $value::get(reader.by_ref())?;
1254 map.insert(k, v);
1255 }
1256 map
1257 } else {
1258 let mut map = $with_capacity(capacity $(, $state::default())?);
1259 for _ in 0..len {
1260 let k = $key::get(reader.by_ref())?;
1261 let v = $value::get(reader.by_ref())?;
1262 map.insert(k, v);
1263 }
1264 map
1265 };
1266
1267 dst.write(map);
1268 Ok(())
1269 }
1270 }
1271 };
1272}
1273
1274pub(crate) use impl_seq_kv;
1275
1276macro_rules! impl_seq_v {
1277 ($feature: literal,
1278 $target: ident <$key: ident : $($constraint:path)|* $(, $state:ident : $($state_constraint:path)|*)?>,
1279 $with_capacity: expr, $insert: ident
1280 $(, $cap_unique_keys: ident)?) => {
1281 #[cfg(feature = $feature)]
1282 unsafe impl<C: $crate::config::Config, $key: $crate::schema::SchemaWrite<C> $(, $state)?> $crate::schema::SchemaWrite<C> for $target<$key $(, $state)?>
1283 where
1284 $key::Src: Sized
1285 $($(, $state: $state_constraint+)* )?
1286 {
1287 type Src = $target<$key::Src $(, $state)?>;
1288
1289 #[inline]
1290 fn size_of(src: &Self::Src) -> $crate::error::WriteResult<usize> {
1291 $crate::schema::size_of_elem_iter::<$key, C::LengthEncoding, C>(src.iter())
1292 }
1293
1294 #[inline]
1295 fn write(writer: impl $crate::io::Writer, src: &Self::Src) -> $crate::error::WriteResult<()> {
1296 $crate::schema::write_elem_iter_prealloc_check::<$key, C::LengthEncoding, C>(writer, src.iter())
1297 }
1298 }
1299
1300 #[cfg(feature = $feature)]
1301 unsafe impl<'de, C: $crate::config::Config, $key $(, $state)?> $crate::schema::SchemaRead<'de, C> for $target<$key $(, $state)?>
1302 where
1303 $key: $crate::schema::SchemaRead<'de, C>
1304 $(,$key::Dst: $constraint+)*
1305 $($(, $state: $state_constraint+)* )?
1306 {
1307 type Dst = $target<$key::Dst $(, $state)?>;
1308
1309 #[inline]
1310 fn read(mut reader: impl $crate::io::Reader<'de>, dst: &mut core::mem::MaybeUninit<Self::Dst>) -> $crate::error::ReadResult<()> {
1311 let len = C::LengthEncoding::read_prealloc_check::<$key::Dst>(reader.by_ref())?;
1312 let capacity = $crate::schema::impls::seq_capacity!($key::Dst, len $(, $cap_unique_keys)?);
1314
1315 let map = match $key::TYPE_META {
1316 $crate::TypeMeta::Static { size, .. } => {
1317 let mut reader = unsafe { reader.as_trusted_for_seq(len, size) }?;
1320 let mut set = $with_capacity(capacity $(, $state::default())?);
1321 for _ in 0..len {
1322 set.$insert($key::get(reader.by_ref())?);
1323 }
1324 set
1325 }
1326 $crate::TypeMeta::Dynamic => {
1327 let mut set = $with_capacity(capacity $(, $state::default())?);
1328 for _ in 0..len {
1329 set.$insert($key::get(reader.by_ref())?);
1330 }
1331 set
1332 }
1333 };
1334
1335 dst.write(map);
1336 Ok(())
1337 }
1338 }
1339 };
1340}
1341
1342pub(crate) use impl_seq_v;
1343
1344impl_seq_kv! { "alloc", BTreeMap<K: Ord, V>, |_| BTreeMap::new() }
1345impl_seq_kv! { "std", HashMap<K: Hash | Eq, V, S: BuildHasher | Default>, HashMap::with_capacity_and_hasher, cap_unique_keys }
1346impl_seq_v! { "alloc", BTreeSet<K: Ord>, |_| BTreeSet::new(), insert }
1347impl_seq_v! { "std", HashSet<K: Hash | Eq, S: BuildHasher | Default>, HashSet::with_capacity_and_hasher, insert, cap_unique_keys }
1348impl_seq_v! { "alloc", LinkedList<K:>, |_| LinkedList::new(), push_back }
1349
1350#[cfg(feature = "alloc")]
1351unsafe impl<T, C: Config> SchemaWrite<C> for BinaryHeap<T>
1352where
1353 T: SchemaWrite<C>,
1354 T::Src: Sized,
1355{
1356 type Src = BinaryHeap<T::Src>;
1357
1358 #[inline]
1359 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1360 <containers::BinaryHeap<T, C::LengthEncoding>>::size_of(src)
1361 }
1362
1363 #[inline]
1364 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1365 <containers::BinaryHeap<T, C::LengthEncoding>>::write(writer, src)
1366 }
1367}
1368
1369#[cfg(feature = "alloc")]
1370unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for BinaryHeap<T>
1371where
1372 T: SchemaRead<'de, C>,
1373 T::Dst: Ord,
1374{
1375 type Dst = BinaryHeap<T::Dst>;
1376
1377 #[inline]
1378 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1379 <containers::BinaryHeap<T, C::LengthEncoding>>::read(reader, dst)
1380 }
1381}
1382
1383mod zero_copy {
1384 use {
1385 super::*,
1386 core::slice::{from_raw_parts, from_raw_parts_mut},
1387 };
1388
1389 #[inline(always)]
1400 fn cast_ensure_aligned<C: ConfigCore, T, U>(ptr: *const T) -> ReadResult<*const U> {
1401 let ptr = ptr.cast::<U>();
1402
1403 if !C::ZERO_COPY_ALIGN_CHECK {
1404 return Ok(ptr);
1405 }
1406
1407 if align_of::<U>() > 1 && !ptr.is_aligned() {
1408 return Err(unaligned_pointer_read());
1409 }
1410 Ok(ptr)
1411 }
1412
1413 #[inline(always)]
1418 fn cast_ensure_aligned_mut<C: ConfigCore, T, U>(ptr: *mut T) -> ReadResult<*mut U> {
1419 let ptr = ptr.cast::<U>();
1420
1421 if !C::ZERO_COPY_ALIGN_CHECK {
1422 return Ok(ptr);
1423 }
1424
1425 if align_of::<U>() > 1 && !ptr.is_aligned() {
1426 return Err(unaligned_pointer_read());
1427 }
1428 Ok(ptr)
1429 }
1430
1431 #[inline(always)]
1443 pub(super) unsafe fn cast_slice_to_t<C: ConfigCore, T>(bytes: &[u8]) -> ReadResult<&T> {
1444 debug_assert_eq!(bytes.len(), size_of::<T>());
1445 let ptr = cast_ensure_aligned::<C, u8, T>(bytes.as_ptr())?;
1446 let val = unsafe { &*ptr };
1450 Ok(val)
1451 }
1452
1453 #[inline(always)]
1457 pub(super) unsafe fn cast_slice_to_t_mut<C: ConfigCore, T>(
1458 bytes: &mut [u8],
1459 ) -> ReadResult<&mut T> {
1460 debug_assert_eq!(bytes.len(), size_of::<T>());
1461 let ptr = cast_ensure_aligned_mut::<C, u8, T>(bytes.as_mut_ptr())?;
1462 let val = unsafe { &mut *ptr };
1466 Ok(val)
1467 }
1468
1469 #[inline(always)]
1481 pub(super) unsafe fn cast_slice_to_slice_t<C: ConfigCore, T>(
1482 bytes: &[u8],
1483 len: usize,
1484 ) -> ReadResult<&[T]> {
1485 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1486 let ptr = cast_ensure_aligned::<C, u8, T>(bytes.as_ptr())?;
1487 let slice = unsafe { from_raw_parts(ptr, len) };
1491 Ok(slice)
1492 }
1493
1494 #[inline(always)]
1498 pub(super) unsafe fn cast_slice_to_slice_t_mut<C: ConfigCore, T>(
1499 bytes: &mut [u8],
1500 len: usize,
1501 ) -> ReadResult<&mut [T]> {
1502 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1503 let ptr = cast_ensure_aligned_mut::<C, u8, T>(bytes.as_mut_ptr())?;
1504 let slice = unsafe { from_raw_parts_mut(ptr, len) };
1508 Ok(slice)
1509 }
1510
1511 pub(super) const fn type_meta_t<'de, T, C: ConfigCore>() -> TypeMeta
1513 where
1514 T: SchemaRead<'de, C> + ZeroCopy<C>,
1515 {
1516 match T::TYPE_META {
1517 TypeMeta::Static {
1518 size,
1519 zero_copy: true,
1520 } => TypeMeta::Static {
1521 size,
1522 zero_copy: false,
1539 },
1540 _ => panic!("Type is not zero-copy"),
1542 }
1543 }
1544
1545 pub(super) const fn type_meta_slice<'de, T, C: ConfigCore>() -> TypeMeta
1551 where
1552 T: SchemaRead<'de, C> + ZeroCopy<C>,
1553 {
1554 match T::TYPE_META {
1555 TypeMeta::Static {
1556 zero_copy: true, ..
1557 } => TypeMeta::Dynamic,
1558 _ => panic!("Type is not zero-copy"),
1559 }
1560 }
1561
1562 #[inline(always)]
1568 pub(super) fn read_slice_len_checked<'de, C: Config>(
1569 reader: impl Reader<'de>,
1570 size: usize,
1571 ) -> ReadResult<(usize, usize)> {
1572 let len = C::LengthEncoding::read(reader)?;
1573 let Some(total_size) = len.checked_mul(size) else {
1574 return Err(read_length_encoding_overflow("usize::MAX"));
1575 };
1576 Ok((len, total_size))
1577 }
1578}
1579
1580unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for &'de T
1581where
1582 T: SchemaRead<'de, C> + ZeroCopy<C>,
1583{
1584 type Dst = &'de T::Dst;
1585
1586 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T, C>();
1587
1588 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1589 let size = T::TYPE_META.size_assert_zero_copy();
1590 let bytes = reader.take_borrowed(size)?;
1591 let val = unsafe { zero_copy::cast_slice_to_t::<C, T::Dst>(bytes)? };
1595 dst.write(val);
1596 Ok(())
1597 }
1598}
1599
1600unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for &'de mut T
1601where
1602 T: SchemaRead<'de, C> + ZeroCopy<C>,
1603{
1604 type Dst = &'de mut T::Dst;
1605
1606 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T, C>();
1607
1608 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1609 let size = T::TYPE_META.size_assert_zero_copy();
1610 let bytes = reader.take_borrowed_mut(size)?;
1611 let val = unsafe { zero_copy::cast_slice_to_t_mut::<C, T::Dst>(bytes)? };
1615 dst.write(val);
1616 Ok(())
1617 }
1618}
1619
1620unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for &'de [T]
1621where
1622 T: SchemaRead<'de, C> + ZeroCopy<C>,
1623{
1624 type Dst = &'de [T::Dst];
1625
1626 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1627
1628 #[inline]
1629 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1630 let len = C::LengthEncoding::read(reader.by_ref())?;
1631 <&[T]>::read_with_context(context::Len(len), reader, dst)?;
1632 Ok(())
1633 }
1634}
1635
1636unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for &'de [T]
1637where
1638 T: SchemaRead<'de, C> + ZeroCopy<C>,
1639{
1640 type Dst = &'de [T::Dst];
1641
1642 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1643
1644 #[inline]
1645 fn read_with_context(
1646 context::Len(len): context::Len,
1647 mut reader: impl Reader<'de>,
1648 dst: &mut MaybeUninit<Self::Dst>,
1649 ) -> ReadResult<()> {
1650 let size = T::TYPE_META.size_assert_zero_copy();
1651 let Some(total_size) = len.checked_mul(size) else {
1652 return Err(read_length_encoding_overflow("usize::MAX"));
1653 };
1654 let bytes = reader.take_borrowed(total_size)?;
1655 let slice = unsafe { zero_copy::cast_slice_to_slice_t::<C, T::Dst>(bytes, len)? };
1659 dst.write(slice);
1660 Ok(())
1661 }
1662}
1663
1664unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for &'de mut [T]
1665where
1666 T: SchemaRead<'de, C> + ZeroCopy<C>,
1667{
1668 type Dst = &'de mut [T::Dst];
1669
1670 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1671
1672 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1673 let size = T::TYPE_META.size_assert_zero_copy();
1674 let (len, total_size) = zero_copy::read_slice_len_checked::<C>(reader.by_ref(), size)?;
1675 let bytes = reader.take_borrowed_mut(total_size)?;
1676 let slice = unsafe { zero_copy::cast_slice_to_slice_t_mut::<C, T::Dst>(bytes, len)? };
1680 dst.write(slice);
1681 Ok(())
1682 }
1683}
1684
1685unsafe impl<C: ConfigCore> SchemaWrite<C> for Duration {
1686 type Src = Duration;
1687
1688 const TYPE_META: TypeMeta = match (
1689 <u64 as SchemaWrite<C>>::TYPE_META,
1690 <u32 as SchemaWrite<C>>::TYPE_META,
1691 ) {
1692 (TypeMeta::Static { size: u64_size, .. }, TypeMeta::Static { size: u32_size, .. }) => {
1694 TypeMeta::Static {
1695 size: u64_size + u32_size,
1696 zero_copy: false,
1697 }
1698 }
1699 _ => TypeMeta::Dynamic,
1700 };
1701
1702 #[inline]
1703 #[allow(clippy::arithmetic_side_effects)]
1704 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1705 match <Self as SchemaWrite<C>>::TYPE_META {
1706 TypeMeta::Static { size, .. } => Ok(size),
1707 TypeMeta::Dynamic => {
1708 let secs = <u64 as SchemaWrite<C>>::size_of(&src.as_secs())?;
1709 let nanos = <u32 as SchemaWrite<C>>::size_of(&src.subsec_nanos())?;
1710 Ok(secs + nanos)
1711 }
1712 }
1713 }
1714
1715 #[inline]
1716 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1717 <u64 as SchemaWrite<C>>::write(writer.by_ref(), &src.as_secs())?;
1718 <u32 as SchemaWrite<C>>::write(writer, &src.subsec_nanos())?;
1719 Ok(())
1720 }
1721}
1722
1723unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Duration {
1724 type Dst = Duration;
1725
1726 const TYPE_META: TypeMeta = <Duration as SchemaWrite<C>>::TYPE_META;
1727
1728 #[inline]
1729 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1730 let secs = <u64 as SchemaRead<'de, C>>::get(reader.by_ref())?;
1731 let nanos = <u32 as SchemaRead<'de, C>>::get(reader)?;
1732 if secs.checked_add(u64::from(nanos) / 1_000_000_000).is_none() {
1733 return Err(invalid_value("Duration overflow"));
1734 }
1735 dst.write(Duration::new(secs, nanos));
1736 Ok(())
1737 }
1738}
1739
1740#[cfg(feature = "std")]
1741unsafe impl<C: ConfigCore> SchemaWrite<C> for SystemTime {
1742 type Src = SystemTime;
1743
1744 const TYPE_META: TypeMeta = <Duration as SchemaWrite<C>>::TYPE_META;
1745
1746 #[inline]
1747 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1748 let duration = src
1749 .duration_since(UNIX_EPOCH)
1750 .map_err(|_| crate::error::WriteError::Custom("SystemTime before UNIX_EPOCH"))?;
1751 <Duration as SchemaWrite<C>>::size_of(&duration)
1752 }
1753
1754 #[inline]
1755 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1756 let duration = src
1757 .duration_since(UNIX_EPOCH)
1758 .map_err(|_| crate::error::WriteError::Custom("SystemTime before UNIX_EPOCH"))?;
1759 <Duration as SchemaWrite<C>>::write(writer, &duration)?;
1760 Ok(())
1761 }
1762}
1763
1764#[cfg(feature = "std")]
1765unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SystemTime {
1766 type Dst = SystemTime;
1767
1768 const TYPE_META: TypeMeta = <Duration as SchemaRead<'de, C>>::TYPE_META;
1769
1770 #[inline]
1771 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1772 let duration = <Duration as SchemaRead<'de, C>>::get(reader)?;
1773 let system_time = UNIX_EPOCH
1774 .checked_add(duration)
1775 .ok_or_else(|| invalid_value("SystemTime overflow"))?;
1776 dst.write(system_time);
1777 Ok(())
1778 }
1779}
1780
1781unsafe impl<C: ConfigCore> SchemaWrite<C> for Ipv4Addr {
1782 type Src = Ipv4Addr;
1783
1784 const TYPE_META: TypeMeta = TypeMeta::Static {
1785 size: 4,
1786 zero_copy: false,
1787 };
1788
1789 #[inline]
1790 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
1791 Ok(4)
1792 }
1793
1794 #[inline]
1795 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1796 writer.write(&src.octets())?;
1797 Ok(())
1798 }
1799}
1800
1801unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Ipv4Addr {
1802 type Dst = Ipv4Addr;
1803
1804 const TYPE_META: TypeMeta = TypeMeta::Static {
1805 size: 4,
1806 zero_copy: false,
1807 };
1808
1809 #[inline]
1810 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1811 let bytes = reader.take_array::<4>()?;
1812 dst.write(Ipv4Addr::from(bytes));
1813 Ok(())
1814 }
1815}
1816
1817unsafe impl<C: ConfigCore> SchemaWrite<C> for Ipv6Addr {
1818 type Src = Ipv6Addr;
1819
1820 const TYPE_META: TypeMeta = TypeMeta::Static {
1821 size: 16,
1822 zero_copy: false,
1823 };
1824
1825 #[inline]
1826 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
1827 Ok(16)
1828 }
1829
1830 #[inline]
1831 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1832 writer.write(&src.octets())?;
1833 Ok(())
1834 }
1835}
1836
1837unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Ipv6Addr {
1838 type Dst = Ipv6Addr;
1839
1840 const TYPE_META: TypeMeta = TypeMeta::Static {
1841 size: 16,
1842 zero_copy: false,
1843 };
1844
1845 #[inline]
1846 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1847 let bytes = reader.take_array::<16>()?;
1848 dst.write(Ipv6Addr::from(bytes));
1849 Ok(())
1850 }
1851}
1852
1853unsafe impl<C: Config> SchemaWrite<C> for IpAddr {
1854 type Src = IpAddr;
1855
1856 #[inline]
1857 #[allow(clippy::arithmetic_side_effects)]
1858 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1859 Ok(match src {
1860 IpAddr::V4(_) => C::TagEncoding::size_of_from_u32(0)? + 4,
1861 IpAddr::V6(_) => C::TagEncoding::size_of_from_u32(1)? + 16,
1862 })
1863 }
1864
1865 #[inline]
1866 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1867 match src {
1868 IpAddr::V4(addr) => {
1869 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
1870 <Ipv4Addr as SchemaWrite<C>>::write(writer, addr)
1871 }
1872 IpAddr::V6(addr) => {
1873 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
1874 <Ipv6Addr as SchemaWrite<C>>::write(writer, addr)
1875 }
1876 }
1877 }
1878}
1879
1880unsafe impl<'de, C: Config> SchemaRead<'de, C> for IpAddr {
1881 type Dst = IpAddr;
1882
1883 #[inline]
1884 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1885 let tag = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
1886 match tag {
1887 0 => {
1888 let addr = <Ipv4Addr as SchemaRead<'de, C>>::get(reader)?;
1889 dst.write(IpAddr::V4(addr));
1890 Ok(())
1891 }
1892 1 => {
1893 let addr = <Ipv6Addr as SchemaRead<'de, C>>::get(reader)?;
1894 dst.write(IpAddr::V6(addr));
1895 Ok(())
1896 }
1897 _ => Err(invalid_tag_encoding(tag as usize)),
1898 }
1899 }
1900}
1901
1902unsafe impl<C: ConfigCore> SchemaWrite<C> for SocketAddrV4 {
1903 type Src = Self;
1904
1905 const TYPE_META: TypeMeta = TypeMeta::join_types([
1906 <Ipv4Addr as SchemaWrite<C>>::TYPE_META,
1907 <u16 as SchemaWrite<C>>::TYPE_META,
1908 ]);
1909
1910 #[inline]
1911 #[allow(clippy::arithmetic_side_effects)]
1912 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1913 Ok(4 + <u16 as SchemaWrite<C>>::size_of(&src.port())?)
1914 }
1915
1916 #[inline]
1917 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1918 <Ipv4Addr as SchemaWrite<C>>::write(writer.by_ref(), src.ip())?;
1919 <u16 as SchemaWrite<C>>::write(writer, &src.port())
1920 }
1921}
1922
1923unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SocketAddrV4 {
1924 type Dst = Self;
1925
1926 const TYPE_META: TypeMeta = TypeMeta::join_types([
1927 <Ipv4Addr as SchemaRead<C>>::TYPE_META,
1928 <u16 as SchemaRead<C>>::TYPE_META,
1929 ]);
1930
1931 #[inline]
1932 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1933 let ip = <Ipv4Addr as SchemaRead<'de, C>>::get(reader.by_ref())?;
1934 let port = <u16 as SchemaRead<'de, C>>::get(reader)?;
1935 dst.write(Self::Dst::new(ip, port));
1936 Ok(())
1937 }
1938}
1939
1940unsafe impl<C: ConfigCore> SchemaWrite<C> for SocketAddrV6 {
1941 type Src = Self;
1942
1943 const TYPE_META: TypeMeta = TypeMeta::join_types([
1944 <Ipv6Addr as SchemaWrite<C>>::TYPE_META,
1945 <u16 as SchemaWrite<C>>::TYPE_META,
1946 ]);
1947
1948 #[inline]
1949 #[allow(clippy::arithmetic_side_effects)]
1950 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1951 Ok(16 + <u16 as SchemaWrite<C>>::size_of(&src.port())?)
1952 }
1953
1954 #[inline]
1955 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1956 <Ipv6Addr as SchemaWrite<C>>::write(writer.by_ref(), src.ip())?;
1957 <u16 as SchemaWrite<C>>::write(writer, &src.port())
1958 }
1959}
1960
1961unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SocketAddrV6 {
1962 type Dst = Self;
1963
1964 const TYPE_META: TypeMeta = TypeMeta::join_types([
1965 <Ipv6Addr as SchemaRead<C>>::TYPE_META,
1966 <u16 as SchemaRead<C>>::TYPE_META,
1967 ]);
1968
1969 #[inline]
1970 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1971 let ip = <Ipv6Addr as SchemaRead<'de, C>>::get(reader.by_ref())?;
1972 let port = <u16 as SchemaRead<'de, C>>::get(reader)?;
1973 dst.write(SocketAddrV6::new(ip, port, 0, 0));
1975 Ok(())
1976 }
1977}
1978
1979unsafe impl<C: Config> SchemaWrite<C> for SocketAddr {
1980 type Src = Self;
1981
1982 #[inline]
1983 #[allow(clippy::arithmetic_side_effects)]
1984 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1985 Ok(match src {
1986 Self::V4(v4) => {
1987 C::TagEncoding::size_of_from_u32(0)?
1988 + <SocketAddrV4 as SchemaWrite<C>>::size_of(v4)?
1989 }
1990 Self::V6(v6) => {
1991 C::TagEncoding::size_of_from_u32(1)?
1992 + <SocketAddrV6 as SchemaWrite<C>>::size_of(v6)?
1993 }
1994 })
1995 }
1996
1997 #[inline]
1998 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1999 match src {
2000 Self::V4(addr) => {
2001 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
2002 <SocketAddrV4 as SchemaWrite<C>>::write(writer, addr)
2003 }
2004 Self::V6(addr) => {
2005 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
2006 <SocketAddrV6 as SchemaWrite<C>>::write(writer, addr)
2007 }
2008 }
2009 }
2010}
2011
2012unsafe impl<'de, C: Config> SchemaRead<'de, C> for SocketAddr {
2013 type Dst = Self;
2014
2015 #[inline]
2016 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2017 let tag = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
2018 match tag {
2019 0 => {
2020 let addr = <SocketAddrV4 as SchemaRead<'de, C>>::get(reader)?;
2021 dst.write(Self::V4(addr));
2022 Ok(())
2023 }
2024 1 => {
2025 let addr = <SocketAddrV6 as SchemaRead<'de, C>>::get(reader)?;
2026 dst.write(Self::V6(addr));
2027 Ok(())
2028 }
2029 _ => Err(invalid_tag_encoding(tag as usize)),
2030 }
2031 }
2032}
2033
2034macro_rules! impl_nonzero {
2035 ($($nonzero_ty:ty => $primitive_ty:ty),* $(,)?) => {
2036 $(
2037 unsafe impl<C: ConfigCore> SchemaWrite<C> for $nonzero_ty {
2038 type Src = $nonzero_ty;
2039
2040 const TYPE_META: TypeMeta = <$primitive_ty as SchemaWrite<C>>::TYPE_META;
2041
2042 #[inline(always)]
2043 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2044 <$primitive_ty as SchemaWrite<C>>::size_of(&src.get())
2045 }
2046
2047 #[inline(always)]
2048 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2049 <$primitive_ty as SchemaWrite<C>>::write(writer, &src.get())
2050 }
2051 }
2052
2053 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $nonzero_ty {
2054 type Dst = $nonzero_ty;
2055
2056 const TYPE_META: TypeMeta = const {
2057 match <$primitive_ty as SchemaRead<'de, C>>::TYPE_META {
2058 TypeMeta::Static { size, .. } => TypeMeta::Static {
2059 size,
2060 zero_copy: false,
2061 },
2062 TypeMeta::Dynamic => TypeMeta::Dynamic,
2063 }
2064 };
2065
2066 #[inline(always)]
2067 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2068 let val = <$primitive_ty as SchemaRead<'de, C>>::get(reader)?;
2069 let nonzero = <$nonzero_ty>::new(val)
2070 .ok_or_else(|| invalid_value(concat!(
2071 "NonZero value cannot be zero for type ",
2072 stringify!($nonzero_ty)
2073 )))?;
2074 dst.write(nonzero);
2075 Ok(())
2076 }
2077 }
2078 )*
2079 };
2080}
2081
2082impl_nonzero!(
2083 NonZeroU8 => u8,
2084 NonZeroU16 => u16,
2085 NonZeroU32 => u32,
2086 NonZeroU64 => u64,
2087 NonZeroU128 => u128,
2088 NonZeroUsize => usize,
2089 NonZeroI8 => i8,
2090 NonZeroI16 => i16,
2091 NonZeroI32 => i32,
2092 NonZeroI64 => i64,
2093 NonZeroI128 => i128,
2094 NonZeroIsize => isize,
2095);
2096
2097unsafe impl<C: Config, T> SchemaWrite<C> for Bound<T>
2098where
2099 T: SchemaWrite<C>,
2100 T::Src: Sized,
2101{
2102 type Src = Bound<T::Src>;
2103
2104 #[inline]
2105 #[allow(clippy::arithmetic_side_effects)]
2106 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2107 match src {
2108 Bound::Unbounded => C::TagEncoding::size_of_from_u32(0),
2109 Bound::Included(value) => Ok(C::TagEncoding::size_of_from_u32(1)? + T::size_of(value)?),
2110 Bound::Excluded(value) => Ok(C::TagEncoding::size_of_from_u32(2)? + T::size_of(value)?),
2111 }
2112 }
2113
2114 #[inline]
2115 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
2116 match value {
2117 Bound::Unbounded => C::TagEncoding::write_from_u32(writer.by_ref(), 0),
2118 Bound::Included(value) => {
2119 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
2120 T::write(writer, value)
2121 }
2122 Bound::Excluded(value) => {
2123 C::TagEncoding::write_from_u32(writer.by_ref(), 2)?;
2124 T::write(writer, value)
2125 }
2126 }
2127 }
2128}
2129
2130unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Bound<T>
2131where
2132 T: SchemaRead<'de, C>,
2133{
2134 type Dst = Bound<T::Dst>;
2135
2136 #[inline]
2137 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2138 let disc = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
2139 match disc {
2140 0 => dst.write(Bound::Unbounded),
2141 1 => dst.write(Bound::Included(T::get(reader.by_ref())?)),
2142 2 => dst.write(Bound::Excluded(T::get(reader.by_ref())?)),
2143 _ => return Err(invalid_tag_encoding(disc as usize)),
2144 };
2145
2146 Ok(())
2147 }
2148}
2149
2150unsafe impl<Idx, C: Config> SchemaWrite<C> for Range<Idx>
2151where
2152 Idx: SchemaWrite<C>,
2153 Idx::Src: Sized,
2154{
2155 type Src = Range<Idx::Src>;
2156
2157 const TYPE_META: TypeMeta = const {
2158 match Idx::TYPE_META {
2159 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2160 size: idx_size + idx_size,
2161 zero_copy: false,
2162 },
2163 TypeMeta::Dynamic => TypeMeta::Dynamic,
2164 }
2165 };
2166
2167 #[inline]
2168 #[allow(clippy::arithmetic_side_effects)]
2169 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2170 Ok(Idx::size_of(&src.start)? + Idx::size_of(&src.end)?)
2171 }
2172
2173 #[inline]
2174 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2175 match Self::TYPE_META {
2176 TypeMeta::Static { size, .. } => {
2177 let mut writer = unsafe { writer.as_trusted_for(size) }?;
2180 Idx::write(writer.by_ref(), &src.start)?;
2181 Idx::write(writer.by_ref(), &src.end)?;
2182 writer.finish()?;
2183 }
2184 TypeMeta::Dynamic => {
2185 Idx::write(writer.by_ref(), &src.start)?;
2186 Idx::write(writer.by_ref(), &src.end)?;
2187 }
2188 }
2189 Ok(())
2190 }
2191}
2192
2193unsafe impl<'de, Idx, C: ConfigCore> SchemaRead<'de, C> for Range<Idx>
2194where
2195 Idx: SchemaRead<'de, C>,
2196{
2197 type Dst = Range<Idx::Dst>;
2198
2199 const TYPE_META: TypeMeta = const {
2200 match Idx::TYPE_META {
2201 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2202 size: idx_size + idx_size,
2203 zero_copy: false,
2204 },
2205 TypeMeta::Dynamic => TypeMeta::Dynamic,
2206 }
2207 };
2208
2209 #[inline]
2210 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2211 match Self::TYPE_META {
2212 TypeMeta::Static { size, .. } => {
2213 let mut reader = unsafe { reader.as_trusted_for(size) }?;
2216 let start = Idx::get(reader.by_ref())?;
2217 let end = Idx::get(reader.by_ref())?;
2218 dst.write(Range { start, end });
2219 }
2220 TypeMeta::Dynamic => {
2221 let start = Idx::get(reader.by_ref())?;
2222 let end = Idx::get(reader.by_ref())?;
2223 dst.write(Range { start, end });
2224 }
2225 };
2226
2227 Ok(())
2228 }
2229}
2230
2231unsafe impl<Idx, C: ConfigCore> SchemaWrite<C> for RangeInclusive<Idx>
2232where
2233 Idx: SchemaWrite<C>,
2234 Idx::Src: Sized,
2235{
2236 type Src = RangeInclusive<Idx::Src>;
2237
2238 const TYPE_META: TypeMeta = const {
2239 match Idx::TYPE_META {
2240 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2241 size: idx_size + idx_size,
2242 zero_copy: false,
2243 },
2244 TypeMeta::Dynamic => TypeMeta::Dynamic,
2245 }
2246 };
2247
2248 #[inline]
2249 #[allow(clippy::arithmetic_side_effects)]
2250 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2251 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
2252 return Ok(size);
2253 }
2254 Ok(Idx::size_of(src.start())? + Idx::size_of(src.end())?)
2255 }
2256
2257 #[inline]
2258 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2259 match Self::TYPE_META {
2260 TypeMeta::Static { size, .. } => {
2261 let mut writer = unsafe { writer.as_trusted_for(size) }?;
2264 Idx::write(writer.by_ref(), src.start())?;
2265 Idx::write(writer.by_ref(), src.end())?;
2266 writer.finish()?;
2267 }
2268 TypeMeta::Dynamic => {
2269 Idx::write(writer.by_ref(), src.start())?;
2270 Idx::write(writer.by_ref(), src.end())?;
2271 }
2272 }
2273 Ok(())
2274 }
2275}
2276
2277unsafe impl<'de, Idx, C: ConfigCore> SchemaRead<'de, C> for RangeInclusive<Idx>
2278where
2279 Idx: SchemaRead<'de, C>,
2280{
2281 type Dst = RangeInclusive<Idx::Dst>;
2282
2283 const TYPE_META: TypeMeta = const {
2284 match Idx::TYPE_META {
2285 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2286 size: idx_size + idx_size,
2287 zero_copy: false,
2288 },
2289 TypeMeta::Dynamic => TypeMeta::Dynamic,
2290 }
2291 };
2292
2293 #[inline]
2294 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2295 match Self::TYPE_META {
2296 TypeMeta::Static { size, .. } => {
2297 let mut reader = unsafe { reader.as_trusted_for(size) }?;
2300 let start = Idx::get(reader.by_ref())?;
2301 let end = Idx::get(reader.by_ref())?;
2302 dst.write(RangeInclusive::new(start, end));
2303 }
2304 TypeMeta::Dynamic => {
2305 let start = Idx::get(reader.by_ref())?;
2306 let end = Idx::get(reader.by_ref())?;
2307 dst.write(RangeInclusive::new(start, end));
2308 }
2309 };
2310 Ok(())
2311 }
2312}
2313
2314#[cfg(feature = "alloc")]
2315unsafe impl<T: ?Sized, C: ConfigCore> SchemaWrite<C> for Cow<'_, T>
2316where
2317 T: ToOwned,
2318 T: SchemaWrite<C, Src = T>,
2319{
2320 type Src = Self;
2321
2322 #[inline]
2323 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2324 T::size_of(src.as_ref())
2325 }
2326
2327 #[inline]
2328 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2329 T::write(writer, src.as_ref())
2330 }
2331}
2332
2333#[cfg(feature = "alloc")]
2334unsafe impl<'de, T: ?Sized, C: ConfigCore> SchemaRead<'de, C> for Cow<'de, T>
2335where
2336 T: ToOwned,
2337 &'de T: SchemaRead<'de, C, Dst = &'de T>,
2338 T::Owned: SchemaRead<'de, C, Dst = T::Owned>,
2339{
2340 type Dst = Self;
2341
2342 #[inline]
2343 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2344 let cow = if reader.supports_borrow(BorrowKind::Backing) {
2345 Cow::Borrowed(<&T as SchemaRead<C>>::get(reader)?)
2346 } else {
2347 Cow::Owned(<T::Owned as SchemaRead<C>>::get(reader)?)
2348 };
2349 dst.write(cow);
2350 Ok(())
2351 }
2352}
2353
2354#[cfg(feature = "alloc")]
2355unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for Cow<'de, [T]>
2356where
2357 [T]: ToOwned,
2358 &'de [T]: SchemaReadContext<'de, C, context::Len, Dst = &'de [T]>,
2359 <[T] as ToOwned>::Owned: SchemaReadContext<'de, C, context::Len, Dst = <[T] as ToOwned>::Owned>,
2360{
2361 type Dst = Self;
2362
2363 #[inline]
2364 fn read_with_context(
2365 ctx: context::Len,
2366 reader: impl Reader<'de>,
2367 dst: &mut MaybeUninit<Self::Dst>,
2368 ) -> ReadResult<()> {
2369 let cow = if reader.supports_borrow(BorrowKind::Backing) {
2370 Cow::Borrowed(<&[T]>::get_with_context(ctx, reader)?)
2371 } else {
2372 Cow::Owned(<<[T] as ToOwned>::Owned>::get_with_context(ctx, reader)?)
2373 };
2374 dst.write(cow);
2375 Ok(())
2376 }
2377}
2378
2379unsafe impl<C: ConfigCore, T> SchemaWrite<C> for Cell<T>
2380where
2381 T: SchemaWrite<C>,
2382 T::Src: Copy,
2383{
2384 type Src = Cell<T::Src>;
2385
2386 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2387
2388 #[inline]
2389 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2390 T::size_of(&src.get())
2391 }
2392
2393 #[inline]
2394 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2395 T::write(writer, &src.get())
2396 }
2397}
2398
2399unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for Cell<T>
2400where
2401 T: SchemaRead<'de, C>,
2402{
2403 type Dst = Cell<T::Dst>;
2404
2405 const TYPE_META: TypeMeta = T::TYPE_META;
2406
2407 #[inline]
2408 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2409 dst.write(T::get(reader).map(Self::Dst::new)?);
2410 Ok(())
2411 }
2412}
2413
2414unsafe impl<C: ConfigCore, T> SchemaWrite<C> for RefCell<T>
2415where
2416 T: SchemaWrite<C> + ?Sized,
2417{
2418 type Src = RefCell<T::Src>;
2419
2420 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2421
2422 #[inline]
2423 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2424 let val = src
2425 .try_borrow()
2426 .map_err(|_| WriteError::Custom("RefCell already mutably borrowed"))?;
2427 T::size_of(&*val)
2428 }
2429
2430 #[inline]
2431 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2432 let val = src
2433 .try_borrow()
2434 .map_err(|_| WriteError::Custom("RefCell already mutably borrowed"))?;
2435 T::write(writer, &*val)
2436 }
2437}
2438
2439unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for RefCell<T>
2440where
2441 T: SchemaRead<'de, C> + ?Sized,
2442{
2443 type Dst = RefCell<T::Dst>;
2444
2445 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2446
2447 #[inline]
2448 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2449 dst.write(T::get(reader).map(Self::Dst::new)?);
2450 Ok(())
2451 }
2452}
2453
2454#[cfg(feature = "std")]
2455unsafe impl<C: ConfigCore, T> SchemaWrite<C> for Mutex<T>
2456where
2457 T: SchemaWrite<C> + ?Sized,
2458{
2459 type Src = Mutex<T::Src>;
2460
2461 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2462
2463 #[inline]
2464 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2465 let val = src
2466 .lock()
2467 .map_err(|_| WriteError::Custom("Mutex poisoned"))?;
2468 T::size_of(&*val)
2469 }
2470
2471 #[inline]
2472 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2473 let val = src
2474 .lock()
2475 .map_err(|_| WriteError::Custom("Mutex poisoned"))?;
2476 T::write(writer, &*val)
2477 }
2478}
2479
2480#[cfg(feature = "std")]
2481unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for Mutex<T>
2482where
2483 T: SchemaRead<'de, C> + ?Sized,
2484{
2485 type Dst = Mutex<T::Dst>;
2486
2487 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2488
2489 #[inline]
2490 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2491 dst.write(T::get(reader).map(Self::Dst::new)?);
2492 Ok(())
2493 }
2494}
2495
2496#[cfg(feature = "std")]
2497unsafe impl<C: ConfigCore, T> SchemaWrite<C> for RwLock<T>
2498where
2499 T: SchemaWrite<C> + ?Sized,
2500{
2501 type Src = RwLock<T::Src>;
2502
2503 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2504
2505 #[inline]
2506 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2507 let val = src
2508 .read()
2509 .map_err(|_| WriteError::Custom("RwLock poisoned"))?;
2510 T::size_of(&*val)
2511 }
2512
2513 #[inline]
2514 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2515 let val = src
2516 .read()
2517 .map_err(|_| WriteError::Custom("RwLock poisoned"))?;
2518 T::write(writer, &*val)
2519 }
2520}
2521
2522#[cfg(feature = "std")]
2523unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for RwLock<T>
2524where
2525 T: SchemaRead<'de, C> + ?Sized,
2526{
2527 type Dst = RwLock<T::Dst>;
2528
2529 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2530
2531 #[inline]
2532 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2533 dst.write(T::get(reader).map(Self::Dst::new)?);
2534 Ok(())
2535 }
2536}