lilliput_core/value/
unit.rs

1#[cfg(any(test, feature = "testing"))]
2use proptest::prelude::*;
3#[cfg(any(test, feature = "testing"))]
4use proptest_derive::Arbitrary;
5
6/// Represents a unit value.
7#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
8#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
9pub struct UnitValue;
10
11impl From<()> for UnitValue {
12    fn from(_: ()) -> Self {
13        Self
14    }
15}
16
17impl std::fmt::Debug for UnitValue {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        write!(f, "unit")
20    }
21}
22
23impl std::fmt::Display for UnitValue {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(f, "unit")
26    }
27}
28
29#[cfg(feature = "serde")]
30impl serde::Serialize for UnitValue {
31    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32    where
33        S: serde::Serializer,
34    {
35        serializer.serialize_unit()
36    }
37}
38
39#[cfg(feature = "serde")]
40impl<'de> serde::Deserialize<'de> for UnitValue {
41    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42    where
43        D: serde::Deserializer<'de>,
44    {
45        struct UnitValueVisitor;
46
47        impl serde::de::Visitor<'_> for UnitValueVisitor {
48            type Value = UnitValue;
49
50            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51                formatter.write_str("unit value")
52            }
53
54            fn visit_unit<E>(self) -> Result<Self::Value, E>
55            where
56                E: serde::de::Error,
57            {
58                Ok(UnitValue)
59            }
60        }
61
62        deserializer.deserialize_unit(UnitValueVisitor)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use proptest::prelude::*;
69    use test_log::test;
70
71    use crate::{
72        config::EncoderConfig,
73        decoder::Decoder,
74        encoder::Encoder,
75        io::{SliceReader, VecWriter},
76        value::Value,
77    };
78
79    use super::*;
80
81    #[test]
82    fn display() {
83        assert_eq!(format!("{UnitValue}"), "unit");
84    }
85
86    #[test]
87    fn debug() {
88        assert_eq!(format!("{UnitValue:?}"), "unit");
89        assert_eq!(format!("{UnitValue:#?}"), "unit");
90    }
91
92    proptest! {
93        #[test]
94        fn encode_decode_roundtrip(value in UnitValue::arbitrary(), config in EncoderConfig::arbitrary()) {
95            let mut encoded: Vec<u8> = Vec::new();
96            let writer = VecWriter::new(&mut encoded);
97            let mut encoder = Encoder::new(writer, config);
98            encoder.encode_unit().unwrap();
99
100            prop_assert!(encoded.len() <= 1);
101
102            let reader = SliceReader::new(&encoded);
103            let mut decoder = Decoder::from_reader(reader);
104            decoder.decode_unit().unwrap();
105
106            let reader = SliceReader::new(&encoded);
107            let mut decoder = Decoder::from_reader(reader);
108            let decoded = decoder.decode_value().unwrap();
109            let Value::Unit(decoded) = decoded else {
110                panic!("expected unit value");
111            };
112            prop_assert_eq!(&decoded, &value);
113        }
114    }
115}