c_its_parser/transport/
decode.rs1use etherparse::PacketHeaders;
2use nom::bytes::streaming::take;
3use nom::combinator::{into, map_res};
4use nom::error::{ErrorKind, FromExternalError, ParseError};
5use nom::sequence::pair;
6
7use crate::transport::{BasicTransportAHeader, BasicTransportBHeader, IPv6Header};
8
9#[derive(Debug, PartialEq)]
10pub enum DecodeError<I> {
11 IntegerError(alloc::string::String),
12 IPv6Parsing(alloc::string::String),
13 Nom(I, ErrorKind),
14 #[cfg(feature = "json")]
15 Json(alloc::string::String),
16}
17
18impl<I> ParseError<I> for DecodeError<I> {
19 fn from_error_kind(input: I, kind: ErrorKind) -> Self {
20 DecodeError::Nom(input, kind)
21 }
22
23 fn append(_: I, _: ErrorKind, other: Self) -> Self {
24 other
25 }
26}
27
28impl<I, E> FromExternalError<I, E> for DecodeError<I> {
29 fn from_external_error(input: I, kind: ErrorKind, _: E) -> Self {
30 DecodeError::Nom(input, kind)
31 }
32}
33
34pub type IResult<I, T> = nom::IResult<I, T, DecodeError<I>>;
35
36pub trait Decode: Sized {
37 fn decode(input: &[u8]) -> IResult<&[u8], Self>;
53}
54
55impl Decode for BasicTransportAHeader {
56 fn decode(input: &[u8]) -> IResult<&[u8], Self> {
57 into(pair(u16_from_be_bytes, u16_from_be_bytes))(input)
58 }
59}
60
61impl From<(u16, u16)> for BasicTransportAHeader {
62 fn from(value: (u16, u16)) -> Self {
63 Self {
64 destination_port: value.0,
65 source_port: value.1,
66 }
67 }
68}
69
70impl BasicTransportAHeader {
71 #[cfg(feature = "json")]
72 pub fn decode_from_json(input: &str) -> Result<Self, DecodeError<&str>> {
77 serde_json::from_str(input)
78 .map_err(|e| DecodeError::Json(alloc::format!("Error encoding to JSON: {e:?}")))
79 }
80}
81
82impl Decode for BasicTransportBHeader {
83 fn decode(input: &[u8]) -> IResult<&[u8], Self> {
84 into(pair(u16_from_be_bytes, u16_from_be_bytes))(input)
85 }
86}
87
88impl From<(u16, u16)> for BasicTransportBHeader {
89 fn from(value: (u16, u16)) -> Self {
90 Self {
91 destination_port: value.0,
92 destination_port_info: value.1,
93 }
94 }
95}
96
97impl BasicTransportBHeader {
98 #[cfg(feature = "json")]
99 pub fn decode_from_json(input: &str) -> Result<Self, DecodeError<&str>> {
104 serde_json::from_str(input)
105 .map_err(|e| DecodeError::Json(alloc::format!("Error encoding to JSON: {e:?}")))
106 }
107}
108
109fn u16_from_be_bytes(input: &[u8]) -> IResult<&[u8], u16> {
110 map_res(take(2usize), |slice: &[u8]| {
111 slice.try_into().map(u16::from_be_bytes).map_err(|e| {
112 DecodeError::IntegerError::<&[u8]>(alloc::format!(
113 "Failed to construct integer from bytes: {e:?}"
114 ))
115 })
116 })(input)
117}
118
119impl Decode for IPv6Header {
120 fn decode(input: &[u8]) -> IResult<&[u8], Self> {
121 etherparse::PacketHeaders::from_ip_slice(input)
122 .map(|headers| {
123 let first_after_headers = headers
124 .net
125 .as_ref()
126 .map_or(0, etherparse::NetHeaders::header_len)
127 + headers
128 .link
129 .as_ref()
130 .map_or(0, etherparse::LinkHeader::header_len)
131 + headers
132 .transport
133 .as_ref()
134 .map_or(0, etherparse::TransportHeader::header_len)
135 + headers
136 .link_exts
137 .first()
138 .map_or(0, etherparse::LinkExtHeader::header_len);
139 (&input[first_after_headers..], IPv6Header::from(headers))
140 })
141 .map_err(|e| {
142 nom::Err::Error(DecodeError::IPv6Parsing(alloc::format!(
143 "Error parsing IPv6 Header: {e:?}"
144 )))
145 })
146 }
147}
148
149impl From<PacketHeaders<'_>> for IPv6Header {
150 fn from(value: PacketHeaders<'_>) -> Self {
151 Self {
152 ip: value.net,
153 link: value.link,
154 transport: value.transport,
155 link_ext: value.link_exts.first().cloned(),
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {}