Skip to content

Commit 5f65820

Browse files
committed
parser: Copy from utils
Signed-off-by: Enrique Llorente <[email protected]>
1 parent 93e18e2 commit 5f65820

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed

src/error.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ where
4040
}
4141
}
4242

43+
4344
impl From<&str> for DecodeError{
4445
fn from(msg: &str) -> Self {
4546
Self {
@@ -56,6 +57,13 @@ impl From<String> for DecodeError{
5657
}
5758
}
5859

60+
impl From<std::string::FromUtf8Error> for DecodeError{
61+
fn from(err: std::string::FromUtf8Error) -> Self {
62+
Self {
63+
msg: format!("Invalid UTF-8 sequence: {}", err),
64+
}
65+
}
66+
}
5967

6068
impl std::fmt::Display for DecodeError {
6169
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -65,6 +73,26 @@ impl std::fmt::Display for DecodeError {
6573

6674
impl std::error::Error for DecodeError {}
6775

76+
impl DecodeError {
77+
pub fn invalid_mac_address(received: usize) -> Self {
78+
Self{
79+
msg: format!("Invalid MAC address. Expected 6 bytes, received {received} bytes"),
80+
}
81+
}
82+
83+
pub fn invalid_ip_address(received: usize) -> Self {
84+
Self{
85+
msg: format!("Invalid IP address. Expected 4 or 16 bytes, received {received} bytes"),
86+
}
87+
}
88+
89+
pub fn invalid_number(expected: usize, received: usize) -> Self {
90+
Self{
91+
msg: format!("Invalid number. Expected {expected} bytes, received {received} bytes"),
92+
}
93+
}
94+
}
95+
6896
#[derive(Debug, PartialEq, Eq, Clone)]
6997
#[non_exhaustive]
7098
pub struct ErrorBuffer<T> {

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,5 +268,8 @@ pub use self::message::*;
268268
pub mod constants;
269269
pub use self::constants::*;
270270

271+
pub mod parsers;
272+
pub use self::parsers::*;
273+
271274
#[macro_use]
272275
mod macros;

src/parsers.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
use std::{
4+
mem::size_of,
5+
net::{IpAddr, Ipv4Addr, Ipv6Addr},
6+
};
7+
8+
use byteorder::{BigEndian, ByteOrder, NativeEndian};
9+
10+
use crate::{DecodeError};
11+
12+
pub fn parse_mac(payload: &[u8]) -> Result<[u8; 6], DecodeError> {
13+
if payload.len() != 6 {
14+
return Err(DecodeError::invalid_mac_address(payload.len()));
15+
}
16+
let mut address: [u8; 6] = [0; 6];
17+
for (i, byte) in payload.iter().enumerate() {
18+
address[i] = *byte;
19+
}
20+
Ok(address)
21+
}
22+
23+
pub fn parse_ipv6(payload: &[u8]) -> Result<[u8; 16], DecodeError> {
24+
if payload.len() != 16 {
25+
return Err(DecodeError::invalid_ip_address(payload.len()));
26+
}
27+
let mut address: [u8; 16] = [0; 16];
28+
for (i, byte) in payload.iter().enumerate() {
29+
address[i] = *byte;
30+
}
31+
Ok(address)
32+
}
33+
34+
pub fn parse_ip(payload: &[u8]) -> Result<IpAddr, DecodeError> {
35+
match payload.len() {
36+
4 => Ok(
37+
Ipv4Addr::new(payload[0], payload[1], payload[2], payload[3])
38+
.into(),
39+
),
40+
16 => Ok(Ipv6Addr::from([
41+
payload[0],
42+
payload[1],
43+
payload[2],
44+
payload[3],
45+
payload[4],
46+
payload[5],
47+
payload[6],
48+
payload[7],
49+
payload[8],
50+
payload[9],
51+
payload[10],
52+
payload[11],
53+
payload[12],
54+
payload[13],
55+
payload[14],
56+
payload[15],
57+
])
58+
.into()),
59+
other => Err(DecodeError::invalid_ip_address( other )),
60+
}
61+
}
62+
63+
pub fn parse_string(payload: &[u8]) -> Result<String, DecodeError> {
64+
if payload.is_empty() {
65+
return Ok(String::new());
66+
}
67+
// iproute2 is a bit inconsistent with null-terminated strings.
68+
let slice = if payload[payload.len() - 1] == 0 {
69+
&payload[..payload.len() - 1]
70+
} else {
71+
&payload[..payload.len()]
72+
};
73+
let s = String::from_utf8(slice.to_vec())?;
74+
Ok(s)
75+
}
76+
77+
pub fn parse_u8(payload: &[u8]) -> Result<u8, DecodeError> {
78+
if payload.len() != 1 {
79+
return Err(DecodeError::invalid_number(1, payload.len()));
80+
}
81+
Ok(payload[0])
82+
}
83+
84+
pub fn parse_i8(payload: &[u8]) -> Result<i8, DecodeError> {
85+
if payload.len() != 1 {
86+
return Err(DecodeError::invalid_number(1, payload.len()));
87+
}
88+
Ok(payload[0] as i8)
89+
}
90+
91+
pub fn parse_u32(payload: &[u8]) -> Result<u32, DecodeError> {
92+
if payload.len() != size_of::<u32>() {
93+
return Err(DecodeError::invalid_number(size_of::<u32>(), payload.len()));
94+
}
95+
Ok(NativeEndian::read_u32(payload))
96+
}
97+
98+
pub fn parse_u64(payload: &[u8]) -> Result<u64, DecodeError> {
99+
if payload.len() != size_of::<u64>() {
100+
return Err(DecodeError::invalid_number(size_of::<u64>(), payload.len()));
101+
}
102+
Ok(NativeEndian::read_u64(payload))
103+
}
104+
pub fn parse_u128(payload: &[u8]) -> Result<u128, DecodeError> {
105+
if payload.len() != size_of::<u128>() {
106+
return Err(DecodeError::invalid_number(size_of::<u128>(), payload.len()));
107+
}
108+
Ok(NativeEndian::read_u128(payload))
109+
}
110+
111+
pub fn parse_u16(payload: &[u8]) -> Result<u16, DecodeError> {
112+
if payload.len() != size_of::<u16>() {
113+
return Err(DecodeError::invalid_number(size_of::<u16>(), payload.len()));
114+
}
115+
Ok(NativeEndian::read_u16(payload))
116+
}
117+
118+
pub fn parse_i32(payload: &[u8]) -> Result<i32, DecodeError> {
119+
if payload.len() != 4 {
120+
return Err(DecodeError::invalid_number(4, payload.len()));
121+
}
122+
Ok(NativeEndian::read_i32(payload))
123+
}
124+
125+
pub fn parse_i64(payload: &[u8]) -> Result<i64, DecodeError> {
126+
if payload.len() != 8 {
127+
return Err(format!("invalid i64: {payload:?}").into());
128+
}
129+
Ok(NativeEndian::read_i64(payload))
130+
}
131+
132+
pub fn parse_u16_be(payload: &[u8]) -> Result<u16, DecodeError> {
133+
if payload.len() != size_of::<u16>() {
134+
return Err(DecodeError::invalid_number(size_of::<u16>(), payload.len()));
135+
}
136+
Ok(BigEndian::read_u16(payload))
137+
}
138+
139+
pub fn parse_u32_be(payload: &[u8]) -> Result<u32, DecodeError> {
140+
if payload.len() != size_of::<u32>() {
141+
return Err(DecodeError::invalid_number(size_of::<u32>(), payload.len()));
142+
}
143+
Ok(BigEndian::read_u32(payload))
144+
}

0 commit comments

Comments
 (0)