Skip to main content

object_rainbow/
length_prefixed.rs

1use std::{
2    fmt::Display,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{u63::U63, *};
7
8/// Length-prefixed value. Used to make [`Inline`]s out of arbitrary [`Object`]s.
9///
10/// If you can guarantee absence of zeroes, see [`zero_terminated::Zt`].
11#[derive(
12    ListHashes, Topological, Tagged, ParseAsInline, Default, Clone, PartialEq, Eq, PartialOrd, Ord,
13)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Lp<T>(pub T);
16
17impl<T> Deref for Lp<T> {
18    type Target = T;
19
20    fn deref(&self) -> &Self::Target {
21        &self.0
22    }
23}
24
25impl<T> DerefMut for Lp<T> {
26    fn deref_mut(&mut self) -> &mut Self::Target {
27        &mut self.0
28    }
29}
30
31impl<T: ToOutput> ToOutput for Lp<T> {
32    fn to_output(&self, output: &mut impl Output) {
33        if output.is_mangling() {
34            self.0.to_output(output);
35        }
36        if output.is_real() {
37            let data = self.0.vec();
38            let prefix = U63::len_of(&data);
39            prefix.to_output(output);
40            data.to_output(output);
41        }
42    }
43}
44
45impl<T: ToOutput> InlineOutput for Lp<T> {}
46
47impl<T: Parse<I>, I: ParseInput> ParseInline<I> for Lp<T> {
48    fn parse_inline(input: &mut I) -> crate::Result<Self> {
49        let prefix: U63 = input.parse_inline()?;
50        Ok(Self(input.split_parse(prefix.as_usize()?)?))
51    }
52}
53
54impl<T: SignificantLength> ByteOrd for Lp<T> {
55    fn bytes_cmp(&self, other: &Self) -> Ordering {
56        self.0.bytes_cmp(&other.0)
57    }
58}
59
60#[test]
61fn prefixed() -> crate::Result<()> {
62    let a = Lp(vec![0, 1, 2]);
63    let data = a.vec();
64    let b = Lp::<Vec<u8>>::parse_slice_refless(&data)?;
65    assert_eq!(*a, *b);
66    Ok(())
67}
68
69/// Length-prefixed [`Vec<u8>`]
70#[derive(Debug, Clone, ParseAsInline, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72pub struct LpBytes(pub Vec<u8>);
73
74impl Deref for LpBytes {
75    type Target = Vec<u8>;
76
77    fn deref(&self) -> &Self::Target {
78        &self.0
79    }
80}
81
82impl DerefMut for LpBytes {
83    fn deref_mut(&mut self) -> &mut Self::Target {
84        &mut self.0
85    }
86}
87
88impl ToOutput for LpBytes {
89    fn to_output(&self, output: &mut impl Output) {
90        if output.is_real() {
91            let data = &self.0;
92            let prefix = U63::len_of(data);
93            prefix.to_output(output);
94            data.to_output(output);
95        }
96    }
97}
98
99impl InlineOutput for LpBytes {}
100
101impl<I: ParseInput> ParseInline<I> for LpBytes {
102    fn parse_inline(input: &mut I) -> crate::Result<Self> {
103        let prefix: U63 = input.parse_inline()?;
104        let mut data = vec![0; prefix.as_usize()?];
105        input.read(&mut data)?;
106        Ok(Self(data))
107    }
108}
109
110impl Tagged for LpBytes {}
111impl ListHashes for LpBytes {}
112impl Topological for LpBytes {}
113
114/// Length-prefixed [`String`].
115#[derive(Debug, Clone, ParseAsInline, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117pub struct LpString(pub String);
118
119impl Display for LpString {
120    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121        self.0.fmt(f)
122    }
123}
124
125impl From<&'_ str> for LpString {
126    fn from(s: &'_ str) -> Self {
127        Self(s.into())
128    }
129}
130
131impl AsRef<str> for LpString {
132    fn as_ref(&self) -> &str {
133        self
134    }
135}
136
137impl Deref for LpString {
138    type Target = String;
139
140    fn deref(&self) -> &Self::Target {
141        &self.0
142    }
143}
144
145impl DerefMut for LpString {
146    fn deref_mut(&mut self) -> &mut Self::Target {
147        &mut self.0
148    }
149}
150
151impl ToOutput for LpString {
152    fn to_output(&self, output: &mut impl Output) {
153        if output.is_real() {
154            let data = &self.0;
155            let prefix = U63::len_of(data.as_bytes());
156            prefix.to_output(output);
157            data.to_output(output);
158        }
159    }
160}
161
162impl InlineOutput for LpString {}
163
164impl<I: ParseInput> ParseInline<I> for LpString {
165    fn parse_inline(input: &mut I) -> crate::Result<Self> {
166        String::from_utf8(input.parse_inline::<LpBytes>()?.0)
167            .map_err(Error::Utf8)
168            .map(Self)
169    }
170}
171
172impl Tagged for LpString {}
173impl ListHashes for LpString {}
174impl Topological for LpString {}
175
176#[derive(ListHashes, Topological, Tagged, ParseAsInline, Clone, PartialEq, Eq)]
177pub struct LpVec<T>(pub Vec<T>);
178
179impl<T> Deref for LpVec<T> {
180    type Target = Vec<T>;
181
182    fn deref(&self) -> &Self::Target {
183        &self.0
184    }
185}
186
187impl<T> DerefMut for LpVec<T> {
188    fn deref_mut(&mut self) -> &mut Self::Target {
189        &mut self.0
190    }
191}
192
193impl<T: InlineOutput> ToOutput for LpVec<T> {
194    fn to_output(&self, output: &mut impl Output) {
195        if output.is_mangling() {
196            self.0.to_output(output);
197        }
198        if output.is_real() {
199            let prefix = U63::len_of(&self.0);
200            prefix.to_output(output);
201            self.0.to_output(output);
202        }
203    }
204}
205
206impl<T: InlineOutput> InlineOutput for LpVec<T> {}
207
208impl<T: ParseInline<I>, I: ParseInput> ParseInline<I> for LpVec<T> {
209    fn parse_inline(input: &mut I) -> crate::Result<Self> {
210        let prefix: U63 = input.parse_inline()?;
211        Ok(Self(input.parse_vec_n(prefix.as_usize()?)?))
212    }
213}