Skip to main content

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