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