@@ -11,16 +11,108 @@ pub mod serde {
1111 use std:: { fmt, io} ;
1212
1313 use serde:: {
14- de:: { self , Visitor } ,
14+ de:: { self , SeqAccess , Visitor } ,
15+ ser:: SerializeTuple ,
1516 Deserializer , Serializer ,
1617 } ;
1718
19+ fn error_kind_to_u8 ( kind : io:: ErrorKind ) -> u8 {
20+ match kind {
21+ io:: ErrorKind :: AddrInUse => 0 ,
22+ io:: ErrorKind :: AddrNotAvailable => 1 ,
23+ io:: ErrorKind :: AlreadyExists => 2 ,
24+ io:: ErrorKind :: ArgumentListTooLong => 3 ,
25+ io:: ErrorKind :: BrokenPipe => 4 ,
26+ io:: ErrorKind :: ConnectionAborted => 5 ,
27+ io:: ErrorKind :: ConnectionRefused => 6 ,
28+ io:: ErrorKind :: ConnectionReset => 7 ,
29+ io:: ErrorKind :: CrossesDevices => 8 ,
30+ io:: ErrorKind :: Deadlock => 9 ,
31+ io:: ErrorKind :: DirectoryNotEmpty => 10 ,
32+ io:: ErrorKind :: ExecutableFileBusy => 11 ,
33+ io:: ErrorKind :: FileTooLarge => 12 ,
34+ io:: ErrorKind :: HostUnreachable => 13 ,
35+ io:: ErrorKind :: Interrupted => 14 ,
36+ io:: ErrorKind :: InvalidData => 15 ,
37+ io:: ErrorKind :: InvalidInput => 17 ,
38+ io:: ErrorKind :: IsADirectory => 18 ,
39+ io:: ErrorKind :: NetworkDown => 19 ,
40+ io:: ErrorKind :: NetworkUnreachable => 20 ,
41+ io:: ErrorKind :: NotADirectory => 21 ,
42+ io:: ErrorKind :: NotConnected => 22 ,
43+ io:: ErrorKind :: NotFound => 23 ,
44+ io:: ErrorKind :: NotSeekable => 24 ,
45+ io:: ErrorKind :: Other => 25 ,
46+ io:: ErrorKind :: OutOfMemory => 26 ,
47+ io:: ErrorKind :: PermissionDenied => 27 ,
48+ io:: ErrorKind :: QuotaExceeded => 28 ,
49+ io:: ErrorKind :: ReadOnlyFilesystem => 29 ,
50+ io:: ErrorKind :: ResourceBusy => 30 ,
51+ io:: ErrorKind :: StaleNetworkFileHandle => 31 ,
52+ io:: ErrorKind :: StorageFull => 32 ,
53+ io:: ErrorKind :: TimedOut => 33 ,
54+ io:: ErrorKind :: TooManyLinks => 34 ,
55+ io:: ErrorKind :: UnexpectedEof => 35 ,
56+ io:: ErrorKind :: Unsupported => 36 ,
57+ io:: ErrorKind :: WouldBlock => 37 ,
58+ io:: ErrorKind :: WriteZero => 38 ,
59+ _ => 25 ,
60+ }
61+ }
62+
63+ fn u8_to_error_kind ( num : u8 ) -> io:: ErrorKind {
64+ match num {
65+ 0 => io:: ErrorKind :: AddrInUse ,
66+ 1 => io:: ErrorKind :: AddrNotAvailable ,
67+ 2 => io:: ErrorKind :: AlreadyExists ,
68+ 3 => io:: ErrorKind :: ArgumentListTooLong ,
69+ 4 => io:: ErrorKind :: BrokenPipe ,
70+ 5 => io:: ErrorKind :: ConnectionAborted ,
71+ 6 => io:: ErrorKind :: ConnectionRefused ,
72+ 7 => io:: ErrorKind :: ConnectionReset ,
73+ 8 => io:: ErrorKind :: CrossesDevices ,
74+ 9 => io:: ErrorKind :: Deadlock ,
75+ 10 => io:: ErrorKind :: DirectoryNotEmpty ,
76+ 11 => io:: ErrorKind :: ExecutableFileBusy ,
77+ 12 => io:: ErrorKind :: FileTooLarge ,
78+ 13 => io:: ErrorKind :: HostUnreachable ,
79+ 14 => io:: ErrorKind :: Interrupted ,
80+ 15 => io:: ErrorKind :: InvalidData ,
81+ // 16 => io::ErrorKind::InvalidFilename,
82+ 17 => io:: ErrorKind :: InvalidInput ,
83+ 18 => io:: ErrorKind :: IsADirectory ,
84+ 19 => io:: ErrorKind :: NetworkDown ,
85+ 20 => io:: ErrorKind :: NetworkUnreachable ,
86+ 21 => io:: ErrorKind :: NotADirectory ,
87+ 22 => io:: ErrorKind :: NotConnected ,
88+ 23 => io:: ErrorKind :: NotFound ,
89+ 24 => io:: ErrorKind :: NotSeekable ,
90+ 25 => io:: ErrorKind :: Other ,
91+ 26 => io:: ErrorKind :: OutOfMemory ,
92+ 27 => io:: ErrorKind :: PermissionDenied ,
93+ 28 => io:: ErrorKind :: QuotaExceeded ,
94+ 29 => io:: ErrorKind :: ReadOnlyFilesystem ,
95+ 30 => io:: ErrorKind :: ResourceBusy ,
96+ 31 => io:: ErrorKind :: StaleNetworkFileHandle ,
97+ 32 => io:: ErrorKind :: StorageFull ,
98+ 33 => io:: ErrorKind :: TimedOut ,
99+ 34 => io:: ErrorKind :: TooManyLinks ,
100+ 35 => io:: ErrorKind :: UnexpectedEof ,
101+ 36 => io:: ErrorKind :: Unsupported ,
102+ 37 => io:: ErrorKind :: WouldBlock ,
103+ 38 => io:: ErrorKind :: WriteZero ,
104+ _ => io:: ErrorKind :: Other ,
105+ }
106+ }
107+
18108 pub fn serialize < S > ( error : & io:: Error , serializer : S ) -> Result < S :: Ok , S :: Error >
19109 where
20110 S : Serializer ,
21111 {
22- // Serialize the error kind and message
23- serializer. serialize_str ( & format ! ( "{:?}:{}" , error. kind( ) , error) )
112+ let mut tup = serializer. serialize_tuple ( 2 ) ?;
113+ tup. serialize_element ( & error_kind_to_u8 ( error. kind ( ) ) ) ?;
114+ tup. serialize_element ( & error. to_string ( ) ) ?;
115+ tup. end ( )
24116 }
25117
26118 pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < io:: Error , D :: Error >
@@ -33,20 +125,93 @@ pub mod serde {
33125 type Value = io:: Error ;
34126
35127 fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
36- formatter. write_str ( "an io::Error string representation " )
128+ formatter. write_str ( "a tuple of (u32, String) representing io::Error" )
37129 }
38130
39- fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
131+ fn visit_seq < A > ( self , mut seq : A ) -> Result < Self :: Value , A :: Error >
40132 where
41- E : de :: Error ,
133+ A : SeqAccess < ' de > ,
42134 {
43- // For simplicity, create a generic error
44- // In a real app, you might want to parse the kind from the string
45- Ok ( io:: Error :: other ( value) )
135+ let num: u8 = seq
136+ . next_element ( ) ?
137+ . ok_or_else ( || de:: Error :: invalid_length ( 0 , & self ) ) ?;
138+ let message: String = seq
139+ . next_element ( ) ?
140+ . ok_or_else ( || de:: Error :: invalid_length ( 1 , & self ) ) ?;
141+ let kind = u8_to_error_kind ( num) ;
142+ Ok ( io:: Error :: new ( kind, message) )
46143 }
47144 }
48145
49- deserializer. deserialize_str ( IoErrorVisitor )
146+ deserializer. deserialize_tuple ( 2 , IoErrorVisitor )
147+ }
148+ }
149+
150+ #[ cfg( test) ]
151+ mod tests {
152+ use std:: io:: { self , ErrorKind } ;
153+
154+ use postcard;
155+ use serde:: { Deserialize , Serialize } ;
156+
157+ use super :: io_error_serde;
158+
159+ #[ derive( Serialize , Deserialize ) ]
160+ struct TestError ( #[ serde( with = "io_error_serde" ) ] io:: Error ) ;
161+
162+ #[ test]
163+ fn test_roundtrip_error_kinds ( ) {
164+ let message = "test error" ;
165+ let kinds = [
166+ ErrorKind :: AddrInUse ,
167+ ErrorKind :: AddrNotAvailable ,
168+ ErrorKind :: AlreadyExists ,
169+ ErrorKind :: ArgumentListTooLong ,
170+ ErrorKind :: BrokenPipe ,
171+ ErrorKind :: ConnectionAborted ,
172+ ErrorKind :: ConnectionRefused ,
173+ ErrorKind :: ConnectionReset ,
174+ ErrorKind :: CrossesDevices ,
175+ ErrorKind :: Deadlock ,
176+ ErrorKind :: DirectoryNotEmpty ,
177+ ErrorKind :: ExecutableFileBusy ,
178+ ErrorKind :: FileTooLarge ,
179+ ErrorKind :: HostUnreachable ,
180+ ErrorKind :: Interrupted ,
181+ ErrorKind :: InvalidData ,
182+ // ErrorKind::InvalidFilename,
183+ ErrorKind :: InvalidInput ,
184+ ErrorKind :: IsADirectory ,
185+ ErrorKind :: NetworkDown ,
186+ ErrorKind :: NetworkUnreachable ,
187+ ErrorKind :: NotADirectory ,
188+ ErrorKind :: NotConnected ,
189+ ErrorKind :: NotFound ,
190+ ErrorKind :: NotSeekable ,
191+ ErrorKind :: Other ,
192+ ErrorKind :: OutOfMemory ,
193+ ErrorKind :: PermissionDenied ,
194+ ErrorKind :: QuotaExceeded ,
195+ ErrorKind :: ReadOnlyFilesystem ,
196+ ErrorKind :: ResourceBusy ,
197+ ErrorKind :: StaleNetworkFileHandle ,
198+ ErrorKind :: StorageFull ,
199+ ErrorKind :: TimedOut ,
200+ ErrorKind :: TooManyLinks ,
201+ ErrorKind :: UnexpectedEof ,
202+ ErrorKind :: Unsupported ,
203+ ErrorKind :: WouldBlock ,
204+ ErrorKind :: WriteZero ,
205+ ] ;
206+
207+ for kind in kinds {
208+ let err = TestError ( io:: Error :: new ( kind, message) ) ;
209+ let serialized = postcard:: to_allocvec ( & err) . unwrap ( ) ;
210+ let deserialized: TestError = postcard:: from_bytes ( & serialized) . unwrap ( ) ;
211+
212+ assert_eq ! ( err. 0 . kind( ) , deserialized. 0 . kind( ) ) ;
213+ assert_eq ! ( err. 0 . to_string( ) , deserialized. 0 . to_string( ) ) ;
214+ }
50215 }
51216 }
52217}
0 commit comments