1#[doc(hidden)]
23pub use self::internal::*;
24use core::marker::PhantomData;
25
26#[derive(Copy, Clone, Debug)]
43pub struct Configuration<
44 E = LittleEndian,
45 I = Varint,
46 L = NoLimit,
47 B = SkipBitPacking,
48 O = LsbFirst,
49 F = FingerprintDisabled,
50 FO = BincodeFormat,
51> {
52 _e: PhantomData<E>,
53 _i: PhantomData<I>,
54 _l: PhantomData<L>,
55 _b: PhantomData<B>,
56 _o: PhantomData<O>,
57 _f: PhantomData<F>,
58 _fo: PhantomData<FO>,
59}
60
61#[derive(Copy, Clone, Debug, PartialEq, Eq)]
63#[repr(u8)]
64pub enum CborDeterministicMode {
65 None = 0,
67 Core = 1,
69 LengthFirst = 2,
71}
72
73#[allow(clippy::struct_excessive_bools)]
75#[derive(Copy, Clone, Debug, PartialEq, Eq)]
76pub struct CborOptions {
77 pub deterministic_mode: CborDeterministicMode,
79 pub preferred_float: bool,
81 pub canonical_nan: bool,
83 pub normalize_neg_zero: bool,
85 pub allow_indefinite: bool,
87 pub strict_tags: bool,
89}
90
91impl CborOptions {
92 pub const DEFAULT: Self = Self {
94 deterministic_mode: CborDeterministicMode::None,
95 preferred_float: true,
96 canonical_nan: true,
97 normalize_neg_zero: false,
98 allow_indefinite: true,
99 strict_tags: false,
100 };
101 pub const DETERMINISTIC: Self = Self {
103 deterministic_mode: CborDeterministicMode::Core,
104 preferred_float: true,
105 canonical_nan: true,
106 normalize_neg_zero: false, allow_indefinite: false,
108 strict_tags: true,
109 };
110}
111
112#[must_use]
126pub const fn standard() -> Configuration {
127 generate()
128}
129
130#[must_use]
134pub const fn legacy() -> Configuration<
135 LittleEndian,
136 Fixint,
137 NoLimit,
138 SkipBitPacking,
139 LsbFirst,
140 FingerprintDisabled,
141 BincodeLegacyFormat,
142> {
143 generate()
144}
145
146impl<E, I, L, B, O, F, FO> Default for Configuration<E, I, L, B, O, F, FO> {
147 fn default() -> Self {
148 generate()
149 }
150}
151
152const fn generate<E, I, L, B, O, F, FO>() -> Configuration<E, I, L, B, O, F, FO> {
153 Configuration {
154 _e: PhantomData,
155 _i: PhantomData,
156 _l: PhantomData,
157 _b: PhantomData,
158 _o: PhantomData,
159 _f: PhantomData,
160 _fo: PhantomData,
161 }
162}
163
164impl<E, I, L, B, O, F, FO> Configuration<E, I, L, B, O, F, FO> {
165 #[must_use]
167 pub const fn with_big_endian(self) -> Configuration<BigEndian, I, L, B, MsbFirst, F, FO> {
168 generate()
169 }
170
171 #[must_use]
173 pub const fn with_little_endian(self) -> Configuration<LittleEndian, I, L, B, LsbFirst, F, FO> {
174 generate()
175 }
176
177 #[must_use]
234 pub const fn with_variable_int_encoding(self) -> Configuration<E, Varint, L, B, O, F, FO> {
235 generate()
236 }
237
238 #[must_use]
244 pub const fn with_fixed_int_encoding(self) -> Configuration<E, Fixint, L, B, O, F, FO> {
245 generate()
246 }
247
248 #[must_use]
250 pub const fn with_limit<const N: usize>(self) -> Configuration<E, I, Limit<N>, B, O, F, FO> {
251 generate()
252 }
253
254 #[must_use]
256 pub const fn with_no_limit(self) -> Configuration<E, I, NoLimit, B, O, F, FO> {
257 generate()
258 }
259
260 #[must_use]
262 pub const fn with_bit_packing(self) -> Configuration<E, I, L, AllowBitPacking, O, F, FO> {
263 generate()
264 }
265
266 #[must_use]
268 pub const fn with_no_bit_packing(self) -> Configuration<E, I, L, SkipBitPacking, O, F, FO> {
269 generate()
270 }
271
272 #[must_use]
280 pub const fn with_fingerprint(self) -> Configuration<E, I, L, B, O, FingerprintEnabled<0>, FO> {
281 generate()
282 }
283
284 #[must_use]
289 pub const fn with_fingerprint_and_seed<const SEED: u64>(
290 self
291 ) -> Configuration<E, I, L, B, O, FingerprintEnabled<SEED>, FO> {
292 generate()
293 }
294
295 #[must_use]
300 pub const fn with_legacy_fingerprint<const EXPECTED: u64>(
301 self
302 ) -> Configuration<E, I, L, B, O, FingerprintLegacy<EXPECTED>, FO> {
303 generate()
304 }
305
306 #[must_use]
308 pub const fn with_cbor_format(self) -> Configuration<E, I, L, B, O, F, CborFormat> {
309 generate()
310 }
311
312 #[must_use]
314 pub const fn with_deterministic_cbor(
315 self
316 ) -> Configuration<E, I, L, B, O, F, CborDeterministicFormat> {
317 generate()
318 }
319
320 #[must_use]
322 pub const fn with_deterministic_bincode(
323 self
324 ) -> Configuration<E, I, L, B, O, F, BincodeDeterministicFormat> {
325 generate()
326 }
327
328 #[must_use]
330 pub const fn with_cbor_options<
331 const DET: u8,
332 const PREF: bool,
333 const NAN: bool,
334 const NZ: bool,
335 const INDEF: bool,
336 const TAGS: bool,
337 >(
338 self
339 ) -> Configuration<E, I, L, B, O, F, CborConfig<DET, PREF, NAN, NZ, INDEF, TAGS>> {
340 generate()
341 }
342}
343
344pub trait Config:
346 InternalEndianConfig
347 + InternalIntEncodingConfig
348 + InternalLimitConfig
349 + InternalBitPackingConfig
350 + InternalBitOrderingConfig
351 + InternalFingerprintConfig
352 + InternalFormatConfig
353 + InternalConfigFingerprint
354 + InternalFingerprintConfigExt
355 + Copy
356 + Clone
357{
358 fn endianness(&self) -> Endianness;
360
361 fn int_encoding(&self) -> IntEncoding;
363
364 fn limit(&self) -> Option<usize>;
366
367 fn bit_packing_enabled(&self) -> bool;
369
370 fn bit_ordering(&self) -> BitOrdering;
372
373 fn fingerprint_mode(&self) -> FingerprintMode;
375
376 fn format(&self) -> Format;
378
379 fn cbor_options(&self) -> CborOptions;
382
383 fn is_compact_net(&self) -> bool;
385}
386
387impl<T> Config for T
388where
389 T: InternalEndianConfig
390 + InternalIntEncodingConfig
391 + InternalLimitConfig
392 + InternalBitPackingConfig
393 + InternalBitOrderingConfig
394 + InternalFingerprintConfig
395 + InternalFormatConfig
396 + InternalConfigFingerprint
397 + InternalFingerprintConfigExt
398 + Copy
399 + Clone,
400{
401 fn endianness(&self) -> Endianness {
402 <T as InternalEndianConfig>::ENDIAN
403 }
404
405 fn int_encoding(&self) -> IntEncoding {
406 <T as InternalIntEncodingConfig>::INT_ENCODING
407 }
408
409 fn limit(&self) -> Option<usize> {
410 <T as InternalLimitConfig>::LIMIT
411 }
412
413 fn bit_packing_enabled(&self) -> bool {
414 matches!(
415 <T as InternalBitPackingConfig>::BIT_PACKING,
416 BitPacking::Enabled
417 )
418 }
419
420 fn bit_ordering(&self) -> BitOrdering {
421 <T as InternalBitOrderingConfig>::BIT_ORDERING
422 }
423
424 fn fingerprint_mode(&self) -> FingerprintMode {
425 <T as InternalFingerprintConfig>::FINGERPRINT_MODE
426 }
427
428 fn format(&self) -> Format {
429 <T as InternalFormatConfig>::FORMAT
430 }
431
432 fn cbor_options(&self) -> CborOptions {
433 <T as InternalFormatConfig>::CBOR_OPTIONS
434 }
435
436 fn is_compact_net(&self) -> bool {
437 <T as InternalFormatConfig>::IS_COMPACT_NET
438 }
439}
440
441#[derive(Copy, Clone, Debug)]
443#[doc(hidden)]
444pub struct BigEndian;
445
446impl InternalEndianConfig for BigEndian {
447 const ENDIAN: Endianness = Endianness::Big;
448}
449
450#[derive(Copy, Clone, Debug)]
452#[doc(hidden)]
453pub struct LittleEndian;
454
455impl InternalEndianConfig for LittleEndian {
456 const ENDIAN: Endianness = Endianness::Little;
457}
458
459#[derive(Copy, Clone, Debug)]
461#[doc(hidden)]
462pub struct Fixint;
463
464impl InternalIntEncodingConfig for Fixint {
465 const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
466}
467
468#[derive(Copy, Clone, Debug)]
470#[doc(hidden)]
471pub struct Varint;
472
473impl InternalIntEncodingConfig for Varint {
474 const INT_ENCODING: IntEncoding = IntEncoding::Variable;
475}
476
477#[derive(Copy, Clone, Debug)]
479#[doc(hidden)]
480pub struct NoLimit;
481impl InternalLimitConfig for NoLimit {
482 const LIMIT: Option<usize> = None;
483}
484
485#[derive(Copy, Clone, Debug)]
487#[doc(hidden)]
488pub struct Limit<const N: usize>;
489impl<const N: usize> InternalLimitConfig for Limit<N> {
490 const LIMIT: Option<usize> = Some(N);
491}
492
493#[derive(Copy, Clone, Debug)]
495#[doc(hidden)]
496pub struct AllowBitPacking;
497
498impl InternalBitPackingConfig for AllowBitPacking {
499 const BIT_PACKING: BitPacking = BitPacking::Enabled;
500}
501
502#[derive(Copy, Clone, Debug)]
504#[doc(hidden)]
505pub struct SkipBitPacking;
506
507impl InternalBitPackingConfig for SkipBitPacking {
508 const BIT_PACKING: BitPacking = BitPacking::Disabled;
509}
510
511#[derive(Copy, Clone, Debug)]
513#[doc(hidden)]
514pub struct MsbFirst;
515
516impl InternalBitOrderingConfig for MsbFirst {
517 const BIT_ORDERING: BitOrdering = BitOrdering::Msb;
518}
519
520#[derive(Copy, Clone, Debug)]
522#[doc(hidden)]
523pub struct LsbFirst;
524
525impl InternalBitOrderingConfig for LsbFirst {
526 const BIT_ORDERING: BitOrdering = BitOrdering::Lsb;
527}
528
529#[derive(Copy, Clone, Debug)]
531#[doc(hidden)]
532pub struct FingerprintDisabled;
533
534impl InternalFingerprintConfig for FingerprintDisabled {
535 const FINGERPRINT_MODE: FingerprintMode = FingerprintMode::Disabled;
536}
537
538#[derive(Copy, Clone, Debug)]
540#[doc(hidden)]
541pub struct FingerprintEnabled<const SEED: u64>;
542
543impl<const SEED: u64> InternalFingerprintConfig for FingerprintEnabled<SEED> {
544 const FINGERPRINT_MODE: FingerprintMode = FingerprintMode::Enabled { seed: SEED };
545}
546
547#[derive(Copy, Clone, Debug)]
549#[doc(hidden)]
550pub struct FingerprintLegacy<const EXPECTED: u64>;
551
552impl<const EXPECTED: u64> InternalFingerprintConfig for FingerprintLegacy<EXPECTED> {
553 const FINGERPRINT_MODE: FingerprintMode = FingerprintMode::Legacy { expected: EXPECTED };
554}
555
556#[derive(Copy, Clone, Debug)]
558#[doc(hidden)]
559pub struct BincodeFormat;
560
561impl InternalFormatConfig for BincodeFormat {
562 const CBOR_OPTIONS: CborOptions = CborOptions::DEFAULT;
563 const FORMAT: Format = Format::Bincode;
564 const IS_COMPACT_NET: bool = false;
565}
566
567#[derive(Copy, Clone, Debug)]
569#[doc(hidden)]
570pub struct BincodeDeterministicFormat;
571
572impl InternalFormatConfig for BincodeDeterministicFormat {
573 const CBOR_OPTIONS: CborOptions = CborOptions::DEFAULT;
574 const FORMAT: Format = Format::BincodeDeterministic;
575 const IS_COMPACT_NET: bool = false;
576}
577
578#[derive(Copy, Clone, Debug)]
580#[doc(hidden)]
581pub struct CborConfig<
582 const DET: u8,
583 const PREF: bool,
584 const NAN: bool,
585 const NZ: bool,
586 const INDEF: bool,
587 const TAGS: bool,
588>;
589
590impl<
591 const DET: u8,
592 const PREF: bool,
593 const NAN: bool,
594 const NZ: bool,
595 const INDEF: bool,
596 const TAGS: bool,
597> InternalFormatConfig for CborConfig<DET, PREF, NAN, NZ, INDEF, TAGS>
598{
599 const CBOR_OPTIONS: CborOptions = CborOptions {
600 deterministic_mode: match DET {
601 | 1 => CborDeterministicMode::Core,
602 | 2 => CborDeterministicMode::LengthFirst,
603 | _ => CborDeterministicMode::None,
604 },
605 preferred_float: PREF,
606 canonical_nan: NAN,
607 normalize_neg_zero: NZ,
608 allow_indefinite: INDEF,
609 strict_tags: TAGS,
610 };
611 const FORMAT: Format = if DET == 0 {
612 Format::Cbor
613 } else {
614 Format::CborDeterministic
615 };
616 const IS_COMPACT_NET: bool = false;
617}
618
619#[derive(Copy, Clone, Debug)]
621#[doc(hidden)]
622pub struct BincodeLegacyFormat;
623
624impl InternalFormatConfig for BincodeLegacyFormat {
625 const CBOR_OPTIONS: CborOptions = CborOptions::DEFAULT;
626 const FORMAT: Format = Format::Bincode;
627 const IS_COMPACT_NET: bool = true;
628}
629
630#[doc(hidden)]
632pub type CborFormat = CborConfig<0, true, true, false, true, false>;
633
634#[doc(hidden)]
636pub type CborDeterministicFormat = CborConfig<1, true, true, false, false, true>;
637
638#[derive(Copy, Clone, Debug, PartialEq, Eq)]
640#[non_exhaustive]
641pub enum Endianness {
642 Little,
644 Big,
646}
647
648#[derive(Copy, Clone, Debug, PartialEq, Eq)]
650#[non_exhaustive]
651pub enum IntEncoding {
652 Fixed,
654 Variable,
656}
657
658#[derive(Copy, Clone, Debug, PartialEq, Eq)]
660#[non_exhaustive]
661pub enum BitPacking {
662 Enabled,
664 Disabled,
666}
667
668#[derive(Copy, Clone, Debug, PartialEq, Eq)]
670#[non_exhaustive]
671pub enum BitOrdering {
672 Lsb,
674 Msb,
676}
677
678#[derive(Copy, Clone, Debug, PartialEq, Eq)]
680#[non_exhaustive]
681pub enum FingerprintMode {
682 Disabled,
684 Enabled {
686 seed: u64,
688 },
689 Legacy {
691 expected: u64,
693 },
694}
695
696#[derive(Copy, Clone, Debug, PartialEq, Eq)]
698#[non_exhaustive]
699pub enum Format {
700 Bincode,
702 BincodeDeterministic,
704 Cbor,
706 CborDeterministic,
708}
709
710#[doc(hidden)]
711pub mod internal {
712 use super::BitOrdering;
713 use super::BitPacking;
714 use super::Configuration;
715 use super::Endianness;
716 use super::FingerprintMode;
717 use super::IntEncoding;
718
719 pub trait InternalEndianConfig {
720 const ENDIAN: Endianness;
721 }
722
723 impl<E: InternalEndianConfig, I, L, B, O, F, FO> InternalEndianConfig
724 for Configuration<E, I, L, B, O, F, FO>
725 {
726 const ENDIAN: Endianness = E::ENDIAN;
727 }
728
729 pub trait InternalIntEncodingConfig {
730 const INT_ENCODING: IntEncoding;
731 }
732
733 impl<E, I: InternalIntEncodingConfig, L, B, O, F, FO> InternalIntEncodingConfig
734 for Configuration<E, I, L, B, O, F, FO>
735 {
736 const INT_ENCODING: IntEncoding = I::INT_ENCODING;
737 }
738
739 pub trait InternalLimitConfig {
740 const LIMIT: Option<usize>;
741 }
742
743 impl<E, I, L: InternalLimitConfig, B, O, F, FO> InternalLimitConfig
744 for Configuration<E, I, L, B, O, F, FO>
745 {
746 const LIMIT: Option<usize> = L::LIMIT;
747 }
748
749 pub trait InternalBitPackingConfig {
750 const BIT_PACKING: BitPacking;
751 }
752
753 impl<E, I, L, B: InternalBitPackingConfig, O, F, FO> InternalBitPackingConfig
754 for Configuration<E, I, L, B, O, F, FO>
755 {
756 const BIT_PACKING: BitPacking = B::BIT_PACKING;
757 }
758
759 pub trait InternalBitOrderingConfig {
760 const BIT_ORDERING: BitOrdering;
761 }
762
763 impl<E, I, L, B, O: InternalBitOrderingConfig, F, FO> InternalBitOrderingConfig
764 for Configuration<E, I, L, B, O, F, FO>
765 {
766 const BIT_ORDERING: BitOrdering = O::BIT_ORDERING;
767 }
768
769 pub trait InternalFingerprintConfig {
770 const FINGERPRINT_MODE: FingerprintMode;
771 }
772
773 impl<E, I, L, B, O, F: InternalFingerprintConfig, FO> InternalFingerprintConfig
774 for Configuration<E, I, L, B, O, F, FO>
775 {
776 const FINGERPRINT_MODE: FingerprintMode = F::FINGERPRINT_MODE;
777 }
778
779 pub trait InternalFingerprintConfigExt {
780 type Mode;
781 }
782
783 impl<E, I, L, B, O, F, FO> InternalFingerprintConfigExt for Configuration<E, I, L, B, O, F, FO> {
784 type Mode = F;
785 }
786
787 pub trait InternalFingerprintGuard<D, C: super::Config> {
788 fn decode_check<R: crate::de::read::Reader>(
789 _config: &C,
790 reader: &mut R,
791 ) -> core::result::Result<(), crate::error::DecodeError>;
792 fn encode_check<W: crate::enc::write::Writer>(
793 _config: &C,
794 writer: &mut W,
795 ) -> core::result::Result<(), crate::error::EncodeError>;
796 }
797
798 impl<D, C: super::Config> InternalFingerprintGuard<D, C> for super::FingerprintDisabled {
799 #[inline(always)]
800 fn decode_check<R: crate::de::read::Reader>(
801 _config: &C,
802 _reader: &mut R,
803 ) -> core::result::Result<(), crate::error::DecodeError> {
804 core::result::Result::Ok(())
805 }
806
807 #[inline(always)]
808 fn encode_check<W: crate::enc::write::Writer>(
809 _config: &C,
810 _writer: &mut W,
811 ) -> core::result::Result<(), crate::error::EncodeError> {
812 core::result::Result::Ok(())
813 }
814 }
815
816 impl<D: crate::fingerprint::Fingerprint<C>, C: super::Config, const SEED: u64>
817 InternalFingerprintGuard<D, C> for super::FingerprintEnabled<SEED>
818 {
819 #[inline]
820 fn decode_check<R: crate::de::read::Reader>(
821 _config: &C,
822 reader: &mut R,
823 ) -> core::result::Result<(), crate::error::DecodeError> {
824 let mut bytes = [0u8; 8];
825 reader.read(&mut bytes)?;
826 let actual = u64::from_le_bytes(bytes);
827 if actual != D::SCHEMA_HASH {
828 return crate::error::cold_decode_error_schema_mismatch(D::SCHEMA_HASH, actual);
829 }
830 core::result::Result::Ok(())
831 }
832
833 #[inline]
834 fn encode_check<W: crate::enc::write::Writer>(
835 _config: &C,
836 writer: &mut W,
837 ) -> core::result::Result<(), crate::error::EncodeError> {
838 writer.write(&D::SCHEMA_HASH.to_le_bytes())
839 }
840 }
841
842 impl<D, C: super::Config, const EXPECTED: u64> InternalFingerprintGuard<D, C>
843 for super::FingerprintLegacy<EXPECTED>
844 {
845 #[inline]
846 fn decode_check<R: crate::de::read::Reader>(
847 _config: &C,
848 reader: &mut R,
849 ) -> core::result::Result<(), crate::error::DecodeError> {
850 let mut bytes = [0u8; 8];
851 reader.read(&mut bytes)?;
852 let actual = u64::from_le_bytes(bytes);
853 if actual != EXPECTED {
854 return crate::error::cold_decode_error_schema_mismatch(EXPECTED, actual);
855 }
856 core::result::Result::Ok(())
857 }
858
859 #[inline]
860 fn encode_check<W: crate::enc::write::Writer>(
861 _config: &C,
862 _writer: &mut W,
863 ) -> core::result::Result<(), crate::error::EncodeError> {
864 core::result::Result::Ok(())
865 }
866 }
867
868 pub trait InternalConfigFingerprint {
869 const CONFIG_HASH: u64;
870 }
871
872 impl<E, I, L, B, O, F, FO> InternalConfigFingerprint for Configuration<E, I, L, B, O, F, FO>
873 where
874 E: InternalEndianConfig,
875 I: InternalIntEncodingConfig,
876 L: InternalLimitConfig,
877 B: InternalBitPackingConfig,
878 O: InternalBitOrderingConfig,
879 FO: InternalFormatConfig,
880 {
881 const CONFIG_HASH: u64 = {
882 let format_byte: u8 = match FO::FORMAT {
883 | super::Format::Bincode => 0,
884 | super::Format::BincodeDeterministic => 1,
885 | super::Format::Cbor => 2,
886 | super::Format::CborDeterministic => 3,
887 };
888 let opts = FO::CBOR_OPTIONS;
889 rapidhash::v3::rapidhash_v3_seeded(
890 &[
891 crate::BINCODE_MAJOR_VERSION as u8,
892 E::ENDIAN as u8,
893 I::INT_ENCODING as u8,
894 match L::LIMIT {
895 | None => 0,
896 | Some(_) => 1,
897 },
898 B::BIT_PACKING as u8,
899 O::BIT_ORDERING as u8,
900 format_byte,
901 opts.deterministic_mode as u8,
902 opts.preferred_float as u8,
903 opts.canonical_nan as u8,
904 opts.normalize_neg_zero as u8,
905 opts.allow_indefinite as u8,
906 opts.strict_tags as u8,
907 ],
908 &rapidhash::v3::RapidSecrets::seed_cpp(0),
909 )
910 };
911 }
912
913 pub trait InternalFormatConfig {
914 const FORMAT: super::Format;
915 const CBOR_OPTIONS: super::CborOptions;
916 const IS_COMPACT_NET: bool;
917 }
918
919 impl<E, I, L, B, O, F, FO: InternalFormatConfig> InternalFormatConfig
920 for Configuration<E, I, L, B, O, F, FO>
921 {
922 const CBOR_OPTIONS: super::CborOptions = FO::CBOR_OPTIONS;
923 const FORMAT: super::Format = FO::FORMAT;
924 const IS_COMPACT_NET: bool = FO::IS_COMPACT_NET;
925 }
926}