lilliput_core/
header.rs

1//! Value headers.
2
3mod bool;
4mod bytes;
5mod float;
6mod int;
7mod map;
8mod null;
9mod seq;
10mod string;
11mod unit;
12
13#[cfg(any(test, feature = "testing"))]
14use proptest::prelude::*;
15#[cfg(any(test, feature = "testing"))]
16use proptest_derive::Arbitrary;
17
18use crate::marker::Marker;
19
20pub use self::{
21    bool::BoolHeader,
22    bytes::BytesHeader,
23    float::FloatHeader,
24    int::{CompactIntHeader, ExtendedIntHeader, IntHeader},
25    map::{CompactMapHeader, ExtendedMapHeader, MapHeader},
26    null::NullHeader,
27    seq::{CompactSeqHeader, ExtendedSeqHeader, SeqHeader},
28    string::{CompactStringHeader, ExtendedStringHeader, StringHeader},
29    unit::UnitHeader,
30};
31
32#[cfg(any(test, feature = "testing"))]
33pub(crate) fn arbitrary_len() -> impl Strategy<Value = usize> {
34    proptest::prop_oneof![
35        proptest::num::u8::ANY.prop_map(|len| len as usize),
36        proptest::num::u16::ANY.prop_map(|len| len as usize),
37        proptest::num::u32::ANY.prop_map(|len| len as usize),
38        proptest::num::u64::ANY.prop_map(|len| len as usize),
39    ]
40}
41
42/// A value's header.
43#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
44#[derive(Copy, Clone, Eq, PartialEq, Debug)]
45pub enum Header {
46    /// Represents a integer number.
47    Int(IntHeader),
48
49    /// Represents a string.
50    String(StringHeader),
51
52    /// Represents a sequence of values.
53    Seq(SeqHeader),
54
55    /// Represents a map of key-value pairs.
56    ///
57    /// By default the map is backed by a `BTreeMap`. Enable the `preserve_order`
58    /// feature of serde_lilliput to use `OrderMap` instead, which preserves
59    /// entries in the order they are inserted into the map.
60    Map(MapHeader),
61
62    /// Represents a floating-point number.
63    Float(FloatHeader),
64
65    /// Represents a byte array.
66    Bytes(BytesHeader),
67
68    /// Represents a boolean.
69    Bool(BoolHeader),
70
71    /// Represents a unit value.
72    Unit(UnitHeader),
73
74    /// Represents a null value.
75    Null(NullHeader),
76}
77
78impl Default for Header {
79    #[inline]
80    fn default() -> Self {
81        Self::Null(NullHeader)
82    }
83}
84
85impl From<IntHeader> for Header {
86    #[inline]
87    fn from(value: IntHeader) -> Self {
88        Self::Int(value)
89    }
90}
91
92impl From<StringHeader> for Header {
93    #[inline]
94    fn from(value: StringHeader) -> Self {
95        Self::String(value)
96    }
97}
98
99impl From<SeqHeader> for Header {
100    #[inline]
101    fn from(value: SeqHeader) -> Self {
102        Self::Seq(value)
103    }
104}
105
106impl From<MapHeader> for Header {
107    #[inline]
108    fn from(value: MapHeader) -> Self {
109        Self::Map(value)
110    }
111}
112
113impl From<FloatHeader> for Header {
114    #[inline]
115    fn from(value: FloatHeader) -> Self {
116        Self::Float(value)
117    }
118}
119
120impl From<BytesHeader> for Header {
121    #[inline]
122    fn from(value: BytesHeader) -> Self {
123        Self::Bytes(value)
124    }
125}
126
127impl From<BoolHeader> for Header {
128    #[inline]
129    fn from(value: BoolHeader) -> Self {
130        Self::Bool(value)
131    }
132}
133
134impl From<UnitHeader> for Header {
135    #[inline]
136    fn from(value: UnitHeader) -> Self {
137        Self::Unit(value)
138    }
139}
140
141impl From<NullHeader> for Header {
142    #[inline]
143    fn from(value: NullHeader) -> Self {
144        Self::Null(value)
145    }
146}
147
148impl Header {
149    /// Returns the header's type marker.
150    pub fn marker(&self) -> Marker {
151        match self {
152            Header::Int(_) => Marker::Int,
153            Header::String(_) => Marker::String,
154            Header::Seq(_) => Marker::Seq,
155            Header::Map(_) => Marker::Map,
156            Header::Float(_) => Marker::Float,
157            Header::Bytes(_) => Marker::Bytes,
158            Header::Bool(_) => Marker::Bool,
159            Header::Unit(_) => Marker::Unit,
160            Header::Null(_) => Marker::Null,
161        }
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use proptest::prelude::*;
168    use test_log::test;
169
170    use crate::{
171        config::EncoderConfig,
172        decoder::Decoder,
173        encoder::Encoder,
174        io::{SliceReader, VecWriter},
175    };
176
177    use super::*;
178
179    proptest! {
180        #[test]
181        fn encode_decode_roundtrip(header in Header::arbitrary(), config in EncoderConfig::arbitrary()) {
182            let mut encoded: Vec<u8> = Vec::new();
183            let writer = VecWriter::new(&mut encoded);
184            let mut encoder = Encoder::new(writer, config);
185            encoder.encode_header(&header).unwrap();
186
187            let reader = SliceReader::new(&encoded);
188            let mut decoder = Decoder::from_reader(reader);
189            let decoded = decoder.decode_header().unwrap();
190            prop_assert_eq!(&decoded, &header);
191        }
192    }
193}