1use core::ops::Deref;
6
7use zerocopy::SplitByteSlice;
8
9use crate::BufferView;
10
11pub trait FromRaw<R, A>: Sized {
20 type Error;
22
23 fn try_from_raw_with(raw: R, args: A) -> Result<Self, Self::Error>;
25
26 fn try_from_raw(raw: R) -> Result<Self, <Self as FromRaw<R, A>>::Error>
28 where
29 Self: FromRaw<R, (), Error = <Self as FromRaw<R, A>>::Error>,
30 {
31 Self::try_from_raw_with(raw, ())
32 }
33}
34
35#[derive(Copy, Clone, Debug, Eq, PartialEq)]
41pub enum MaybeParsed<C, I> {
42 Complete(C),
43 Incomplete(I),
44}
45
46impl<T> MaybeParsed<T, T> {
47 pub fn new_with_min_len(bytes: T, min_len: usize) -> Self
54 where
55 T: SplitByteSlice,
56 {
57 if bytes.len() >= min_len {
58 MaybeParsed::Complete(bytes)
59 } else {
60 MaybeParsed::Incomplete(bytes)
61 }
62 }
63
64 pub fn into_inner(self) -> T {
67 match self {
68 MaybeParsed::Complete(c) => c,
69 MaybeParsed::Incomplete(i) => i,
70 }
71 }
72}
73
74impl<C, I> MaybeParsed<C, I> {
75 pub fn take_from_buffer_with<BV: BufferView<I>, F>(buf: &mut BV, n: usize, map: F) -> Self
83 where
84 F: FnOnce(I) -> C,
85 I: SplitByteSlice,
86 {
87 if let Some(v) = buf.take_front(n) {
88 MaybeParsed::Complete(map(v))
89 } else {
90 MaybeParsed::Incomplete(buf.take_rest_front())
91 }
92 }
93
94 pub fn map<M, F>(self, f: F) -> MaybeParsed<M, I>
98 where
99 F: FnOnce(C) -> M,
100 {
101 match self {
102 MaybeParsed::Incomplete(v) => MaybeParsed::Incomplete(v),
103 MaybeParsed::Complete(v) => MaybeParsed::Complete(f(v)),
104 }
105 }
106
107 pub fn map_incomplete<M, F>(self, f: F) -> MaybeParsed<C, M>
111 where
112 F: FnOnce(I) -> M,
113 {
114 match self {
115 MaybeParsed::Incomplete(v) => MaybeParsed::Incomplete(f(v)),
116 MaybeParsed::Complete(v) => MaybeParsed::Complete(v),
117 }
118 }
119
120 pub fn as_ref(&self) -> MaybeParsed<&C, &I> {
122 match self {
123 MaybeParsed::Incomplete(v) => MaybeParsed::Incomplete(v),
124 MaybeParsed::Complete(v) => MaybeParsed::Complete(v),
125 }
126 }
127
128 pub fn complete(self) -> Result<C, I> {
134 match self {
135 MaybeParsed::Complete(v) => Ok(v),
136 MaybeParsed::Incomplete(v) => Err(v),
137 }
138 }
139
140 pub fn incomplete(self) -> Result<I, C> {
146 match self {
147 MaybeParsed::Complete(v) => Err(v),
148 MaybeParsed::Incomplete(v) => Ok(v),
149 }
150 }
151
152 pub fn ok_or_else<F, E>(self, f: F) -> Result<C, E>
161 where
162 F: FnOnce(I) -> E,
163 {
164 match self {
165 MaybeParsed::Complete(v) => Ok(v),
166 MaybeParsed::Incomplete(v) => Err(f(v)),
167 }
168 }
169}
170
171impl<C, I> MaybeParsed<C, I>
172where
173 C: Deref<Target = [u8]>,
174 I: Deref<Target = [u8]>,
175{
176 pub fn len(&self) -> usize {
178 match self {
179 MaybeParsed::Incomplete(v) => v.deref().len(),
180 MaybeParsed::Complete(v) => v.deref().len(),
181 }
182 }
183
184 pub fn is_empty(&self) -> bool {
186 self.len() == 0
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193
194 impl<T> MaybeParsed<T, T> {
195 #[cfg(test)]
202 pub fn take_from_buffer<BV: BufferView<T>>(buff: &mut BV, n: usize) -> Self
203 where
204 T: SplitByteSlice,
205 {
206 if let Some(v) = buff.take_front(n) {
207 MaybeParsed::Complete(v)
208 } else {
209 MaybeParsed::Incomplete(buff.take_rest_front())
210 }
211 }
212 }
213
214 #[test]
215 fn test_maybe_parsed_take_from_buffer() {
216 let buff = [1_u8, 2, 3, 4];
217 let mut bv = &mut &buff[..];
218 assert_eq!(MaybeParsed::take_from_buffer(&mut bv, 2), MaybeParsed::Complete(&buff[..2]));
219 assert_eq!(MaybeParsed::take_from_buffer(&mut bv, 3), MaybeParsed::Incomplete(&buff[2..]));
220 }
221
222 #[test]
223 fn test_maybe_parsed_min_len() {
224 let buff = [1_u8, 2, 3, 4];
225 assert_eq!(MaybeParsed::new_with_min_len(&buff[..], 3), MaybeParsed::Complete(&buff[..]));
226 assert_eq!(MaybeParsed::new_with_min_len(&buff[..], 5), MaybeParsed::Incomplete(&buff[..]));
227 }
228
229 #[test]
230 fn test_maybe_parsed_take_from_buffer_with() {
231 let buff = [1_u8, 2, 3, 4];
232 let mut bv = &mut &buff[..];
233 assert_eq!(
234 MaybeParsed::take_from_buffer_with(&mut bv, 2, |x| Some(usize::from(x[0] + x[1]))),
235 MaybeParsed::Complete(Some(3)),
236 );
237 assert_eq!(
238 MaybeParsed::take_from_buffer_with(&mut bv, 3, |_| panic!("map shouldn't be called")),
239 MaybeParsed::Incomplete(&buff[2..]),
240 );
241 }
242
243 #[test]
244 fn test_maybe_parsed_map() {
245 assert_eq!(
246 MaybeParsed::<&str, ()>::Complete("hello").map(|x| format!("{} you", x)),
247 MaybeParsed::Complete("hello you".to_string()),
248 );
249 assert_eq!(
250 MaybeParsed::<(), &str>::Incomplete("hello").map(|_| panic!("map shouldn't be called")),
251 MaybeParsed::Incomplete("hello"),
252 );
253 }
254
255 #[test]
256 fn test_maybe_parsed_len() {
257 let buff = [1_u8, 2, 3, 4];
258 let mp1 = MaybeParsed::new_with_min_len(&buff[..], 2);
259 let mp2 = MaybeParsed::new_with_min_len(&buff[..], 10);
260 assert_eq!(mp1.len(), 4);
261 assert_eq!(mp2.len(), 4);
262 }
263}