Skip to main content

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
18pub mod common;
19pub mod error;
20pub mod reader;
21#[cfg(feature = "test-helpers")]
22pub mod test_helpers;
23pub mod traits;
24
25/// Generates `From<std::io::Error>` for one or more serializer error enums.
26///
27/// Serializer errors store the IO failure as a string rather than a
28/// [`std::io::Error`], because they derive `Eq`/`PartialEq`/`Clone` (the
29/// `test_write*` helpers require `E: Eq`) and `std::io::Error` implements none
30/// of those. That lossy conversion is why `thiserror`'s `#[from]` cannot be
31/// used here: it requires the variant field to *be* the source error type.
32///
33/// Each enum is expected to carry a `StdIOError` variant holding anything
34/// convertible from [`String`] — [`Box<str>`] is preferred, since it is 8 bytes
35/// smaller and these errors sit in the `Result` of every write call. Pass
36/// `Type => Variant` explicitly if the variant is spelled differently.
37///
38/// ```
39/// # use netgauze_parse_utils::impl_from_io_error;
40/// #[derive(thiserror::Error, Eq, PartialEq, Clone, Debug)]
41/// pub enum MyWritingError {
42///     #[error("IO error while writing: {0}")]
43///     StdIOError(Box<str>),
44/// }
45/// impl_from_io_error!(MyWritingError);
46/// ```
47#[macro_export]
48macro_rules! impl_from_io_error {
49    ($($ty:ty),+ $(,)?) => {
50        $( $crate::impl_from_io_error!($ty => StdIOError); )+
51    };
52    ($ty:ty => $variant:ident) => {
53        #[automatically_derived]
54        impl From<std::io::Error> for $ty {
55            fn from(err: std::io::Error) -> Self {
56                // `.into()` so the variant can hold `Box<str>` or `String`
57                <$ty>::$variant(err.to_string().into())
58            }
59        }
60    };
61}
62
63/// Generic trait for Writable Protocol Data Unit that doesn't need any external
64/// input while writing the packet.
65#[allow(clippy::len_without_is_empty)]
66pub trait WritablePdu<ErrorType> {
67    const BASE_LENGTH: usize;
68
69    /// The total length of the written buffer
70    ///
71    /// *Note*: the [`Self::len`] might be less than the length value written in
72    /// the PDU, since most PDUs don't include the length of their 'length'
73    /// field in the calculation
74    fn len(&self) -> usize;
75
76    fn write<T: std::io::Write>(&self, _writer: &mut T) -> Result<(), ErrorType>
77    where
78        Self: Sized;
79}
80
81/// Generic trait for Writable Protocol Data Unit that doesn't need any external
82/// input while writing the packet.
83#[allow(clippy::len_without_is_empty)]
84pub trait WritablePduWithOneInput<I, ErrorType> {
85    const BASE_LENGTH: usize;
86
87    /// The total length of the written buffer
88    ///
89    /// *Note*: the [`Self::len`] might be less than the length value written in
90    /// the PDU, since most PDUs don't include the length of their 'length'
91    /// field in the calculation
92    fn len(&self, input: I) -> usize;
93
94    fn write<T: std::io::Write>(&self, _writer: &mut T, input: I) -> Result<(), ErrorType>
95    where
96        Self: Sized;
97}
98
99/// Generic trait for Writable Protocol Data Unit that doesn't need any external
100/// input while writing the packet.
101#[allow(clippy::len_without_is_empty)]
102pub trait WritablePduWithTwoInputs<I1, I2, ErrorType> {
103    const BASE_LENGTH: usize;
104
105    /// The total length of the written buffer
106    ///
107    /// *Note*: the [`Self::len`] might be less than the length value written in
108    /// the PDU, since most PDUs don't include the length of their 'length'
109    /// field in the calculation
110    fn len(&self, input1: I1, input2: I2) -> usize;
111
112    fn write<T: std::io::Write>(
113        &self,
114        _writer: &mut T,
115        input1: I1,
116        input2: I2,
117    ) -> Result<(), ErrorType>
118    where
119        Self: Sized;
120}