object_rainbow/
length_prefixed.rs

1use std::ops::{Add, Deref, DerefMut};
2
3use generic_array::ArrayLength;
4use typenum::{Sum, U8, Unsigned, tarr};
5
6use crate::{numeric::Le, *};
7
8#[derive(Topological, Tagged, ParseAsInline, Default)]
9pub struct Lp<T>(pub T);
10
11impl<T> Deref for Lp<T> {
12    type Target = T;
13
14    fn deref(&self) -> &Self::Target {
15        &self.0
16    }
17}
18
19impl<T> DerefMut for Lp<T> {
20    fn deref_mut(&mut self) -> &mut Self::Target {
21        &mut self.0
22    }
23}
24
25impl<T: ToOutput> ToOutput for Lp<T> {
26    fn to_output(&self, output: &mut dyn crate::Output) {
27        let data = self.0.vec();
28        let len = data.len();
29        let len = len as u64;
30        assert_ne!(len, u64::MAX);
31        let prefix = Le::<u64>(len);
32        prefix.to_output(output);
33        data.to_output(output);
34    }
35}
36
37impl<T: Size> Size for Lp<T>
38where
39    U8: Add<T::Size, Output: Unsigned>,
40{
41    type Size = Sum<U8, T::Size>;
42}
43
44impl<T: Size> MaybeHasNiche for Lp<T>
45where
46    U8: Add<T::Size, Output: ArrayLength>,
47{
48    type MnArray = tarr![SomeNiche<OneNiche<U8>>, NoNiche<ZeroNoNiche<T::Size>>];
49}
50
51impl<T: Parse<I>, I: ParseInput> ParseInline<I> for Lp<T> {
52    fn parse_inline(input: &mut I) -> crate::Result<Self> {
53        let prefix: Le<u64> = input.parse_inline()?;
54        let len = prefix.0;
55        let len = len.try_into().map_err(|_| Error::UnsupportedLength)?;
56        Ok(Self(input.parse_ahead(len)?))
57    }
58}
59
60impl<T: Object<Extra>, Extra: 'static> Object<Extra> for Lp<T> {}
61impl<T: Object<Extra>, Extra: 'static> Inline<Extra> for Lp<T> {}
62impl<T: ReflessObject> ReflessObject for Lp<T> {}
63impl<T: ReflessObject> ReflessInline for Lp<T> {}
64
65#[test]
66fn prefixed() {
67    let a = Lp(vec![0, 1, 2]);
68    let data = a.vec();
69    let b = Lp::<Vec<u8>>::parse_slice_refless(&data).unwrap();
70    assert_eq!(*a, *b);
71}
72
73#[derive(Debug, Clone, ParseAsInline, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
74pub struct LpBytes(pub Vec<u8>);
75
76impl Deref for LpBytes {
77    type Target = Vec<u8>;
78
79    fn deref(&self) -> &Self::Target {
80        &self.0
81    }
82}
83
84impl DerefMut for LpBytes {
85    fn deref_mut(&mut self) -> &mut Self::Target {
86        &mut self.0
87    }
88}
89
90impl ToOutput for LpBytes {
91    fn to_output(&self, output: &mut dyn crate::Output) {
92        let data = &self.0;
93        let len = data.len();
94        let len = len as u64;
95        assert_ne!(len, u64::MAX);
96        let prefix = Le::<u64>(len);
97        prefix.to_output(output);
98        data.to_output(output);
99    }
100}
101
102impl<I: ParseInput> ParseInline<I> for LpBytes {
103    fn parse_inline(input: &mut I) -> crate::Result<Self> {
104        let prefix: Le<u64> = input.parse_inline()?;
105        let len = prefix.0;
106        let len = len.try_into().map_err(|_| Error::UnsupportedLength)?;
107        Ok(Self(input.parse_n(len)?.into()))
108    }
109}
110
111impl Tagged for LpBytes {}
112impl Topological for LpBytes {}
113impl<E: 'static> Object<E> for LpBytes {}
114impl<E: 'static> Inline<E> for LpBytes {}
115impl ReflessObject for LpBytes {}
116impl ReflessInline for LpBytes {}
117
118#[derive(Debug, Clone, ParseAsInline, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
119pub struct LpString(pub String);
120
121impl Deref for LpString {
122    type Target = String;
123
124    fn deref(&self) -> &Self::Target {
125        &self.0
126    }
127}
128
129impl DerefMut for LpString {
130    fn deref_mut(&mut self) -> &mut Self::Target {
131        &mut self.0
132    }
133}
134
135impl ToOutput for LpString {
136    fn to_output(&self, output: &mut dyn crate::Output) {
137        let data = self.0.as_bytes();
138        let len = data.len();
139        let len = len as u64;
140        assert_ne!(len, u64::MAX);
141        let prefix = Le::<u64>(len);
142        prefix.to_output(output);
143        data.to_output(output);
144    }
145}
146
147impl<I: ParseInput> ParseInline<I> for LpString {
148    fn parse_inline(input: &mut I) -> crate::Result<Self> {
149        String::from_utf8(input.parse_inline::<LpBytes>()?.0)
150            .map_err(Error::Utf8)
151            .map(Self)
152    }
153}
154
155impl Tagged for LpString {}
156impl Topological for LpString {}
157impl<E: 'static> Object<E> for LpString {}
158impl<E: 'static> Inline<E> for LpString {}
159impl ReflessObject for LpString {}
160impl ReflessInline for LpString {}