Skip to content

Commit 6e73b5f

Browse files
committed
errors: Move DecodeError from utils
Signed-off-by: Enrique Llorente <[email protected]>
1 parent 01e8dd1 commit 6e73b5f

File tree

5 files changed

+104
-49
lines changed

5 files changed

+104
-49
lines changed

src/buffer.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// SPDX-License-Identifier: MIT
22

33
use byteorder::{ByteOrder, NativeEndian};
4-
use netlink_packet_utils::DecodeError;
54

6-
use crate::{Field, Rest};
5+
use crate::{DecodeError, ErrorContext, Field, Rest};
76

87
const LENGTH: Field = 0..4;
98
const MESSAGE_TYPE: Field = 4..6;
@@ -158,7 +157,7 @@ impl<T: AsRef<[u8]>> NetlinkBuffer<T> {
158157
/// ```
159158
pub fn new_checked(buffer: T) -> Result<NetlinkBuffer<T>, DecodeError> {
160159
let packet = Self::new(buffer);
161-
packet.check_buffer_length()?;
160+
packet.check_buffer_length().context("invalid netlink buffer length")?;
162161
Ok(packet)
163162
}
164163

@@ -331,7 +330,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> NetlinkBuffer<&'a T> {
331330
}
332331
}
333332

334-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NetlinkBuffer<&'a mut T> {
333+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NetlinkBuffer<&mut T> {
335334
/// Return a mutable pointer to the payload.
336335
///
337336
/// # Panic

src/done.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
use std::mem::size_of;
44

55
use byteorder::{ByteOrder, NativeEndian};
6-
use netlink_packet_utils::DecodeError;
76

8-
use crate::{Emitable, Field, Parseable, Rest};
7+
use crate::{DecodeError, Emitable, ErrorContext, Field, Parseable, Rest};
98

109
const CODE: Field = 0..4;
1110
const EXTENDED_ACK: Rest = 4..;
@@ -29,7 +28,9 @@ impl<T: AsRef<[u8]>> DoneBuffer<T> {
2928

3029
pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
3130
let packet = Self::new(buffer);
32-
packet.check_buffer_length()?;
31+
packet
32+
.check_buffer_length()
33+
.context("invalid DoneBuffer length")?;
3334
Ok(packet)
3435
}
3536

@@ -61,7 +62,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> DoneBuffer<&'a T> {
6162
}
6263
}
6364

