netlink_packet_core/
error.rs1use std::{fmt, io, mem::size_of};
4
5use byteorder::{ByteOrder, NativeEndian};
6
7use crate::{DecodeError, Emitable, Field, Parseable, Rest};
8
9const CODE: Field = 0..4;
10const PAYLOAD: Rest = 4..;
11const ERROR_HEADER_LEN: usize = PAYLOAD.start;
12
13#[derive(Debug, PartialEq, Eq, Clone)]
14pub struct ErrorBuffer<T> {
15 buffer: T,
16}
17
18impl<T: AsRef<[u8]>> ErrorBuffer<T> {
19 pub fn new(buffer: T) -> ErrorBuffer<T> {
20 ErrorBuffer { buffer }
21 }
22
23 pub fn into_inner(self) -> T {
25 self.buffer
26 }
27
28 pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
29 let packet = Self::new(buffer);
30 packet.check_buffer_length()?;
31 Ok(packet)
32 }
33
34 fn check_buffer_length(&self) -> Result<(), DecodeError> {
35 let len = self.buffer.as_ref().len();
36 if len < ERROR_HEADER_LEN {
37 Err(format!(
38 "invalid ErrorBuffer: length is {} but ErrorBuffer are at least {} bytes",
39 len, ERROR_HEADER_LEN
40 )
41 .into())
42 } else {
43 Ok(())
44 }
45 }
46
47 pub fn code(&self) -> i32 {
49 let data = self.buffer.as_ref();
50 NativeEndian::read_i32(&data[CODE])
51 }
52}
53
54impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
55 pub fn payload(&self) -> &'a [u8] {
57 let data = self.buffer.as_ref();
58 &data[PAYLOAD]
59 }
60}
61
62impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&'a mut T> {
63 pub fn payload_mut(&mut self) -> &mut [u8] {
65 let data = self.buffer.as_mut();
66 &mut data[PAYLOAD]
67 }
68}
69
70impl<T: AsRef<[u8]> + AsMut<[u8]>> ErrorBuffer<T> {
71 pub fn set_code(&mut self, value: i32) {
73 let data = self.buffer.as_mut();
74 NativeEndian::write_i32(&mut data[CODE], value)
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct ErrorMessage {
80 pub code: i32,
81 pub header: Vec<u8>,
82}
83
84pub type AckMessage = ErrorMessage;
85
86impl Emitable for ErrorMessage {
87 fn buffer_len(&self) -> usize {
88 size_of::<i32>() + self.header.len()
89 }
90 fn emit(&self, buffer: &mut [u8]) {
91 let mut buffer = ErrorBuffer::new(buffer);
92 buffer.set_code(self.code);
93 buffer.payload_mut().copy_from_slice(&self.header)
94 }
95}
96
97impl<'buffer, T: AsRef<[u8]> + 'buffer> Parseable<ErrorBuffer<&'buffer T>> for ErrorMessage {
98 fn parse(buf: &ErrorBuffer<&'buffer T>) -> Result<ErrorMessage, DecodeError> {
99 Ok(ErrorMessage {
108 code: buf.code(),
109 header: buf.payload().to_vec(),
110 })
111 }
112}
113
114impl ErrorMessage {
115 pub fn to_io(&self) -> io::Error {
121 io::Error::from_raw_os_error(self.code.abs())
122 }
123}
124
125impl fmt::Display for ErrorMessage {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 fmt::Display::fmt(&self.to_io(), f)
128 }
129}
130
131impl From<ErrorMessage> for io::Error {
132 fn from(e: ErrorMessage) -> io::Error {
133 e.to_io()
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn into_io_error() {
143 let io_err = io::Error::from_raw_os_error(95);
144 let err_msg = ErrorMessage {
145 code: -95,
146 header: vec![],
147 };
148
149 let to_io: io::Error = err_msg.to_io();
150
151 assert_eq!(err_msg.to_string(), io_err.to_string());
152 assert_eq!(to_io.raw_os_error(), io_err.raw_os_error());
153 }
154}