33use std:: { fmt, io, mem:: size_of, num:: NonZeroI32 } ;
44
55use byteorder:: { ByteOrder , NativeEndian } ;
6- use netlink_packet_utils:: DecodeError ;
76
87use crate :: { Emitable , Field , Parseable , Rest } ;
98
109const CODE : Field = 0 ..4 ;
1110const PAYLOAD : Rest = 4 ..;
1211const 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 From < std:: string:: FromUtf8Error > for DecodeError {
57+ fn from ( err : std:: string:: FromUtf8Error ) -> Self {
58+ Self {
59+ msg : format ! ( "Invalid UTF-8 sequence: {}" , err) ,
60+ }
61+ }
62+ }
63+
64+ impl std:: fmt:: Display for DecodeError {
65+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
66+ write ! ( f, "{}" , self . msg)
67+ }
68+ }
69+
70+ impl std:: error:: Error for DecodeError { }
71+
72+ impl DecodeError {
73+ pub fn invalid_mac_address ( received : usize ) -> Self {
74+ Self {
75+ msg : format ! ( "Invalid MAC address. Expected 6 bytes, received {received} bytes" ) ,
76+ }
77+ }
78+
79+ pub fn invalid_ip_address ( received : usize ) -> Self {
80+ Self {
81+ msg : format ! ( "Invalid IP address. Expected 4 or 16 bytes, received {received} bytes" ) ,
82+ }
83+ }
84+
85+ pub fn invalid_number ( expected : usize , received : usize ) -> Self {
86+ Self {
87+ msg : format ! ( "Invalid number. Expected {expected} bytes, received {received} bytes" ) ,
88+ }
89+ }
90+ }
91+
1492#[ derive( Debug , PartialEq , Eq , Clone ) ]
1593#[ non_exhaustive]
1694pub struct ErrorBuffer < T > {
@@ -29,18 +107,21 @@ impl<T: AsRef<[u8]>> ErrorBuffer<T> {
29107
30108 pub fn new_checked ( buffer : T ) -> Result < Self , DecodeError > {
31109 let packet = Self :: new ( buffer) ;
32- packet. check_buffer_length ( ) ?;
110+ packet
111+ . check_buffer_length ( )
112+ . context ( "invalid ErrorBuffer length" ) ?;
33113 Ok ( packet)
34114 }
35115
36116 fn check_buffer_length ( & self ) -> Result < ( ) , DecodeError > {
37117 let len = self . buffer . as_ref ( ) . len ( ) ;
38118 if len < ERROR_HEADER_LEN {
39- Err ( format ! (
40- "invalid ErrorBuffer: length is {len} but ErrorBuffer are \
119+ Err ( DecodeError {
120+ msg : format ! (
121+ "invalid ErrorBuffer: length is {len} but ErrorBuffer are \
41122 at least {ERROR_HEADER_LEN} bytes"
42- )
43- . into ( ) )
123+ ) ,
124+ } )
44125 } else {
45126 Ok ( ( ) )
46127 }
@@ -65,7 +146,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
65146 }
66147}
67148
68- impl < ' a , T : AsRef < [ u8 ] > + AsMut < [ u8 ] > + ?Sized > ErrorBuffer < & ' a mut T > {
149+ impl < T : AsRef < [ u8 ] > + AsMut < [ u8 ] > + ?Sized > ErrorBuffer < & mut T > {
69150 /// Return a mutable pointer to the payload.
70151 pub fn payload_mut ( & mut self ) -> & mut [ u8 ] {
71152 let data = self . buffer . as_mut ( ) ;
@@ -199,8 +280,7 @@ mod tests {
199280 #[ test]
200281 fn parse_nack ( ) {
201282 // SAFETY: value is non-zero.
202- const ERROR_CODE : NonZeroI32 =
203- unsafe { NonZeroI32 :: new_unchecked ( -1234 ) } ;
283+ const ERROR_CODE : NonZeroI32 = NonZeroI32 :: new ( -1234 ) . unwrap ( ) ;
204284 let mut bytes = vec ! [ 0 , 0 , 0 , 0 ] ;
205285 NativeEndian :: write_i32 ( & mut bytes, ERROR_CODE . get ( ) ) ;
206286 let msg = ErrorBuffer :: new_checked ( & bytes)
0 commit comments