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