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}