@@ -11,16 +11,109 @@ pub mod serde {
11
11
use std:: { fmt, io} ;
12
12
13
13
use serde:: {
14
- de:: { self , Visitor } ,
14
+ de:: { self , SeqAccess , Visitor } ,
15
+ ser:: SerializeTuple ,
15
16
Deserializer , Serializer ,
16
17
} ;
17
18
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
+
18
109
pub fn serialize < S > ( error : & io:: Error , serializer : S ) -> Result < S :: Ok , S :: Error >
19
110
where
20
111
S : Serializer ,
21
112
{
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 ( )
24
117
}
25
118
26
119
pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < io:: Error , D :: Error >
@@ -33,20 +126,93 @@ pub mod serde {
33
126
type Value = io:: Error ;
34
127
35
128
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" )
37
130
}
38
131
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 >
40
133
where
41
- E : de :: Error ,
134
+ A : SeqAccess < ' de > ,
42
135
{
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) )
46
144
}
47
145
}
48
146
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
+ }
50
216
}
51
217
}
52
218
}
0 commit comments