64-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> DoneBuffer<&'a mut T> {
65+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> DoneBuffer<&mut T> {
6566
/// Return a mutable pointer to the extended ack attributes.
6667
pub fn extended_ack_mut(&mut self) -> &mut [u8] {
6768
let data = self.buffer.as_mut();

src/error.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,64 @@
33
use std::{fmt, io, mem::size_of, num::NonZeroI32};
44

55
use byteorder::{ByteOrder, NativeEndian};
6-
use netlink_packet_utils::DecodeError;
76

87
use crate::{Emitable, Field, Parseable, Rest};
98

109
const CODE: Field = 0..4;
1110
const PAYLOAD: Rest = 4..;
1211
const ERROR_HEADER_LEN: usize = PAYLOAD.start;
1312

13+
pub trait ErrorContext {
14+
fn context(self, msg: &str) -> Self;
15+
}
16+
17+
#[derive(Debug)]
18+
pub struct DecodeError {
19+
msg: String,
20+
}
21+
22+
impl ErrorContext for DecodeError {
23+
fn context(self, msg: &str) -> Self {
24+
Self {
25+
msg: format!("{} caused by {}", msg, self.msg),
26+
}
27+
}
28+
}
29+
30+
impl<T> ErrorContext for Result<T, DecodeError>
31+
where
32+
T: Clone,
33+
{
34+
fn context(self, msg: &str) -> Result<T, DecodeError> {
35+
match self {
36+
Ok(t) => Ok(t),
37+
Err(e) => Err(e.context(msg)),
38+
}
39+
}
40+
}
41+
42+
impl From<&str> for DecodeError {
43+
fn from(msg: &str) -> Self {
44+
Self {
45+
msg: msg.to_string(),
46+
}
47+
}
48+
}
49+
50+
impl From<String> for DecodeError {
51+
fn from(msg: String) -> Self {
52+
Self { msg }
53+
}
54+
}
55+
56+
impl std::fmt::Display for DecodeError {
57+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58+
write!(f, "{}", self.msg)
59+
}
60+
}
61+
62+
impl std::error::Error for DecodeError {}
63+
1464
#[derive(Debug, PartialEq, Eq, Clone)]
1565
#[non_exhaustive]
1666
pub struct ErrorBuffer<T> {
@@ -29,18 +79,21 @@ impl<T: AsRef<[u8]>> ErrorBuffer<T> {
2979

3080
pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
3181
let packet = Self::new(buffer);
32-
packet.check_buffer_length()?;
82+
packet
83+
.check_buffer_length()
84+
.context("invalid ErrorBuffer length")?;
3385
Ok(packet)
3486
}
3587

3688
fn check_buffer_length(&self) -> Result<(), DecodeError> {
3789
let len = self.buffer.as_ref().len();
3890
if len < ERROR_HEADER_LEN {
39-
Err(format!(
40-
"invalid ErrorBuffer: length is {len} but ErrorBuffer are \
91+
Err(DecodeError {
92+
msg: format!(
93+
"invalid ErrorBuffer: length is {len} but ErrorBuffer are \
4194
at least {ERROR_HEADER_LEN} bytes"
42-
)
43-
.into())
95+
),
96+
})
4497
} else {
4598
Ok(())
4699
}
@@ -65,7 +118,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
65118
}
66119
}
67120

68-
impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&'a mut T> {
121+
impl<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&mut T> {
69122
/// Return a mutable pointer to the payload.
70123
pub fn payload_mut(&mut self) -> &mut [u8] {
71124
let data = self.buffer.as_mut();
@@ -200,7 +253,7 @@ mod tests {
200253
fn parse_nack() {
201254
// SAFETY: value is non-zero.
202255
const ERROR_CODE: NonZeroI32 =
203-
unsafe { NonZeroI32::new_unchecked(-1234) };
256+
NonZeroI32::new(-1234).unwrap();
204257
let mut bytes = vec![0, 0, 0, 0];
205258
NativeEndian::write_i32(&mut bytes, ERROR_CODE.get());
206259
let msg = ErrorBuffer::new_checked(&bytes)

src/header.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// SPDX-License-Identifier: MIT
22

3-
use netlink_packet_utils::DecodeError;
4-
5-
use crate::{buffer::NETLINK_HEADER_LEN, Emitable, NetlinkBuffer, Parseable};
3+
use crate::{
4+
buffer::NETLINK_HEADER_LEN, DecodeError, Emitable, NetlinkBuffer, Parseable,
5+
};
66

77
/// A Netlink header representation. A netlink header has the following
88
/// structure:
@@ -111,7 +111,7 @@ mod tests {
111111
port_number: 0,
112112
};
113113
assert_eq!(repr.buffer_len(), 16);
114-
let mut buf = vec![0; 16];
114+
let mut buf = [0; 16];
115115
repr.emit(&mut buf[..]);
116116
assert_eq!(&buf[..], &IP_LINK_SHOW_PKT[..16]);
117117
}

src/message.rs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
use std::fmt::Debug;
44

5-
use netlink_packet_utils::DecodeError;
6-
75
use crate::{
86
payload::{NLMSG_DONE, NLMSG_ERROR, NLMSG_NOOP, NLMSG_OVERRUN},
9-
DoneBuffer, DoneMessage, Emitable, ErrorBuffer, ErrorMessage,
10-
NetlinkBuffer, NetlinkDeserializable, NetlinkHeader, NetlinkPayload,
11-
NetlinkSerializable, Parseable,
7+
DecodeError, DoneBuffer, DoneMessage, Emitable, ErrorBuffer, ErrorContext,
8+
ErrorMessage, NetlinkBuffer, NetlinkDeserializable, NetlinkHeader,
9+
NetlinkPayload, NetlinkSerializable, Parseable,
1210
};
1311

1412
/// Represent a netlink message.
@@ -39,7 +37,8 @@ where
3937
{
4038
/// Parse the given buffer as a netlink message
4139
pub fn deserialize(buffer: &[u8]) -> Result<Self, DecodeError> {
42-
let netlink_buffer = NetlinkBuffer::new_checked(&buffer)?;
40+
let netlink_buffer = NetlinkBuffer::new_checked(&buffer)
41+
.context("failed deserializing NetlinkMessage")?;
4342
<Self as Parseable<NetlinkBuffer<&&[u8]>>>::parse(&netlink_buffer)
4443
}
4544
}
@@ -93,31 +92,34 @@ where
9392
use self::NetlinkPayload::*;
9493

9594
let header =
96-
<NetlinkHeader as Parseable<NetlinkBuffer<&B>>>::parse(buf)?;
95+
<NetlinkHeader as Parseable<NetlinkBuffer<&B>>>::parse(buf)
96+
.context("failed parsing NetlinkHeader")?;
9797

9898
let bytes = buf.payload();
99-
let payload = match header.message_type {
100-
NLMSG_ERROR => {
101-
let msg = ErrorBuffer::new_checked(&bytes)
102-
.and_then(|buf| ErrorMessage::parse(&buf))?;
103-
Error(msg)
104-
}
105-
NLMSG_NOOP => Noop,
106-
NLMSG_DONE => {
107-
let msg = DoneBuffer::new_checked(&bytes)
108-
.and_then(|buf| DoneMessage::parse(&buf))?;
109-
Done(msg)
110-
}
111-
NLMSG_OVERRUN => Overrun(bytes.to_vec()),
112-
message_type => match I::deserialize(&header, bytes) {
113-
Err(e) => {
114-
return Err(DecodeError::Other(
115-
format!("Failed to parse message with type {message_type}: {e}").into()),
116-
);
99+
let payload =
100+
match header.message_type {
101+
NLMSG_ERROR => {
102+
let msg = ErrorBuffer::new_checked(&bytes)
103+
.and_then(|buf| ErrorMessage::parse(&buf))
104+
.context("failed parsing NLMSG_ERROR")?;
105+
Error(msg)
117106
}
118-
Ok(inner_msg) => InnerMessage(inner_msg),
119-
},
120-
};
107+
NLMSG_NOOP => Noop,
108+
NLMSG_DONE => {
109+
let msg = DoneBuffer::new_checked(&bytes)
110+
.and_then(|buf| DoneMessage::parse(&buf))
111+
.context("failed parsing NLMSG_DONE")?;
112+
Done(msg)
113+
}
114+
NLMSG_OVERRUN => Overrun(bytes.to_vec()),
115+
message_type => match I::deserialize(&header, bytes) {
116+
Err(e) => return Err(format!(
117+
"Failed to parse message with type {message_type}: {e}"
118+
)
119+
.into()),
120+
Ok(inner_msg) => InnerMessage(inner_msg),
121+
},
122+
};
121123
Ok(NetlinkMessage { header, payload })
122124
}
123125
}
@@ -239,7 +241,7 @@ mod tests {
239241
fn test_error() {
240242
// SAFETY: value is non-zero.
241243
const ERROR_CODE: NonZeroI32 =
242-
unsafe { NonZeroI32::new_unchecked(-8765) };
244+
NonZeroI32::new(-8765).unwrap();
243245

244246
let header = NetlinkHeader::default();
245247
let error_msg = ErrorMessage {

0 commit comments

Comments
 (0)