lilliput_core/value/
bytes.rs

1#[cfg(any(test, feature = "testing"))]
2use proptest::prelude::*;
3#[cfg(any(test, feature = "testing"))]
4use proptest_derive::Arbitrary;
5
6use crate::binary::BytesSlice;
7
8/// Represents a byte sequence.
9#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
10#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
11pub struct BytesValue(pub Vec<u8>);
12
13impl BytesValue {
14    /// Returns a slice, referencing the inner vec.
15    pub fn as_slice(&self) -> &[u8] {
16        &self.0
17    }
18
19    /// Returns the internal vec, consuming `self`.
20    pub fn into_vec(self) -> Vec<u8> {
21        self.0
22    }
23
24    /// Returns the length of the internal vec.
25    pub fn len(&self) -> usize {
26        self.0.len()
27    }
28
29    /// Returns `true`, if the internal vec is empty, otherwise `false`.
30    pub fn is_empty(&self) -> bool {
31        self.0.is_empty()
32    }
33}
34
35impl From<Vec<u8>> for BytesValue {
36    fn from(value: Vec<u8>) -> Self {
37        Self(value)
38    }
39}
40
41impl<'a> From<&'a BytesValue> for &'a [u8] {
42    fn from(value: &'a BytesValue) -> Self {
43        &value.0
44    }
45}
46
47impl From<BytesValue> for Vec<u8> {
48    fn from(value: BytesValue) -> Self {
49        value.0
50    }
51}
52
53impl std::fmt::Debug for BytesValue {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        std::fmt::Debug::fmt(&BytesSlice(&self.0), f)
56    }
57}
58
59impl std::fmt::Display for BytesValue {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        std::fmt::Display::fmt(&BytesSlice(&self.0), f)
62    }
63}
64
65#[cfg(feature = "serde")]
66impl serde::Serialize for BytesValue {
67    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68    where
69        S: serde::Serializer,
70    {
71        serde_bytes::Bytes::new(&self.0).serialize(serializer)
72    }
73}
74
75#[cfg(feature = "serde")]
76impl<'de> serde::Deserialize<'de> for BytesValue {
77    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78    where
79        D: serde::Deserializer<'de>,
80    {
81        Ok(Self(
82            serde_bytes::ByteBuf::deserialize(deserializer)?.into_vec(),
83        ))
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use proptest::prelude::*;
90    use test_log::test;
91
92    use crate::{
93        config::EncoderConfig,
94        decoder::Decoder,
95        encoder::Encoder,
96        io::{SliceReader, VecWriter},
97        value::Value,
98    };
99
100    use super::*;
101
102    #[test]
103    fn display() {
104        assert_eq!(
105            format!("{}", BytesValue::from(vec![1, 2, 3])),
106            "[01, 02, 03]"
107        );
108    }
109
110    #[test]
111    fn debug() {
112        assert_eq!(
113            format!("{:?}", BytesValue::from(vec![1, 2, 3])),
114            "[00000001, 00000010, 00000011]"
115        );
116
117        assert_eq!(
118            format!("{:#?}", BytesValue::from(vec![1, 2, 3])),
119            "[0b00000001, 0b00000010, 0b00000011]"
120        );
121    }
122
123    proptest! {
124        #[test]
125        fn encode_decode_roundtrip(value in BytesValue::arbitrary(), config in EncoderConfig::arbitrary()) {
126            let mut encoded: Vec<u8> = Vec::new();
127            let writer = VecWriter::new(&mut encoded);
128            let mut encoder = Encoder::new(writer, config);
129            encoder.encode_bytes(value.as_slice()).unwrap();
130
131            prop_assert!(encoded.len() <= 1 + 8 + value.len());
132
133            let reader = SliceReader::new(&encoded);
134            let mut decoder = Decoder::from_reader(reader);
135            let decoded = decoder.decode_bytes_buf().unwrap();
136            prop_assert_eq!(&decoded, value.as_slice());
137
138            let reader = SliceReader::new(&encoded);
139            let mut decoder = Decoder::from_reader(reader);
140            let decoded = decoder.decode_value().unwrap();
141            let Value::Bytes(decoded) = decoded else {
142                panic!("expected bytes value");
143            };
144            prop_assert_eq!(&decoded, &value);
145        }
146    }
147}