ordcode/params.rs
1//! Serialization parameters traits and types
2//!
3#![allow(clippy::module_name_repetitions)]
4
5use crate::{varint, Result, buf::{TailReadBytes, TailWriteBytes}};
6
7/// lexicographic ordering for serialization
8///
9/// Note that there are no ordering marks in the serialized data; specification of different ordering
10/// for serialization and deserialization of the same data is UB.
11#[derive(Copy, Clone)]
12pub enum Order {
13 Ascending,
14 Descending,
15 /// For use by other crates. For the purposes of `ordcode`, same as [`Ascending`](Order::Ascending).
16 Unordered
17}
18
19/// Endianness representation for serialized integers
20#[derive(Copy, Clone)]
21pub enum Endianness {
22 Little,
23 Big,
24 Native,
25}
26
27/// Encoding parameters for primitive types serialization: lexicographic order and endianness.
28pub trait EncodingParams: Copy {
29 /// Serialization ordering of primitive types
30 ///
31 /// Note that you should not specify [`Order::Descending`] when parameterizing [`Serializer`](crate::Serializer):
32 /// descending ordering for composite types is achieved differently, by negating the resulting
33 /// byte buffer (this is also faster).
34 const ORDER: Order;
35
36 /// Endianness for encoding integer and float values; for encodings which preserve
37 /// lexicographic ordering, should be [`Endianness::Big`]
38 const ENDIANNESS: Endianness;
39}
40
41/// Parameters for implementations of `serde` serializer and deserializer
42pub trait SerializerParams: EncodingParams {
43 /// Encoder for sequence lengths
44 type SeqLenEncoder: LengthEncoder<Value=usize>;
45
46 /// Encoder for discriminant values
47 type DiscriminantEncoder: LengthEncoder<Value=u32>;
48}
49
50/// Encoder for array lengths, enum discriminants etc.
51pub trait LengthEncoder {
52 /// Value type, may be `u32`, `u64` or usize
53 type Value;
54
55 /// Calculate serialized size for value
56 fn calc_size(value: Self::Value) -> usize;
57 fn read(reader: impl TailReadBytes) -> Result<Self::Value>;
58 fn write(writer: impl TailWriteBytes, value: Self::Value) -> Result;
59}
60
61impl<T> EncodingParams for &T where T: EncodingParams {
62 const ORDER: Order = T::ORDER;
63 const ENDIANNESS: Endianness = T::ENDIANNESS;
64}
65
66impl <T> SerializerParams for &T where T: SerializerParams {
67 type SeqLenEncoder = T::SeqLenEncoder;
68 type DiscriminantEncoder = T::DiscriminantEncoder;
69}
70
71/// Serializer parameters for lexicographic order-preserving serialization in ascending order
72#[derive(Copy, Clone, Default)]
73pub struct AscendingOrder;
74
75impl EncodingParams for AscendingOrder {
76 const ORDER: Order = Order::Ascending;
77 const ENDIANNESS: Endianness = Endianness::Big;
78}
79
80impl SerializerParams for AscendingOrder {
81 type SeqLenEncoder = varint::VarIntTailLenEncoder;
82 type DiscriminantEncoder = varint::VarIntDiscrEncoder;
83}
84
85/// Encoding parameters for lexicographic order-preserving serialization in descending order
86///
87/// Note: deliberately implements only [`EncodingParams`] trait, not [`SerializerParams`], so it can
88/// be used with serialization primitives, but not with [`Serializer`](crate::Serializer)
89/// or [`Deserializer`](crate::Deserializer).
90#[derive(Copy, Clone, Default)]
91pub struct DescendingOrder;
92
93impl EncodingParams for DescendingOrder {
94 const ORDER: Order = Order::Descending;
95 const ENDIANNESS: Endianness = Endianness::Big;
96}
97
98/// Serializer parameters for portable binary format, which does not need double-ended buffer
99///
100/// However, it still requires implementation of [`TailReadBytes`](crate::buf::TailReadBytes),
101/// [`TailWriteBytes`](crate::buf::TailWriteBytes) traits
102/// for reader and writer, which should behave same as [`ReadBytes`](crate::buf::ReadBytes),
103/// [`WriteBytes`](crate::buf::WriteBytes).
104#[derive(Copy, Clone, Default)]
105pub struct PortableBinary;
106
107impl EncodingParams for PortableBinary {
108 const ORDER: Order = Order::Ascending;
109 const ENDIANNESS: Endianness = Endianness::Big;
110}
111
112impl SerializerParams for PortableBinary {
113 type SeqLenEncoder = varint::VarIntLenEncoder;
114 type DiscriminantEncoder = varint::VarIntDiscrEncoder;
115}
116
117/// Serializer parameters for platform-specific binary format, which does not need a double-ended buffer
118///
119/// This is probably the fastest option, but serialized data will not be portable.
120/// It still requires implementation of [`TailReadBytes`](crate::buf::TailReadBytes),
121/// [`TailWriteBytes`](crate::buf::TailWriteBytes) traits for reader
122/// and writer, which should behave the same as [`ReadBytes`](crate::buf::ReadBytes),
123/// [`WriteBytes`](crate::buf::WriteBytes).
124#[derive(Copy, Clone, Default)]
125pub struct NativeBinary;
126
127impl EncodingParams for NativeBinary {
128 const ORDER: Order = Order::Unordered;
129 const ENDIANNESS: Endianness = Endianness::Native;
130}
131
132impl SerializerParams for NativeBinary {
133 type SeqLenEncoder = varint::VarIntLenEncoder;
134 type DiscriminantEncoder = varint::VarIntDiscrEncoder;
135}