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 {
305 size: size_of::<bool>(),
306 zero_copy: false,
307 };
308
309 #[inline]
310 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
311 Ok(size_of::<u8>())
312 }
313
314 #[inline]
315 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
316 unsafe { Ok(writer.write_t(&(*src as u8))?) }
317 }
318}
319
320unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for bool {
321 type Dst = bool;
322
323 const TYPE_META: TypeMeta = TypeMeta::Static {
324 size: size_of::<bool>(),
325 zero_copy: false,
326 };
327
328 #[inline]
329 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
330 let byte = <u8 as SchemaRead<'de, C>>::get(reader)?;
332 match byte {
333 0 => {
334 dst.write(false);
335 }
336 1 => {
337 dst.write(true);
338 }
339 _ => return Err(invalid_bool_encoding(byte)),
340 }
341 Ok(())
342 }
343}
344
345unsafe impl<C: ConfigCore> SchemaWrite<C> for char {
346 type Src = char;
347
348 #[inline]
349 fn size_of(src: &Self::Src) -> WriteResult<usize> {
350 let mut buf = [0; 4];
351 let str = src.encode_utf8(&mut buf);
352 Ok(str.len())
353 }
354
355 #[inline]
356 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
357 let mut buf = [0; 4];
358 let str = src.encode_utf8(&mut buf);
359 writer.write(str.as_bytes())?;
360 Ok(())
361 }
362}
363
364unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for char {
365 type Dst = char;
366
367 #[inline]
368 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
369 use crate::error::ReadError;
370
371 #[cold]
373 fn utf8_error(buf: &[u8]) -> ReadError {
374 invalid_utf8_encoding(core::str::from_utf8(buf).unwrap_err())
375 }
376 let b0 = reader.take_byte()?;
377 let code_point = match b0 {
378 0x00..=0x7F => {
379 dst.write(b0 as char);
380 return Ok(());
381 }
382 0xC2..=0xDF => {
383 let b1 = reader.take_byte()?;
384 if (b1 & 0xC0) != 0x80 {
386 return Err(utf8_error(&[b0, b1]));
387 }
388 ((b0 & 0x1F) as u32) << 6 | ((b1 & 0x3F) as u32)
389 }
390 0xE0..=0xEF => {
391 let [b1, b2] = reader.take_array()?;
392 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 {
393 return Err(utf8_error(&[b0, b1, b2]));
394 }
395 if (b0 == 0xE0 && b1 < 0xA0) || (b0 == 0xED && b1 >= 0xA0) {
397 return Err(utf8_error(&[b0, b1, b2]));
398 }
399 ((b0 & 0x0F) as u32) << 12 | ((b1 & 0x3F) as u32) << 6 | ((b2 & 0x3F) as u32)
400 }
401 0xF0..=0xF4 => {
402 let [b1, b2, b3] = reader.take_array()?;
403 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80 {
404 return Err(utf8_error(&[b0, b1, b2, b3]));
405 }
406 if (b0 == 0xF0 && b1 < 0x90) || (b0 == 0xF4 && b1 > 0x8F) {
407 return Err(utf8_error(&[b0, b1, b2, b3]));
408 }
409 ((b0 & 0x07) as u32) << 18
410 | ((b1 & 0x3F) as u32) << 12
411 | ((b2 & 0x3F) as u32) << 6
412 | ((b3 & 0x3F) as u32)
413 }
414 _ => return Err(invalid_char_lead(b0)),
415 };
416
417 let c = char::from_u32(code_point).ok_or(ReadError::InvalidUtf8Code(code_point))?;
418 dst.write(c);
419 Ok(())
420 }
421}
422
423unsafe impl<T, C: ConfigCore> SchemaWrite<C> for PhantomData<T> {
424 type Src = PhantomData<T>;
425
426 const TYPE_META: TypeMeta = TypeMeta::Static {
427 size: 0,
428 zero_copy: true,
429 };
430
431 #[inline]
432 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
433 Ok(0)
434 }
435
436 #[inline]
437 fn write(_writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
438 Ok(())
439 }
440}
441
442unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for PhantomData<T> {
443 type Dst = PhantomData<T>;
444
445 const TYPE_META: TypeMeta = TypeMeta::Static {
446 size: 0,
447 zero_copy: true,
448 };
449
450 #[inline]
451 fn read(_reader: impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
452 Ok(())
453 }
454}
455
456unsafe impl<C: ConfigCore> SchemaWrite<C> for () {
457 type Src = ();
458
459 const TYPE_META: TypeMeta = TypeMeta::Static {
460 size: 0,
461 zero_copy: true,
462 };
463
464 #[inline]
465 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
466 Ok(0)
467 }
468
469 #[inline]
470 fn write(_writer: impl Writer, _src: &Self::Src) -> WriteResult<()> {
471 Ok(())
472 }
473}
474
475unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for () {
476 type Dst = ();
477
478 const TYPE_META: TypeMeta = TypeMeta::Static {
479 size: 0,
480 zero_copy: true,
481 };
482
483 #[inline]
484 fn read(_reader: impl Reader<'de>, _dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
485 Ok(())
486 }
487}
488
489#[cfg(feature = "alloc")]
490unsafe impl<T, C: Config> SchemaWrite<C> for Vec<T>
491where
492 T: SchemaWrite<C>,
493 T::Src: Sized,
494{
495 type Src = Vec<T::Src>;
496
497 #[inline]
498 fn size_of(value: &Self::Src) -> WriteResult<usize> {
499 <containers::Vec<T, C::LengthEncoding>>::size_of(value)
500 }
501
502 #[inline]
503 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
504 <containers::Vec<T, C::LengthEncoding>>::write(writer, value)
505 }
506}
507
508#[cfg(feature = "alloc")]
509unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Vec<T>
510where
511 T: SchemaRead<'de, C>,
512{
513 type Dst = Vec<T::Dst>;
514
515 #[inline]
516 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
517 <containers::Vec<T, C::LengthEncoding>>::read(reader, dst)
518 }
519}
520
521#[cfg(feature = "alloc")]
522unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for Vec<T>
523where
524 T: SchemaRead<'de, C>,
525{
526 type Dst = Vec<T::Dst>;
527
528 #[inline]
529 fn read_with_context(
530 ctx: context::Len,
531 mut reader: impl Reader<'de>,
532 dst: &mut MaybeUninit<Self::Dst>,
533 ) -> ReadResult<()> {
534 let len = ctx.0;
535 let mut vec = Vec::with_capacity(len);
536 decode_into_slice_t::<T, C>(reader.by_ref(), &mut vec.spare_capacity_mut()[..len])?;
537 unsafe { vec.set_len(len) };
539 dst.write(vec);
540 Ok(())
541 }
542}
543
544#[cfg(feature = "alloc")]
545unsafe impl<T, C: Config> SchemaWrite<C> for VecDeque<T>
546where
547 T: SchemaWrite<C>,
548 T::Src: Sized,
549{
550 type Src = VecDeque<T::Src>;
551
552 #[inline]
553 fn size_of(value: &Self::Src) -> WriteResult<usize> {
554 <containers::VecDeque<T, C::LengthEncoding>>::size_of(value)
555 }
556
557 #[inline]
558 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
559 <containers::VecDeque<T, C::LengthEncoding>>::write(writer, value)
560 }
561}
562
563#[cfg(feature = "alloc")]
564unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for VecDeque<T>
565where
566 T: SchemaRead<'de, C>,
567{
568 type Dst = VecDeque<T::Dst>;
569
570 #[inline]
571 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
572 <containers::VecDeque<T, C::LengthEncoding>>::read(reader, dst)
573 }
574}
575
576unsafe impl<T, C: Config> SchemaWrite<C> for [T]
577where
578 T: SchemaWrite<C>,
579 T::Src: Sized,
580{
581 type Src = [T::Src];
582
583 #[inline]
584 fn size_of(value: &Self::Src) -> WriteResult<usize> {
585 size_of_elem_slice::<T, C::LengthEncoding, C>(value)
586 }
587
588 #[inline]
589 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
590 write_elem_slice::<T, C::LengthEncoding, C>(writer, value)
591 }
592}
593
594unsafe impl<const N: usize, C: ConfigCore, T> ZeroCopy<C> for [T; N] where T: ZeroCopy<C> {}
598
599unsafe impl<'de, T, const N: usize, C: ConfigCore> SchemaRead<'de, C> for [T; N]
600where
601 T: SchemaRead<'de, C>,
602{
603 type Dst = [T::Dst; N];
604
605 const TYPE_META: TypeMeta = const {
606 match T::TYPE_META {
607 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
608 size: N * size,
609 zero_copy,
610 },
611 TypeMeta::Dynamic => TypeMeta::Dynamic,
612 }
613 };
614
615 #[inline]
616 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
617 let dst =
619 unsafe { transmute::<&mut MaybeUninit<Self::Dst>, &mut [MaybeUninit<T::Dst>; N]>(dst) };
620 decode_into_slice_t::<T, C>(reader, dst)
621 }
622}
623
624unsafe impl<T, const N: usize, C: ConfigCore> SchemaWrite<C> for [T; N]
625where
626 T: SchemaWrite<C>,
627 T::Src: Sized,
628{
629 type Src = [T::Src; N];
630
631 const TYPE_META: TypeMeta = const {
632 match T::TYPE_META {
633 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
634 size: N * size,
635 zero_copy,
636 },
637 TypeMeta::Dynamic => TypeMeta::Dynamic,
638 }
639 };
640
641 #[inline]
642 #[allow(clippy::arithmetic_side_effects)]
643 fn size_of(value: &Self::Src) -> WriteResult<usize> {
644 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
645 return Ok(size);
646 }
647 value
649 .iter()
650 .map(T::size_of)
651 .try_fold(0usize, |acc, x| x.map(|x| acc + x))
652 }
653
654 #[inline]
655 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
656 match Self::TYPE_META {
657 TypeMeta::Static {
658 zero_copy: true, ..
659 } => {
660 unsafe { writer.write_slice_t(value)? };
662 }
663 TypeMeta::Static {
664 size,
665 zero_copy: false,
666 } => {
667 let mut writer = unsafe { writer.as_trusted_for(size) }?;
670 for item in value {
671 T::write(writer.by_ref(), item)?;
672 }
673 writer.finish()?;
674 }
675 TypeMeta::Dynamic => {
676 for item in value {
677 T::write(writer.by_ref(), item)?;
678 }
679 }
680 }
681
682 Ok(())
683 }
684}
685
686unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for Option<T>
687where
688 T: SchemaRead<'de, C>,
689{
690 type Dst = Option<T::Dst>;
691
692 #[inline]
693 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
694 let variant = <u8 as SchemaRead<'de, C>>::get(reader.by_ref())?;
695 match variant {
696 0 => dst.write(Option::None),
697 1 => dst.write(Option::Some(T::get(reader)?)),
698 _ => return Err(invalid_tag_encoding(variant as usize)),
699 };
700
701 Ok(())
702 }
703}
704
705unsafe impl<T, C: ConfigCore> SchemaWrite<C> for Option<T>
706where
707 T: SchemaWrite<C>,
708 T::Src: Sized,
709{
710 type Src = Option<T::Src>;
711
712 #[inline]
713 #[allow(clippy::arithmetic_side_effects)]
714 fn size_of(src: &Self::Src) -> WriteResult<usize> {
715 match src {
716 Option::Some(value) => Ok(1 + T::size_of(value)?),
718 Option::None => Ok(1),
719 }
720 }
721
722 #[inline]
723 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
724 match value {
725 Option::Some(value) => {
726 <u8 as SchemaWrite<C>>::write(writer.by_ref(), &1)?;
727 T::write(writer, value)
728 }
729 Option::None => <u8 as SchemaWrite<C>>::write(writer, &0),
730 }
731 }
732}
733
734unsafe impl<'de, T, E, C: Config> SchemaRead<'de, C> for Result<T, E>
735where
736 T: SchemaRead<'de, C>,
737 E: SchemaRead<'de, C>,
738{
739 type Dst = Result<T::Dst, E::Dst>;
740
741 const TYPE_META: TypeMeta = match (
742 T::TYPE_META,
743 E::TYPE_META,
744 <C::TagEncoding as SchemaRead<C>>::TYPE_META,
745 ) {
746 (
747 TypeMeta::Static { size: t_size, .. },
748 TypeMeta::Static { size: e_size, .. },
749 TypeMeta::Static {
750 size: disc_size, ..
751 },
752 ) if t_size == e_size => TypeMeta::Static {
753 size: disc_size + t_size,
754 zero_copy: false,
755 },
756 _ => TypeMeta::Dynamic,
757 };
758
759 #[inline]
760 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
761 let disc = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
762 match disc {
763 0 => dst.write(Result::Ok(T::get(reader)?)),
764 1 => dst.write(Result::Err(E::get(reader)?)),
765 _ => return Err(invalid_tag_encoding(disc as usize)),
766 };
767
768 Ok(())
769 }
770}
771
772unsafe impl<T, E, C: Config> SchemaWrite<C> for Result<T, E>
773where
774 T: SchemaWrite<C>,
775 E: SchemaWrite<C>,
776 T::Src: Sized,
777 E::Src: Sized,
778{
779 type Src = Result<T::Src, E::Src>;
780
781 const TYPE_META: TypeMeta = match (
782 T::TYPE_META,
783 E::TYPE_META,
784 <C::TagEncoding as SchemaWrite<C>>::TYPE_META,
785 ) {
786 (
787 TypeMeta::Static { size: t_size, .. },
788 TypeMeta::Static { size: e_size, .. },
789 TypeMeta::Static {
790 size: disc_size, ..
791 },
792 ) if t_size == e_size => TypeMeta::Static {
793 size: disc_size + t_size,
794 zero_copy: false,
795 },
796 _ => TypeMeta::Dynamic,
797 };
798
799 #[inline]
800 #[allow(clippy::arithmetic_side_effects)]
801 fn size_of(src: &Self::Src) -> WriteResult<usize> {
802 match src {
803 Result::Ok(value) => Ok(C::TagEncoding::size_of_from_u32(0)? + T::size_of(value)?),
805 Result::Err(error) => Ok(C::TagEncoding::size_of_from_u32(1)? + E::size_of(error)?),
806 }
807 }
808
809 #[inline]
810 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
811 match value {
812 Result::Ok(value) => {
813 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
814 T::write(writer, value)
815 }
816 Result::Err(error) => {
817 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
818 E::write(writer, error)
819 }
820 }
821 }
822}
823
824unsafe impl<'a, T, C: ConfigCore> SchemaWrite<C> for &'a T
825where
826 T: SchemaWrite<C>,
827 T: ?Sized,
828{
829 type Src = &'a T::Src;
830
831 const TYPE_META: TypeMeta = T::TYPE_META;
832
833 #[inline]
834 fn size_of(src: &Self::Src) -> WriteResult<usize> {
835 T::size_of(*src)
836 }
837
838 #[inline]
839 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
840 T::write(writer, *value)
841 }
842}
843
844macro_rules! impl_heap_container {
845 ($container:ident) => {
846 #[cfg(feature = "alloc")]
847 unsafe impl<T, C: ConfigCore> SchemaWrite<C> for $container<T>
848 where
849 T: SchemaWrite<C>,
850 {
851 type Src = $container<T::Src>;
852
853 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
854
855 #[inline]
856 fn size_of(src: &Self::Src) -> WriteResult<usize> {
857 T::size_of(src)
858 }
859
860 #[inline]
861 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
862 T::write(writer, value)
863 }
864 }
865
866 #[cfg(feature = "alloc")]
867 unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for $container<T>
868 where
869 T: SchemaRead<'de, C>,
870 {
871 type Dst = $container<T::Dst>;
872
873 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
874
875 #[inline]
876 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
877 struct DropGuard<T>(*mut MaybeUninit<T>);
878 impl<T> Drop for DropGuard<T> {
879 #[inline]
880 fn drop(&mut self) {
881 drop(unsafe { $container::from_raw(self.0) });
882 }
883 }
884
885 let mem = $container::<T::Dst>::new_uninit();
886 let ptr = $container::into_raw(mem) as *mut _;
887 let guard: DropGuard<T::Dst> = DropGuard(ptr);
888 T::read(reader, unsafe { &mut *ptr })?;
889
890 mem::forget(guard);
891
892 unsafe {
893 dst.write($container::from_raw(ptr).assume_init());
895 }
896 Ok(())
897 }
898 }
899 };
900}
901
902impl_heap_container!(Box);
903impl_heap_container!(Rc);
904#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
905impl_heap_container!(Arc);
906
907#[cfg(feature = "alloc")]
908unsafe impl<T, C: Config> SchemaWrite<C> for Box<[T]>
909where
910 T: SchemaWrite<C>,
911 T::Src: Sized,
912{
913 type Src = Box<[T::Src]>;
914
915 #[inline]
916 fn size_of(src: &Self::Src) -> WriteResult<usize> {
917 <containers::Box<[T], C::LengthEncoding>>::size_of(src)
918 }
919
920 #[inline]
921 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
922 <containers::Box<[T], C::LengthEncoding>>::write(writer, value)
923 }
924}
925
926#[cfg(feature = "alloc")]
927unsafe impl<T, C: Config> SchemaWrite<C> for Rc<[T]>
928where
929 T: SchemaWrite<C>,
930 T::Src: Sized,
931{
932 type Src = Rc<[T::Src]>;
933
934 #[inline]
935 fn size_of(src: &Self::Src) -> WriteResult<usize> {
936 <containers::Rc<[T], C::LengthEncoding>>::size_of(src)
937 }
938
939 #[inline]
940 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
941 <containers::Rc<[T], C::LengthEncoding>>::write(writer, value)
942 }
943}
944
945#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
946unsafe impl<T, C: Config> SchemaWrite<C> for Arc<[T]>
947where
948 T: SchemaWrite<C>,
949 T::Src: Sized,
950{
951 type Src = Arc<[T::Src]>;
952
953 #[inline]
954 fn size_of(src: &Self::Src) -> WriteResult<usize> {
955 <containers::Arc<[T], C::LengthEncoding>>::size_of(src)
956 }
957
958 #[inline]
959 fn write(writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
960 <containers::Arc<[T], C::LengthEncoding>>::write(writer, value)
961 }
962}
963
964#[cfg(feature = "alloc")]
965unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Box<[T]>
966where
967 T: SchemaRead<'de, C>,
968{
969 type Dst = Box<[T::Dst]>;
970
971 #[inline]
972 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
973 <containers::Box<[T], C::LengthEncoding>>::read(reader, dst)
974 }
975}
976
977#[cfg(feature = "alloc")]
978unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Rc<[T]>
979where
980 T: SchemaRead<'de, C>,
981{
982 type Dst = Rc<[T::Dst]>;
983
984 #[inline]
985 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
986 <containers::Rc<[T], C::LengthEncoding>>::read(reader, dst)
987 }
988}
989
990#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
991unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Arc<[T]>
992where
993 T: SchemaRead<'de, C>,
994{
995 type Dst = Arc<[T::Dst]>;
996
997 #[inline]
998 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
999 <containers::Arc<[T], C::LengthEncoding>>::read(reader, dst)
1000 }
1001}
1002
1003unsafe impl<C: Config> SchemaWrite<C> for str {
1004 type Src = str;
1005
1006 #[inline]
1007 #[allow(clippy::arithmetic_side_effects)]
1008 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1009 Ok(C::LengthEncoding::write_bytes_needed(src.len())? + src.len())
1011 }
1012
1013 #[inline]
1014 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1015 C::LengthEncoding::write(writer.by_ref(), src.len())?;
1016 writer.write(src.as_bytes())?;
1017 Ok(())
1018 }
1019}
1020
1021#[cfg(feature = "alloc")]
1022unsafe impl<C: Config> SchemaWrite<C> for String {
1023 type Src = String;
1024
1025 #[inline]
1026 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1027 <str as SchemaWrite<C>>::size_of(src)
1028 }
1029
1030 #[inline]
1031 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1032 C::LengthEncoding::prealloc_check::<u8>(src.len())?;
1033 <str as SchemaWrite<C>>::write(writer, src)
1034 }
1035}
1036
1037unsafe impl<'de, C: Config> SchemaRead<'de, C> for &'de str {
1038 type Dst = &'de str;
1039
1040 #[inline]
1041 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1042 let len = C::LengthEncoding::read(reader.by_ref())?;
1043 <&'de str as SchemaReadContext<C, _>>::read_with_context(context::Len(len), reader, dst)
1044 }
1045}
1046
1047unsafe impl<'de, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for &'de str {
1048 type Dst = &'de str;
1049
1050 #[inline]
1051 fn read_with_context(
1052 context::Len(len): context::Len,
1053 mut reader: impl Reader<'de>,
1054 dst: &mut MaybeUninit<Self::Dst>,
1055 ) -> ReadResult<()> {
1056 let bytes = reader.take_borrowed(len)?;
1057 match core::str::from_utf8(bytes) {
1058 Ok(s) => {
1059 dst.write(s);
1060 Ok(())
1061 }
1062 Err(e) => Err(invalid_utf8_encoding(e)),
1063 }
1064 }
1065}
1066
1067#[cfg(feature = "alloc")]
1068unsafe impl<'de, C: Config> SchemaRead<'de, C> for String {
1069 type Dst = String;
1070
1071 #[inline]
1072 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1073 let len = C::LengthEncoding::read_prealloc_check::<u8>(reader.by_ref())?;
1074 <String as SchemaReadContext<C, _>>::read_with_context(context::Len(len), reader, dst)
1075 }
1076}
1077
1078#[cfg(feature = "alloc")]
1079unsafe impl<'de, C: Config> SchemaReadContext<'de, C, context::Len> for String {
1080 type Dst = String;
1081
1082 #[inline]
1083 fn read_with_context(
1084 ctx: context::Len,
1085 reader: impl Reader<'de>,
1086 dst: &mut MaybeUninit<Self::Dst>,
1087 ) -> ReadResult<()> {
1088 let bytes = <Vec<u8> as SchemaReadContext<C, _>>::get_with_context(ctx, reader)?;
1089 match String::from_utf8(bytes) {
1090 Ok(s) => {
1091 dst.write(s);
1092 Ok(())
1093 }
1094 Err(e) => Err(invalid_utf8_encoding(e.utf8_error())),
1095 }
1096 }
1097}
1098
1099macro_rules! impl_seq_kv {
1105 ($feature: literal,
1106 $target: ident<$key: ident : $($constraint:path)|*, $value: ident $(, $state:ident : $($state_constraint:path)|* )?>,
1107 $with_capacity: expr) => {
1108 #[cfg(feature = $feature)]
1109 unsafe impl<C: $crate::config::Config, $key, $value $(, $state)?> $crate::schema::SchemaWrite<C> for $target<$key, $value $(, $state)?>
1110 where
1111 $key: $crate::schema::SchemaWrite<C>,
1112 $key::Src: Sized,
1113 $value: $crate::schema::SchemaWrite<C>,
1114 $value::Src: Sized
1115 $($(, $state: $state_constraint+)*)?
1116 {
1117 type Src = $target<$key::Src, $value::Src $(, $state)?>;
1118
1119 #[inline]
1120 #[allow(clippy::arithmetic_side_effects)]
1121 fn size_of(src: &Self::Src) -> $crate::error::WriteResult<usize> {
1122 if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1123 return Ok(C::LengthEncoding::write_bytes_needed(src.len())? + (key_size + value_size) * src.len());
1124 }
1125 Ok(C::LengthEncoding::write_bytes_needed(src.len())? +
1126 src
1127 .iter()
1128 .try_fold(
1129 0usize,
1130 |acc, (k, v)|
1131 Ok::<_, $crate::error::WriteError>(
1132 acc
1133 + $key::size_of(k)?
1134 + $value::size_of(v)?
1135 )
1136 )?
1137 )
1138 }
1139
1140 #[inline]
1141 fn write(mut writer: impl $crate::io::Writer, src: &Self::Src) -> $crate::error::WriteResult<()> {
1142 if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1143 let len = src.len();
1144 #[allow(clippy::arithmetic_side_effects)]
1145 let needed = C::LengthEncoding::write_bytes_needed_prealloc_check::<($key, $value)>(len)? + (key_size + value_size) * len;
1146 let mut writer = unsafe { writer.as_trusted_for(needed) }?;
1149 C::LengthEncoding::write(writer.by_ref(), len)?;
1150 for (k, v) in src.iter() {
1151 $key::write(writer.by_ref(), k)?;
1152 $value::write(writer.by_ref(), v)?;
1153 }
1154 writer.finish()?;
1155 return Ok(());
1156 }
1157 C::LengthEncoding::write(writer.by_ref(), src.len())?;
1158 for (k, v) in src.iter() {
1159 $key::write(writer.by_ref(), k)?;
1160 $value::write(writer.by_ref(), v)?;
1161 }
1162 Ok(())
1163 }
1164 }
1165
1166 #[cfg(feature = $feature)]
1167 unsafe impl<'de, C: $crate::config::Config, $key, $value $(, $state)?> $crate::schema::SchemaRead<'de, C> for $target<$key, $value $(, $state)?>
1168 where
1169 $key: $crate::schema::SchemaRead<'de, C>,
1170 $value: $crate::schema::SchemaRead<'de, C>
1171 $(,$key::Dst: $constraint+)*
1172 $($(, $state: $state_constraint+)* )?
1173 {
1174 type Dst = $target<$key::Dst, $value::Dst $(, $state)?>;
1175
1176 #[inline]
1177 fn read(mut reader: impl $crate::io::Reader<'de>, dst: &mut core::mem::MaybeUninit<Self::Dst>) -> $crate::error::ReadResult<()> {
1178 let len = C::LengthEncoding::read_prealloc_check::<($key::Dst, $value::Dst)>(reader.by_ref())?;
1179
1180 let map = if let ($crate::TypeMeta::Static { size: key_size, .. }, $crate::TypeMeta::Static { size: value_size, .. }) = ($key::TYPE_META, $value::TYPE_META) {
1181 let Some(el_size) = key_size.checked_add(value_size) else {
1184 return Err($crate::error::read_length_encoding_overflow("usize::MAX"));
1185 };
1186 let mut reader = unsafe { reader.as_trusted_for_seq(len, el_size) }?;
1187 let mut map = $with_capacity(len $(, $state::default())?);
1188 for _ in 0..len {
1189 let k = $key::get(reader.by_ref())?;
1190 let v = $value::get(reader.by_ref())?;
1191 map.insert(k, v);
1192 }
1193 map
1194 } else {
1195 let mut map = $with_capacity(len $(, $state::default())?);
1196 for _ in 0..len {
1197 let k = $key::get(reader.by_ref())?;
1198 let v = $value::get(reader.by_ref())?;
1199 map.insert(k, v);
1200 }
1201 map
1202 };
1203
1204 dst.write(map);
1205 Ok(())
1206 }
1207 }
1208 };
1209}
1210
1211pub(crate) use impl_seq_kv;
1212
1213macro_rules! impl_seq_v {
1214 ($feature: literal,
1215 $target: ident <$key: ident : $($constraint:path)|* $(, $state:ident : $($state_constraint:path)|*)?>,
1216 $with_capacity: expr, $insert: ident) => {
1217 #[cfg(feature = $feature)]
1218 unsafe impl<C: $crate::config::Config, $key: $crate::schema::SchemaWrite<C> $(, $state)?> $crate::schema::SchemaWrite<C> for $target<$key $(, $state)?>
1219 where
1220 $key::Src: Sized
1221 $($(, $state: $state_constraint+)* )?
1222 {
1223 type Src = $target<$key::Src $(, $state)?>;
1224
1225 #[inline]
1226 fn size_of(src: &Self::Src) -> $crate::error::WriteResult<usize> {
1227 $crate::schema::size_of_elem_iter::<$key, C::LengthEncoding, C>(src.iter())
1228 }
1229
1230 #[inline]
1231 fn write(writer: impl $crate::io::Writer, src: &Self::Src) -> $crate::error::WriteResult<()> {
1232 $crate::schema::write_elem_iter_prealloc_check::<$key, C::LengthEncoding, C>(writer, src.iter())
1233 }
1234 }
1235
1236 #[cfg(feature = $feature)]
1237 unsafe impl<'de, C: $crate::config::Config, $key $(, $state)?> $crate::schema::SchemaRead<'de, C> for $target<$key $(, $state)?>
1238 where
1239 $key: $crate::schema::SchemaRead<'de, C>
1240 $(,$key::Dst: $constraint+)*
1241 $($(, $state: $state_constraint+)* )?
1242 {
1243 type Dst = $target<$key::Dst $(, $state)?>;
1244
1245 #[inline]
1246 fn read(mut reader: impl $crate::io::Reader<'de>, dst: &mut core::mem::MaybeUninit<Self::Dst>) -> $crate::error::ReadResult<()> {
1247 let len = C::LengthEncoding::read_prealloc_check::<$key::Dst>(reader.by_ref())?;
1248
1249 let map = match $key::TYPE_META {
1250 $crate::TypeMeta::Static { size, .. } => {
1251 let mut reader = unsafe { reader.as_trusted_for_seq(len, size) }?;
1254 let mut set = $with_capacity(len $(, $state::default())?);
1255 for _ in 0..len {
1256 set.$insert($key::get(reader.by_ref())?);
1257 }
1258 set
1259 }
1260 $crate::TypeMeta::Dynamic => {
1261 let mut set = $with_capacity(len $(, $state::default())?);
1262 for _ in 0..len {
1263 set.$insert($key::get(reader.by_ref())?);
1264 }
1265 set
1266 }
1267 };
1268
1269 dst.write(map);
1270 Ok(())
1271 }
1272 }
1273 };
1274}
1275
1276pub(crate) use impl_seq_v;
1277
1278impl_seq_kv! { "alloc", BTreeMap<K: Ord, V>, |_| BTreeMap::new() }
1279impl_seq_kv! { "std", HashMap<K: Hash | Eq, V, S: BuildHasher | Default>, HashMap::with_capacity_and_hasher }
1280impl_seq_v! { "alloc", BTreeSet<K: Ord>, |_| BTreeSet::new(), insert }
1281impl_seq_v! { "std", HashSet<K: Hash | Eq, S: BuildHasher | Default>, HashSet::with_capacity_and_hasher, insert }
1282impl_seq_v! { "alloc", LinkedList<K:>, |_| LinkedList::new(), push_back }
1283
1284#[cfg(feature = "alloc")]
1285unsafe impl<T, C: Config> SchemaWrite<C> for BinaryHeap<T>
1286where
1287 T: SchemaWrite<C>,
1288 T::Src: Sized,
1289{
1290 type Src = BinaryHeap<T::Src>;
1291
1292 #[inline]
1293 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1294 <containers::BinaryHeap<T, C::LengthEncoding>>::size_of(src)
1295 }
1296
1297 #[inline]
1298 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1299 <containers::BinaryHeap<T, C::LengthEncoding>>::write(writer, src)
1300 }
1301}
1302
1303#[cfg(feature = "alloc")]
1304unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for BinaryHeap<T>
1305where
1306 T: SchemaRead<'de, C>,
1307 T::Dst: Ord,
1308{
1309 type Dst = BinaryHeap<T::Dst>;
1310
1311 #[inline]
1312 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1313 <containers::BinaryHeap<T, C::LengthEncoding>>::read(reader, dst)
1314 }
1315}
1316
1317mod zero_copy {
1318 use {
1319 super::*,
1320 core::slice::{from_raw_parts, from_raw_parts_mut},
1321 };
1322
1323 #[inline(always)]
1334 fn cast_ensure_aligned<C: ConfigCore, T, U>(ptr: *const T) -> ReadResult<*const U> {
1335 let ptr = ptr.cast::<U>();
1336
1337 if !C::ZERO_COPY_ALIGN_CHECK {
1338 return Ok(ptr);
1339 }
1340
1341 if align_of::<U>() > 1 && !ptr.is_aligned() {
1342 return Err(unaligned_pointer_read());
1343 }
1344 Ok(ptr)
1345 }
1346
1347 #[inline(always)]
1352 fn cast_ensure_aligned_mut<C: ConfigCore, T, U>(ptr: *mut T) -> ReadResult<*mut U> {
1353 let ptr = ptr.cast::<U>();
1354
1355 if !C::ZERO_COPY_ALIGN_CHECK {
1356 return Ok(ptr);
1357 }
1358
1359 if align_of::<U>() > 1 && !ptr.is_aligned() {
1360 return Err(unaligned_pointer_read());
1361 }
1362 Ok(ptr)
1363 }
1364
1365 #[inline(always)]
1377 pub(super) unsafe fn cast_slice_to_t<C: ConfigCore, T>(bytes: &[u8]) -> ReadResult<&T> {
1378 debug_assert_eq!(bytes.len(), size_of::<T>());
1379 let ptr = cast_ensure_aligned::<C, u8, T>(bytes.as_ptr())?;
1380 let val = unsafe { &*ptr };
1384 Ok(val)
1385 }
1386
1387 #[inline(always)]
1391 pub(super) unsafe fn cast_slice_to_t_mut<C: ConfigCore, T>(
1392 bytes: &mut [u8],
1393 ) -> ReadResult<&mut T> {
1394 debug_assert_eq!(bytes.len(), size_of::<T>());
1395 let ptr = cast_ensure_aligned_mut::<C, u8, T>(bytes.as_mut_ptr())?;
1396 let val = unsafe { &mut *ptr };
1400 Ok(val)
1401 }
1402
1403 #[inline(always)]
1415 pub(super) unsafe fn cast_slice_to_slice_t<C: ConfigCore, T>(
1416 bytes: &[u8],
1417 len: usize,
1418 ) -> ReadResult<&[T]> {
1419 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1420 let ptr = cast_ensure_aligned::<C, u8, T>(bytes.as_ptr())?;
1421 let slice = unsafe { from_raw_parts(ptr, len) };
1425 Ok(slice)
1426 }
1427
1428 #[inline(always)]
1432 pub(super) unsafe fn cast_slice_to_slice_t_mut<C: ConfigCore, T>(
1433 bytes: &mut [u8],
1434 len: usize,
1435 ) -> ReadResult<&mut [T]> {
1436 debug_assert_eq!(Some(bytes.len()), len.checked_mul(size_of::<T>()));
1437 let ptr = cast_ensure_aligned_mut::<C, u8, T>(bytes.as_mut_ptr())?;
1438 let slice = unsafe { from_raw_parts_mut(ptr, len) };
1442 Ok(slice)
1443 }
1444
1445 pub(super) const fn type_meta_t<'de, T, C: ConfigCore>() -> TypeMeta
1447 where
1448 T: SchemaRead<'de, C> + ZeroCopy<C>,
1449 {
1450 match T::TYPE_META {
1451 TypeMeta::Static {
1452 size,
1453 zero_copy: true,
1454 } => TypeMeta::Static {
1455 size,
1456 zero_copy: false,
1473 },
1474 _ => panic!("Type is not zero-copy"),
1476 }
1477 }
1478
1479 pub(super) const fn type_meta_slice<'de, T, C: ConfigCore>() -> TypeMeta
1485 where
1486 T: SchemaRead<'de, C> + ZeroCopy<C>,
1487 {
1488 match T::TYPE_META {
1489 TypeMeta::Static {
1490 zero_copy: true, ..
1491 } => TypeMeta::Dynamic,
1492 _ => panic!("Type is not zero-copy"),
1493 }
1494 }
1495
1496 #[inline(always)]
1502 pub(super) fn read_slice_len_checked<'de, C: Config>(
1503 reader: impl Reader<'de>,
1504 size: usize,
1505 ) -> ReadResult<(usize, usize)> {
1506 let len = C::LengthEncoding::read(reader)?;
1507 let Some(total_size) = len.checked_mul(size) else {
1508 return Err(read_length_encoding_overflow("usize::MAX"));
1509 };
1510 Ok((len, total_size))
1511 }
1512}
1513
1514unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for &'de T
1515where
1516 T: SchemaRead<'de, C> + ZeroCopy<C>,
1517{
1518 type Dst = &'de T::Dst;
1519
1520 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T, C>();
1521
1522 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1523 let size = T::TYPE_META.size_assert_zero_copy();
1524 let bytes = reader.take_borrowed(size)?;
1525 let val = unsafe { zero_copy::cast_slice_to_t::<C, T::Dst>(bytes)? };
1529 dst.write(val);
1530 Ok(())
1531 }
1532}
1533
1534unsafe impl<'de, T, C: ConfigCore> SchemaRead<'de, C> for &'de mut T
1535where
1536 T: SchemaRead<'de, C> + ZeroCopy<C>,
1537{
1538 type Dst = &'de mut T::Dst;
1539
1540 const TYPE_META: TypeMeta = zero_copy::type_meta_t::<T, C>();
1541
1542 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1543 let size = T::TYPE_META.size_assert_zero_copy();
1544 let bytes = reader.take_borrowed_mut(size)?;
1545 let val = unsafe { zero_copy::cast_slice_to_t_mut::<C, T::Dst>(bytes)? };
1549 dst.write(val);
1550 Ok(())
1551 }
1552}
1553
1554unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for &'de [T]
1555where
1556 T: SchemaRead<'de, C> + ZeroCopy<C>,
1557{
1558 type Dst = &'de [T::Dst];
1559
1560 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1561
1562 #[inline]
1563 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1564 let len = C::LengthEncoding::read(reader.by_ref())?;
1565 <&[T]>::read_with_context(context::Len(len), reader, dst)?;
1566 Ok(())
1567 }
1568}
1569
1570unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for &'de [T]
1571where
1572 T: SchemaRead<'de, C> + ZeroCopy<C>,
1573{
1574 type Dst = &'de [T::Dst];
1575
1576 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1577
1578 #[inline]
1579 fn read_with_context(
1580 context::Len(len): context::Len,
1581 mut reader: impl Reader<'de>,
1582 dst: &mut MaybeUninit<Self::Dst>,
1583 ) -> ReadResult<()> {
1584 let size = T::TYPE_META.size_assert_zero_copy();
1585 let Some(total_size) = len.checked_mul(size) else {
1586 return Err(read_length_encoding_overflow("usize::MAX"));
1587 };
1588 let bytes = reader.take_borrowed(total_size)?;
1589 let slice = unsafe { zero_copy::cast_slice_to_slice_t::<C, T::Dst>(bytes, len)? };
1593 dst.write(slice);
1594 Ok(())
1595 }
1596}
1597
1598unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for &'de mut [T]
1599where
1600 T: SchemaRead<'de, C> + ZeroCopy<C>,
1601{
1602 type Dst = &'de mut [T::Dst];
1603
1604 const TYPE_META: TypeMeta = zero_copy::type_meta_slice::<T, C>();
1605
1606 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1607 let size = T::TYPE_META.size_assert_zero_copy();
1608 let (len, total_size) = zero_copy::read_slice_len_checked::<C>(reader.by_ref(), size)?;
1609 let bytes = reader.take_borrowed_mut(total_size)?;
1610 let slice = unsafe { zero_copy::cast_slice_to_slice_t_mut::<C, T::Dst>(bytes, len)? };
1614 dst.write(slice);
1615 Ok(())
1616 }
1617}
1618
1619unsafe impl<C: ConfigCore> SchemaWrite<C> for Duration {
1620 type Src = Duration;
1621
1622 const TYPE_META: TypeMeta = match (
1623 <u64 as SchemaWrite<C>>::TYPE_META,
1624 <u32 as SchemaWrite<C>>::TYPE_META,
1625 ) {
1626 (TypeMeta::Static { size: u64_size, .. }, TypeMeta::Static { size: u32_size, .. }) => {
1628 TypeMeta::Static {
1629 size: u64_size + u32_size,
1630 zero_copy: false,
1631 }
1632 }
1633 _ => TypeMeta::Dynamic,
1634 };
1635
1636 #[inline]
1637 #[allow(clippy::arithmetic_side_effects)]
1638 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1639 match <Self as SchemaWrite<C>>::TYPE_META {
1640 TypeMeta::Static { size, .. } => Ok(size),
1641 TypeMeta::Dynamic => {
1642 let secs = <u64 as SchemaWrite<C>>::size_of(&src.as_secs())?;
1643 let nanos = <u32 as SchemaWrite<C>>::size_of(&src.subsec_nanos())?;
1644 Ok(secs + nanos)
1645 }
1646 }
1647 }
1648
1649 #[inline]
1650 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1651 <u64 as SchemaWrite<C>>::write(writer.by_ref(), &src.as_secs())?;
1652 <u32 as SchemaWrite<C>>::write(writer, &src.subsec_nanos())?;
1653 Ok(())
1654 }
1655}
1656
1657unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Duration {
1658 type Dst = Duration;
1659
1660 const TYPE_META: TypeMeta = <Duration as SchemaWrite<C>>::TYPE_META;
1661
1662 #[inline]
1663 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1664 let secs = <u64 as SchemaRead<'de, C>>::get(reader.by_ref())?;
1665 let nanos = <u32 as SchemaRead<'de, C>>::get(reader)?;
1666 if secs.checked_add(u64::from(nanos) / 1_000_000_000).is_none() {
1667 return Err(invalid_value("Duration overflow"));
1668 }
1669 dst.write(Duration::new(secs, nanos));
1670 Ok(())
1671 }
1672}
1673
1674#[cfg(feature = "std")]
1675unsafe impl<C: ConfigCore> SchemaWrite<C> for SystemTime {
1676 type Src = SystemTime;
1677
1678 const TYPE_META: TypeMeta = <Duration as SchemaWrite<C>>::TYPE_META;
1679
1680 #[inline]
1681 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1682 match <Self as SchemaWrite<C>>::TYPE_META {
1683 TypeMeta::Static { size, .. } => Ok(size),
1684 TypeMeta::Dynamic => {
1685 let duration = src.duration_since(UNIX_EPOCH).map_err(|_| {
1686 crate::error::WriteError::Custom("SystemTime before UNIX_EPOCH")
1687 })?;
1688 <Duration as SchemaWrite<C>>::size_of(&duration)
1689 }
1690 }
1691 }
1692
1693 #[inline]
1694 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1695 let duration = src
1696 .duration_since(UNIX_EPOCH)
1697 .map_err(|_| crate::error::WriteError::Custom("SystemTime before UNIX_EPOCH"))?;
1698 <Duration as SchemaWrite<C>>::write(writer, &duration)?;
1699 Ok(())
1700 }
1701}
1702
1703#[cfg(feature = "std")]
1704unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SystemTime {
1705 type Dst = SystemTime;
1706
1707 const TYPE_META: TypeMeta = <Duration as SchemaRead<'de, C>>::TYPE_META;
1708
1709 #[inline]
1710 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1711 let duration = <Duration as SchemaRead<'de, C>>::get(reader)?;
1712 let system_time = UNIX_EPOCH
1713 .checked_add(duration)
1714 .ok_or_else(|| invalid_value("SystemTime overflow"))?;
1715 dst.write(system_time);
1716 Ok(())
1717 }
1718}
1719
1720unsafe impl<C: ConfigCore> SchemaWrite<C> for Ipv4Addr {
1721 type Src = Ipv4Addr;
1722
1723 const TYPE_META: TypeMeta = TypeMeta::Static {
1724 size: 4,
1725 zero_copy: false,
1726 };
1727
1728 #[inline]
1729 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
1730 Ok(4)
1731 }
1732
1733 #[inline]
1734 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1735 writer.write(&src.octets())?;
1736 Ok(())
1737 }
1738}
1739
1740unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Ipv4Addr {
1741 type Dst = Ipv4Addr;
1742
1743 const TYPE_META: TypeMeta = TypeMeta::Static {
1744 size: 4,
1745 zero_copy: false,
1746 };
1747
1748 #[inline]
1749 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1750 let bytes = reader.take_array::<4>()?;
1751 dst.write(Ipv4Addr::from(bytes));
1752 Ok(())
1753 }
1754}
1755
1756unsafe impl<C: ConfigCore> SchemaWrite<C> for Ipv6Addr {
1757 type Src = Ipv6Addr;
1758
1759 const TYPE_META: TypeMeta = TypeMeta::Static {
1760 size: 16,
1761 zero_copy: false,
1762 };
1763
1764 #[inline]
1765 fn size_of(_src: &Self::Src) -> WriteResult<usize> {
1766 Ok(16)
1767 }
1768
1769 #[inline]
1770 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1771 writer.write(&src.octets())?;
1772 Ok(())
1773 }
1774}
1775
1776unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for Ipv6Addr {
1777 type Dst = Ipv6Addr;
1778
1779 const TYPE_META: TypeMeta = TypeMeta::Static {
1780 size: 16,
1781 zero_copy: false,
1782 };
1783
1784 #[inline]
1785 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1786 let bytes = reader.take_array::<16>()?;
1787 dst.write(Ipv6Addr::from(bytes));
1788 Ok(())
1789 }
1790}
1791
1792unsafe impl<C: Config> SchemaWrite<C> for IpAddr {
1793 type Src = IpAddr;
1794
1795 #[inline]
1796 #[allow(clippy::arithmetic_side_effects)]
1797 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1798 Ok(match src {
1799 IpAddr::V4(_) => C::TagEncoding::size_of_from_u32(0)? + 4,
1800 IpAddr::V6(_) => C::TagEncoding::size_of_from_u32(1)? + 16,
1801 })
1802 }
1803
1804 #[inline]
1805 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1806 match src {
1807 IpAddr::V4(addr) => {
1808 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
1809 <Ipv4Addr as SchemaWrite<C>>::write(writer, addr)
1810 }
1811 IpAddr::V6(addr) => {
1812 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
1813 <Ipv6Addr as SchemaWrite<C>>::write(writer, addr)
1814 }
1815 }
1816 }
1817}
1818
1819unsafe impl<'de, C: Config> SchemaRead<'de, C> for IpAddr {
1820 type Dst = IpAddr;
1821
1822 #[inline]
1823 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1824 let tag = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
1825 match tag {
1826 0 => {
1827 let addr = <Ipv4Addr as SchemaRead<'de, C>>::get(reader)?;
1828 dst.write(IpAddr::V4(addr));
1829 Ok(())
1830 }
1831 1 => {
1832 let addr = <Ipv6Addr as SchemaRead<'de, C>>::get(reader)?;
1833 dst.write(IpAddr::V6(addr));
1834 Ok(())
1835 }
1836 _ => Err(invalid_tag_encoding(tag as usize)),
1837 }
1838 }
1839}
1840
1841unsafe impl<C: ConfigCore> SchemaWrite<C> for SocketAddrV4 {
1842 type Src = Self;
1843
1844 const TYPE_META: TypeMeta = TypeMeta::join_types([
1845 <Ipv4Addr as SchemaWrite<C>>::TYPE_META,
1846 <u16 as SchemaWrite<C>>::TYPE_META,
1847 ]);
1848
1849 #[inline]
1850 #[allow(clippy::arithmetic_side_effects)]
1851 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1852 Ok(4 + <u16 as SchemaWrite<C>>::size_of(&src.port())?)
1853 }
1854
1855 #[inline]
1856 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1857 <Ipv4Addr as SchemaWrite<C>>::write(writer.by_ref(), src.ip())?;
1858 <u16 as SchemaWrite<C>>::write(writer, &src.port())
1859 }
1860}
1861
1862unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SocketAddrV4 {
1863 type Dst = Self;
1864
1865 const TYPE_META: TypeMeta = TypeMeta::join_types([
1866 <Ipv4Addr as SchemaRead<C>>::TYPE_META,
1867 <u16 as SchemaRead<C>>::TYPE_META,
1868 ]);
1869
1870 #[inline]
1871 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1872 let ip = <Ipv4Addr as SchemaRead<'de, C>>::get(reader.by_ref())?;
1873 let port = <u16 as SchemaRead<'de, C>>::get(reader)?;
1874 dst.write(Self::Dst::new(ip, port));
1875 Ok(())
1876 }
1877}
1878
1879unsafe impl<C: ConfigCore> SchemaWrite<C> for SocketAddrV6 {
1880 type Src = Self;
1881
1882 const TYPE_META: TypeMeta = TypeMeta::join_types([
1883 <Ipv6Addr as SchemaWrite<C>>::TYPE_META,
1884 <u16 as SchemaWrite<C>>::TYPE_META,
1885 ]);
1886
1887 #[inline]
1888 #[allow(clippy::arithmetic_side_effects)]
1889 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1890 Ok(16 + <u16 as SchemaWrite<C>>::size_of(&src.port())?)
1891 }
1892
1893 #[inline]
1894 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1895 <Ipv6Addr as SchemaWrite<C>>::write(writer.by_ref(), src.ip())?;
1896 <u16 as SchemaWrite<C>>::write(writer, &src.port())
1897 }
1898}
1899
1900unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for SocketAddrV6 {
1901 type Dst = Self;
1902
1903 const TYPE_META: TypeMeta = TypeMeta::join_types([
1904 <Ipv6Addr as SchemaRead<C>>::TYPE_META,
1905 <u16 as SchemaRead<C>>::TYPE_META,
1906 ]);
1907
1908 #[inline]
1909 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1910 let ip = <Ipv6Addr as SchemaRead<'de, C>>::get(reader.by_ref())?;
1911 let port = <u16 as SchemaRead<'de, C>>::get(reader)?;
1912 dst.write(SocketAddrV6::new(ip, port, 0, 0));
1914 Ok(())
1915 }
1916}
1917
1918unsafe impl<C: Config> SchemaWrite<C> for SocketAddr {
1919 type Src = Self;
1920
1921 #[inline]
1922 #[allow(clippy::arithmetic_side_effects)]
1923 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1924 Ok(match src {
1925 Self::V4(v4) => {
1926 C::TagEncoding::size_of_from_u32(0)?
1927 + <SocketAddrV4 as SchemaWrite<C>>::size_of(v4)?
1928 }
1929 Self::V6(v6) => {
1930 C::TagEncoding::size_of_from_u32(1)?
1931 + <SocketAddrV6 as SchemaWrite<C>>::size_of(v6)?
1932 }
1933 })
1934 }
1935
1936 #[inline]
1937 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1938 match src {
1939 Self::V4(addr) => {
1940 C::TagEncoding::write_from_u32(writer.by_ref(), 0)?;
1941 <SocketAddrV4 as SchemaWrite<C>>::write(writer, addr)
1942 }
1943 Self::V6(addr) => {
1944 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
1945 <SocketAddrV6 as SchemaWrite<C>>::write(writer, addr)
1946 }
1947 }
1948 }
1949}
1950
1951unsafe impl<'de, C: Config> SchemaRead<'de, C> for SocketAddr {
1952 type Dst = Self;
1953
1954 #[inline]
1955 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
1956 let tag = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
1957 match tag {
1958 0 => {
1959 let addr = <SocketAddrV4 as SchemaRead<'de, C>>::get(reader)?;
1960 dst.write(Self::V4(addr));
1961 Ok(())
1962 }
1963 1 => {
1964 let addr = <SocketAddrV6 as SchemaRead<'de, C>>::get(reader)?;
1965 dst.write(Self::V6(addr));
1966 Ok(())
1967 }
1968 _ => Err(invalid_tag_encoding(tag as usize)),
1969 }
1970 }
1971}
1972
1973macro_rules! impl_nonzero {
1974 ($($nonzero_ty:ty => $primitive_ty:ty),* $(,)?) => {
1975 $(
1976 unsafe impl<C: ConfigCore> SchemaWrite<C> for $nonzero_ty {
1977 type Src = $nonzero_ty;
1978
1979 const TYPE_META: TypeMeta = <$primitive_ty as SchemaWrite<C>>::TYPE_META;
1980
1981 #[inline(always)]
1982 fn size_of(src: &Self::Src) -> WriteResult<usize> {
1983 <$primitive_ty as SchemaWrite<C>>::size_of(&src.get())
1984 }
1985
1986 #[inline(always)]
1987 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
1988 <$primitive_ty as SchemaWrite<C>>::write(writer, &src.get())
1989 }
1990 }
1991
1992 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for $nonzero_ty {
1993 type Dst = $nonzero_ty;
1994
1995 const TYPE_META: TypeMeta = const {
1996 match <$primitive_ty as SchemaRead<'de, C>>::TYPE_META {
1997 TypeMeta::Static { size, .. } => TypeMeta::Static {
1998 size,
1999 zero_copy: false,
2000 },
2001 TypeMeta::Dynamic => TypeMeta::Dynamic,
2002 }
2003 };
2004
2005 #[inline(always)]
2006 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2007 let val = <$primitive_ty as SchemaRead<'de, C>>::get(reader)?;
2008 let nonzero = <$nonzero_ty>::new(val)
2009 .ok_or_else(|| invalid_value(concat!(
2010 "NonZero value cannot be zero for type ",
2011 stringify!($nonzero_ty)
2012 )))?;
2013 dst.write(nonzero);
2014 Ok(())
2015 }
2016 }
2017 )*
2018 };
2019}
2020
2021impl_nonzero!(
2022 NonZeroU8 => u8,
2023 NonZeroU16 => u16,
2024 NonZeroU32 => u32,
2025 NonZeroU64 => u64,
2026 NonZeroU128 => u128,
2027 NonZeroUsize => usize,
2028 NonZeroI8 => i8,
2029 NonZeroI16 => i16,
2030 NonZeroI32 => i32,
2031 NonZeroI64 => i64,
2032 NonZeroI128 => i128,
2033 NonZeroIsize => isize,
2034);
2035
2036unsafe impl<C: Config, T> SchemaWrite<C> for Bound<T>
2037where
2038 T: SchemaWrite<C>,
2039 T::Src: Sized,
2040{
2041 type Src = Bound<T::Src>;
2042
2043 #[inline]
2044 #[allow(clippy::arithmetic_side_effects)]
2045 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2046 match src {
2047 Bound::Unbounded => C::TagEncoding::size_of_from_u32(0),
2048 Bound::Included(value) => Ok(C::TagEncoding::size_of_from_u32(1)? + T::size_of(value)?),
2049 Bound::Excluded(value) => Ok(C::TagEncoding::size_of_from_u32(2)? + T::size_of(value)?),
2050 }
2051 }
2052
2053 #[inline]
2054 fn write(mut writer: impl Writer, value: &Self::Src) -> WriteResult<()> {
2055 match value {
2056 Bound::Unbounded => C::TagEncoding::write_from_u32(writer.by_ref(), 0),
2057 Bound::Included(value) => {
2058 C::TagEncoding::write_from_u32(writer.by_ref(), 1)?;
2059 T::write(writer, value)
2060 }
2061 Bound::Excluded(value) => {
2062 C::TagEncoding::write_from_u32(writer.by_ref(), 2)?;
2063 T::write(writer, value)
2064 }
2065 }
2066 }
2067}
2068
2069unsafe impl<'de, T, C: Config> SchemaRead<'de, C> for Bound<T>
2070where
2071 T: SchemaRead<'de, C>,
2072{
2073 type Dst = Bound<T::Dst>;
2074
2075 #[inline]
2076 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2077 let disc = C::TagEncoding::try_into_u32(C::TagEncoding::get(reader.by_ref())?)?;
2078 match disc {
2079 0 => dst.write(Bound::Unbounded),
2080 1 => dst.write(Bound::Included(T::get(reader.by_ref())?)),
2081 2 => dst.write(Bound::Excluded(T::get(reader.by_ref())?)),
2082 _ => return Err(invalid_tag_encoding(disc as usize)),
2083 };
2084
2085 Ok(())
2086 }
2087}
2088
2089unsafe impl<Idx, C: Config> SchemaWrite<C> for Range<Idx>
2090where
2091 Idx: SchemaWrite<C>,
2092 Idx::Src: Sized,
2093{
2094 type Src = Range<Idx::Src>;
2095
2096 const TYPE_META: TypeMeta = const {
2097 match Idx::TYPE_META {
2098 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2099 size: idx_size + idx_size,
2100 zero_copy: false,
2101 },
2102 TypeMeta::Dynamic => TypeMeta::Dynamic,
2103 }
2104 };
2105
2106 #[inline]
2107 #[allow(clippy::arithmetic_side_effects)]
2108 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2109 Ok(Idx::size_of(&src.start)? + Idx::size_of(&src.end)?)
2110 }
2111
2112 #[inline]
2113 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2114 match Self::TYPE_META {
2115 TypeMeta::Static { size, .. } => {
2116 let mut writer = unsafe { writer.as_trusted_for(size) }?;
2119 Idx::write(writer.by_ref(), &src.start)?;
2120 Idx::write(writer.by_ref(), &src.end)?;
2121 writer.finish()?;
2122 }
2123 TypeMeta::Dynamic => {
2124 Idx::write(writer.by_ref(), &src.start)?;
2125 Idx::write(writer.by_ref(), &src.end)?;
2126 }
2127 }
2128 Ok(())
2129 }
2130}
2131
2132unsafe impl<'de, Idx, C: ConfigCore> SchemaRead<'de, C> for Range<Idx>
2133where
2134 Idx: SchemaRead<'de, C>,
2135{
2136 type Dst = Range<Idx::Dst>;
2137
2138 const TYPE_META: TypeMeta = const {
2139 match Idx::TYPE_META {
2140 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2141 size: idx_size + idx_size,
2142 zero_copy: false,
2143 },
2144 TypeMeta::Dynamic => TypeMeta::Dynamic,
2145 }
2146 };
2147
2148 #[inline]
2149 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2150 match Self::TYPE_META {
2151 TypeMeta::Static { size, .. } => {
2152 let mut reader = unsafe { reader.as_trusted_for(size) }?;
2155 let start = Idx::get(reader.by_ref())?;
2156 let end = Idx::get(reader.by_ref())?;
2157 dst.write(Range { start, end });
2158 }
2159 TypeMeta::Dynamic => {
2160 let start = Idx::get(reader.by_ref())?;
2161 let end = Idx::get(reader.by_ref())?;
2162 dst.write(Range { start, end });
2163 }
2164 };
2165
2166 Ok(())
2167 }
2168}
2169
2170unsafe impl<Idx, C: ConfigCore> SchemaWrite<C> for RangeInclusive<Idx>
2171where
2172 Idx: SchemaWrite<C>,
2173 Idx::Src: Sized,
2174{
2175 type Src = RangeInclusive<Idx::Src>;
2176
2177 const TYPE_META: TypeMeta = const {
2178 match Idx::TYPE_META {
2179 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2180 size: idx_size + idx_size,
2181 zero_copy: false,
2182 },
2183 TypeMeta::Dynamic => TypeMeta::Dynamic,
2184 }
2185 };
2186
2187 #[inline]
2188 #[allow(clippy::arithmetic_side_effects)]
2189 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2190 if let TypeMeta::Static { size, .. } = Self::TYPE_META {
2191 return Ok(size);
2192 }
2193 Ok(Idx::size_of(src.start())? + Idx::size_of(src.end())?)
2194 }
2195
2196 #[inline]
2197 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2198 match Self::TYPE_META {
2199 TypeMeta::Static { size, .. } => {
2200 let mut writer = unsafe { writer.as_trusted_for(size) }?;
2203 Idx::write(writer.by_ref(), src.start())?;
2204 Idx::write(writer.by_ref(), src.end())?;
2205 writer.finish()?;
2206 }
2207 TypeMeta::Dynamic => {
2208 Idx::write(writer.by_ref(), src.start())?;
2209 Idx::write(writer.by_ref(), src.end())?;
2210 }
2211 }
2212 Ok(())
2213 }
2214}
2215
2216unsafe impl<'de, Idx, C: ConfigCore> SchemaRead<'de, C> for RangeInclusive<Idx>
2217where
2218 Idx: SchemaRead<'de, C>,
2219{
2220 type Dst = RangeInclusive<Idx::Dst>;
2221
2222 const TYPE_META: TypeMeta = const {
2223 match Idx::TYPE_META {
2224 TypeMeta::Static { size: idx_size, .. } => TypeMeta::Static {
2225 size: idx_size + idx_size,
2226 zero_copy: false,
2227 },
2228 TypeMeta::Dynamic => TypeMeta::Dynamic,
2229 }
2230 };
2231
2232 #[inline]
2233 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2234 match Self::TYPE_META {
2235 TypeMeta::Static { size, .. } => {
2236 let mut reader = unsafe { reader.as_trusted_for(size) }?;
2239 let start = Idx::get(reader.by_ref())?;
2240 let end = Idx::get(reader.by_ref())?;
2241 dst.write(RangeInclusive::new(start, end));
2242 }
2243 TypeMeta::Dynamic => {
2244 let start = Idx::get(reader.by_ref())?;
2245 let end = Idx::get(reader.by_ref())?;
2246 dst.write(RangeInclusive::new(start, end));
2247 }
2248 };
2249 Ok(())
2250 }
2251}
2252
2253#[cfg(feature = "alloc")]
2254unsafe impl<T: ?Sized, C: ConfigCore> SchemaWrite<C> for Cow<'_, T>
2255where
2256 T: ToOwned,
2257 T: SchemaWrite<C, Src = T>,
2258{
2259 type Src = Self;
2260
2261 #[inline]
2262 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2263 T::size_of(src.as_ref())
2264 }
2265
2266 #[inline]
2267 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2268 T::write(writer, src.as_ref())
2269 }
2270}
2271
2272#[cfg(feature = "alloc")]
2273unsafe impl<'de, T: ?Sized, C: ConfigCore> SchemaRead<'de, C> for Cow<'de, T>
2274where
2275 T: ToOwned,
2276 &'de T: SchemaRead<'de, C, Dst = &'de T>,
2277 T::Owned: SchemaRead<'de, C, Dst = T::Owned>,
2278{
2279 type Dst = Self;
2280
2281 #[inline]
2282 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2283 let cow = if reader.supports_borrow(BorrowKind::Backing) {
2284 Cow::Borrowed(<&T as SchemaRead<C>>::get(reader)?)
2285 } else {
2286 Cow::Owned(<T::Owned as SchemaRead<C>>::get(reader)?)
2287 };
2288 dst.write(cow);
2289 Ok(())
2290 }
2291}
2292
2293#[cfg(feature = "alloc")]
2294unsafe impl<'de, T, C: ConfigCore> SchemaReadContext<'de, C, context::Len> for Cow<'de, [T]>
2295where
2296 [T]: ToOwned,
2297 &'de [T]: SchemaReadContext<'de, C, context::Len, Dst = &'de [T]>,
2298 <[T] as ToOwned>::Owned: SchemaReadContext<'de, C, context::Len, Dst = <[T] as ToOwned>::Owned>,
2299{
2300 type Dst = Self;
2301
2302 #[inline]
2303 fn read_with_context(
2304 ctx: context::Len,
2305 reader: impl Reader<'de>,
2306 dst: &mut MaybeUninit<Self::Dst>,
2307 ) -> ReadResult<()> {
2308 let cow = if reader.supports_borrow(BorrowKind::Backing) {
2309 Cow::Borrowed(<&[T]>::get_with_context(ctx, reader)?)
2310 } else {
2311 Cow::Owned(<<[T] as ToOwned>::Owned>::get_with_context(ctx, reader)?)
2312 };
2313 dst.write(cow);
2314 Ok(())
2315 }
2316}
2317
2318unsafe impl<C: ConfigCore, T> SchemaWrite<C> for Cell<T>
2319where
2320 T: SchemaWrite<C>,
2321 T::Src: Copy,
2322{
2323 type Src = Cell<T::Src>;
2324
2325 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2326
2327 #[inline]
2328 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2329 T::size_of(&src.get())
2330 }
2331
2332 #[inline]
2333 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2334 T::write(writer, &src.get())
2335 }
2336}
2337
2338unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for Cell<T>
2339where
2340 T: SchemaRead<'de, C>,
2341{
2342 type Dst = Cell<T::Dst>;
2343
2344 const TYPE_META: TypeMeta = T::TYPE_META;
2345
2346 #[inline]
2347 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2348 dst.write(T::get(reader).map(Self::Dst::new)?);
2349 Ok(())
2350 }
2351}
2352
2353unsafe impl<C: ConfigCore, T> SchemaWrite<C> for RefCell<T>
2354where
2355 T: SchemaWrite<C> + ?Sized,
2356{
2357 type Src = RefCell<T::Src>;
2358
2359 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2360
2361 #[inline]
2362 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2363 let val = src
2364 .try_borrow()
2365 .map_err(|_| WriteError::Custom("RefCell already mutably borrowed"))?;
2366 T::size_of(&*val)
2367 }
2368
2369 #[inline]
2370 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2371 let val = src
2372 .try_borrow()
2373 .map_err(|_| WriteError::Custom("RefCell already mutably borrowed"))?;
2374 T::write(writer, &*val)
2375 }
2376}
2377
2378unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for RefCell<T>
2379where
2380 T: SchemaRead<'de, C> + ?Sized,
2381{
2382 type Dst = RefCell<T::Dst>;
2383
2384 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2385
2386 #[inline]
2387 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2388 dst.write(T::get(reader).map(Self::Dst::new)?);
2389 Ok(())
2390 }
2391}
2392
2393#[cfg(feature = "std")]
2394unsafe impl<C: ConfigCore, T> SchemaWrite<C> for Mutex<T>
2395where
2396 T: SchemaWrite<C> + ?Sized,
2397{
2398 type Src = Mutex<T::Src>;
2399
2400 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2401
2402 #[inline]
2403 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2404 let val = src
2405 .lock()
2406 .map_err(|_| WriteError::Custom("Mutex poisoned"))?;
2407 T::size_of(&*val)
2408 }
2409
2410 #[inline]
2411 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2412 let val = src
2413 .lock()
2414 .map_err(|_| WriteError::Custom("Mutex poisoned"))?;
2415 T::write(writer, &*val)
2416 }
2417}
2418
2419#[cfg(feature = "std")]
2420unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for Mutex<T>
2421where
2422 T: SchemaRead<'de, C> + ?Sized,
2423{
2424 type Dst = Mutex<T::Dst>;
2425
2426 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2427
2428 #[inline]
2429 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2430 dst.write(T::get(reader).map(Self::Dst::new)?);
2431 Ok(())
2432 }
2433}
2434
2435#[cfg(feature = "std")]
2436unsafe impl<C: ConfigCore, T> SchemaWrite<C> for RwLock<T>
2437where
2438 T: SchemaWrite<C> + ?Sized,
2439{
2440 type Src = RwLock<T::Src>;
2441
2442 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2443
2444 #[inline]
2445 fn size_of(src: &Self::Src) -> WriteResult<usize> {
2446 let val = src
2447 .read()
2448 .map_err(|_| WriteError::Custom("RwLock poisoned"))?;
2449 T::size_of(&*val)
2450 }
2451
2452 #[inline]
2453 fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
2454 let val = src
2455 .read()
2456 .map_err(|_| WriteError::Custom("RwLock poisoned"))?;
2457 T::write(writer, &*val)
2458 }
2459}
2460
2461#[cfg(feature = "std")]
2462unsafe impl<'de, C: ConfigCore, T> SchemaRead<'de, C> for RwLock<T>
2463where
2464 T: SchemaRead<'de, C> + ?Sized,
2465{
2466 type Dst = RwLock<T::Dst>;
2467
2468 const TYPE_META: TypeMeta = T::TYPE_META.keep_zero_copy(false);
2469
2470 #[inline]
2471 fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
2472 dst.write(T::get(reader).map(Self::Dst::new)?);
2473 Ok(())
2474 }
2475}