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