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}