netgauze_parse_utils/
lib.rs

1// Copyright (C) 2022-present The NetGauze Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12// implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Traits for Ser/Deser wire protocols
17
18#[cfg(feature = "test-helpers")]
19pub mod test_helpers;
20
21use netgauze_locate::BinarySpan;
22use nom::IResult;
23use std::fmt::Debug;
24
25pub type Span<'a> = BinarySpan<&'a [u8]>;
26
27/// Generic trait for Readable Protocol Data Unit that doesn't need any external
28/// input while parsing the packet.
29pub trait ReadablePdu<'a, Error: Debug> {
30    fn from_wire(buf: Span<'a>) -> IResult<Span<'a>, Self, Error>
31    where
32        Self: Sized;
33}
34
35/// Generic trait Readable Protocol Data Unit that does need a single external
36/// input
37pub trait ReadablePduWithOneInput<'a, T, ErrorType> {
38    fn from_wire(buf: Span<'a>, input: T) -> IResult<Span<'a>, Self, ErrorType>
39    where
40        Self: Sized;
41}
42
43/// Generic trait for Readable Protocol Data Unit that does need two external
44/// inputs
45pub trait ReadablePduWithTwoInputs<'a, T, U, ErrorType> {
46    fn from_wire(buf: Span<'a>, input1: T, input2: U) -> IResult<Span<'a>, Self, ErrorType>
47    where
48        Self: Sized;
49}
50
51/// Generic trait for Readable Protocol Data Unit that does need three external
52/// inputs
53pub trait ReadablePduWithThreeInputs<'a, I1, I2, I3, ErrorType> {
54    fn from_wire(
55        buf: Span<'a>,
56        input1: I1,
57        input2: I2,
58        input3: I3,
59    ) -> IResult<Span<'a>, Self, ErrorType>
60    where
61        Self: Sized;
62}
63
64/// Generic trait for Writable Protocol Data Unit that doesn't need any external
65/// input while writing the packet.
66#[allow(clippy::len_without_is_empty)]
67pub trait WritablePdu<ErrorType> {
68    const BASE_LENGTH: usize;
69
70    /// The total length of the written buffer
71    ///
72    /// *Note*: the [`Self::len`] might be less than the length value written in
73    /// the PDU, since most PDUs don't include the length of their 'length'
74    /// field in the calculation
75    fn len(&self) -> usize;
76
77    fn write<T: std::io::Write>(&self, _writer: &mut T) -> Result<(), ErrorType>
78    where
79        Self: Sized;
80}
81
82/// Generic trait for Writable Protocol Data Unit that doesn't need any external
83/// input while writing the packet.
84#[allow(clippy::len_without_is_empty)]
85pub trait WritablePduWithOneInput<I, ErrorType> {
86    const BASE_LENGTH: usize;
87
88    /// The total length of the written buffer
89    ///
90    /// *Note*: the [`Self::len`] might be less than the length value written in
91    /// the PDU, since most PDUs don't include the length of their 'length'
92    /// field in the calculation
93    fn len(&self, input: I) -> usize;
94
95    fn write<T: std::io::Write>(&self, _writer: &mut T, input: I) -> Result<(), ErrorType>
96    where
97        Self: Sized;
98}
99
100/// Generic trait for Writable Protocol Data Unit that doesn't need any external
101/// input while writing the packet.
102#[allow(clippy::len_without_is_empty)]
103pub trait WritablePduWithTwoInputs<I1, I2, ErrorType> {
104    const BASE_LENGTH: usize;
105
106    /// The total length of the written buffer
107    ///
108    /// *Note*: the [`Self::len`] might be less than the length value written in
109    /// the PDU, since most PDUs don't include the length of their 'length'
110    /// field in the calculation
111    fn len(&self, input1: I1, input2: I2) -> usize;
112
113    fn write<T: std::io::Write>(
114        &self,
115        _writer: &mut T,
116        input1: I1,
117        input2: I2,
118    ) -> Result<(), ErrorType>
119    where
120        Self: Sized;
121}
122
123/// Located Parsing error is the error raised by parsing a given buffer and a
124/// reference to the location where it occurred. The offset of the buffer in the
125/// [`Span`] should refer (as much as possible) to the first byte where the
126/// error started
127pub trait LocatedParsingError {
128    type Span;
129    type Error;
130
131    fn span(&self) -> &Self::Span;
132    fn error(&self) -> &Self::Error;
133}
134
135#[inline]
136pub fn parse_into_located<'a, Lin: Debug, L: From<Lin>, T: ReadablePdu<'a, Lin>>(
137    buf: Span<'a>,
138) -> IResult<Span<'a>, T, L> {
139    match T::from_wire(buf) {
140        Ok((buf, value)) => Ok((buf, value)),
141        Err(err) => match err {
142            nom::Err::Incomplete(needed) => Err(nom::Err::Incomplete(needed)),
143            nom::Err::Error(error) => Err(nom::Err::Error(error.into())),
144            nom::Err::Failure(failure) => Err(nom::Err::Failure(failure.into())),
145        },
146    }
147}
148
149#[inline]
150pub fn parse_into_located_one_input<
151    'a,
152    I,
153    Lin: Debug,
154    L: From<Lin>,
155    T: ReadablePduWithOneInput<'a, I, Lin>,
156>(
157    buf: Span<'a>,
158    input: I,
159) -> IResult<Span<'a>, T, L> {
160    match T::from_wire(buf, input) {
161        Ok((buf, value)) => Ok((buf, value)),
162        Err(err) => match err {
163            nom::Err::Incomplete(needed) => Err(nom::Err::Incomplete(needed)),
164            nom::Err::Error(error) => Err(nom::Err::Error(error.into())),
165            nom::Err::Failure(failure) => Err(nom::Err::Failure(failure.into())),
166        },
167    }
168}
169
170#[inline]
171pub fn parse_into_located_two_inputs<
172    'a,
173    I1,
174    I2,
175    Lin: Debug,
176    L: From<Lin>,
177    T: ReadablePduWithTwoInputs<'a, I1, I2, Lin>,
178>(
179    buf: Span<'a>,
180    input1: I1,
181    input2: I2,
182) -> IResult<Span<'a>, T, L> {
183    match T::from_wire(buf, input1, input2) {
184        Ok((buf, value)) => Ok((buf, value)),
185        Err(err) => match err {
186            nom::Err::Incomplete(needed) => Err(nom::Err::Incomplete(needed)),
187            nom::Err::Error(error) => Err(nom::Err::Error(error.into())),
188            nom::Err::Failure(failure) => Err(nom::Err::Failure(failure.into())),
189        },
190    }
191}
192
193#[inline]
194pub fn parse_into_located_three_inputs<
195    'a,
196    I1,
197    I2,
198    I3,
199    Lin: Debug,
200    L: From<Lin>,
201    T: ReadablePduWithThreeInputs<'a, I1, I2, I3, Lin>,
202>(
203    buf: Span<'a>,
204    input1: I1,
205    input2: I2,
206    input3: I3,
207) -> IResult<Span<'a>, T, L> {
208    match T::from_wire(buf, input1, input2, input3) {
209        Ok((buf, value)) => Ok((buf, value)),
210        Err(err) => match err {
211            nom::Err::Incomplete(needed) => Err(nom::Err::Incomplete(needed)),
212            nom::Err::Error(error) => Err(nom::Err::Error(error.into())),
213            nom::Err::Failure(failure) => Err(nom::Err::Failure(failure.into())),
214        },
215    }
216}
217
218/// Keep repeating the parser till the buf is empty
219#[inline]
220pub fn parse_till_empty<'a, T: ReadablePdu<'a, E>, E: Debug>(
221    buf: Span<'a>,
222) -> IResult<Span<'a>, Vec<T>, E> {
223    let mut buf = buf;
224    let mut ret = Vec::new();
225    while !buf.is_empty() {
226        let (tmp, element) = T::from_wire(buf)?;
227        ret.push(element);
228        buf = tmp;
229    }
230    Ok((buf, ret))
231}
232
233/// Keep repeating the parser till the buf is empty
234#[inline]
235pub fn parse_till_empty_into_located<'a, Lin: Debug, L: From<Lin>, T: ReadablePdu<'a, Lin>>(
236    buf: Span<'a>,
237) -> IResult<Span<'a>, Vec<T>, L> {
238    let mut buf = buf;
239    let mut ret = Vec::new();
240    while !buf.is_empty() {
241        let (tmp, element) = parse_into_located(buf)?;
242        ret.push(element);
243        buf = tmp;
244    }
245    Ok((buf, ret))
246}
247
248/// Keep repeating the parser till the buf is empty
249#[inline]
250pub fn parse_till_empty_with_one_input<
251    'a,
252    I: Clone,
253    T: ReadablePduWithOneInput<'a, I, E>,
254    E: Debug,
255>(
256    buf: Span<'a>,
257    input: I,
258) -> IResult<Span<'a>, Vec<T>, E> {
259    let mut buf = buf;
260    let mut ret = Vec::new();
261    while !buf.is_empty() {
262        let (tmp, element) = T::from_wire(buf, input.clone())?;
263        ret.push(element);
264        buf = tmp;
265    }
266    Ok((buf, ret))
267}
268
269/// Keep repeating the parser till the buf is empty
270#[inline]
271pub fn parse_till_empty_into_with_one_input_located<
272    'a,
273    I: Clone,
274    Lin: Debug,
275    L: From<Lin>,
276    T: ReadablePduWithOneInput<'a, I, Lin>,
277>(
278    buf: Span<'a>,
279    input: I,
280) -> IResult<Span<'a>, Vec<T>, L> {
281    let mut buf = buf;
282    let mut ret = Vec::new();
283    while !buf.is_empty() {
284        let (tmp, element) = parse_into_located_one_input(buf, input.clone())?;
285        ret.push(element);
286        buf = tmp;
287    }
288    Ok((buf, ret))
289}
290
291/// Keep repeating the parser till the buf is empty
292#[inline]
293pub fn parse_till_empty_into_with_two_inputs_located<
294    'a,
295    I1: Clone,
296    I2: Clone,
297    Lin: Debug,
298    L: From<Lin>,
299    T: ReadablePduWithTwoInputs<'a, I1, I2, Lin>,
300>(
301    buf: Span<'a>,
302    input1: I1,
303    input2: I2,
304) -> IResult<Span<'a>, Vec<T>, L> {
305    let mut buf = buf;
306    let mut ret = Vec::new();
307    while !buf.is_empty() {
308        let (tmp, element) = parse_into_located_two_inputs(buf, input1.clone(), input2.clone())?;
309        ret.push(element);
310        buf = tmp;
311    }
312    Ok((buf, ret))
313}
314
315/// Keep repeating the parser till the buf is empty
316#[inline]
317pub fn parse_till_empty_into_with_three_inputs_located<
318    'a,
319    I1: Clone,
320    I2: Clone,
321    I3: Clone,
322    Lin: Debug,
323    L: From<Lin>,
324    T: ReadablePduWithThreeInputs<'a, I1, I2, I3, Lin>,
325>(
326    buf: Span<'a>,
327    input1: I1,
328    input2: I2,
329    input3: I3,
330) -> IResult<Span<'a>, Vec<T>, L> {
331    let mut buf = buf;
332    let mut ret = Vec::new();
333    while !buf.is_empty() {
334        let (tmp, element) =
335            parse_into_located_three_inputs(buf, input1.clone(), input2.clone(), input3.clone())?;
336        ret.push(element);
337        buf = tmp;
338    }
339    Ok((buf, ret))
340}
341
342#[derive(Debug, serde::Serialize, serde::Deserialize)]
343#[serde(remote = "nom::error::ErrorKind")]
344pub enum ErrorKindSerdeDeref {
345    Tag,
346    MapRes,
347    MapOpt,
348    Alt,
349    IsNot,
350    IsA,
351    SeparatedList,
352    SeparatedNonEmptyList,
353    Many0,
354    Many1,
355    ManyTill,
356    Count,
357    TakeUntil,
358    LengthValue,
359    TagClosure,
360    Alpha,
361    Digit,
362    HexDigit,
363    OctDigit,
364    AlphaNumeric,
365    Space,
366    MultiSpace,
367    LengthValueFn,
368    Eof,
369    Switch,
370    TagBits,
371    OneOf,
372    NoneOf,
373    Char,
374    CrLf,
375    RegexpMatch,
376    RegexpMatches,
377    RegexpFind,
378    RegexpCapture,
379    RegexpCaptures,
380    TakeWhile1,
381    Complete,
382    Fix,
383    Escaped,
384    EscapedTransform,
385    NonEmpty,
386    ManyMN,
387    Not,
388    Permutation,
389    Verify,
390    TakeTill1,
391    TakeWhileMN,
392    TooLarge,
393    Many0Count,
394    Many1Count,
395    Float,
396    Satisfy,
397    Fail,
398}