@@ -4,13 +4,15 @@ use std::io;
4
4
#[ derive( Debug ) ]
5
5
pub enum UnmarshalError {
6
6
Io ( io:: Error ) ,
7
+ Decoding ( :: std:: string:: FromUtf8Error ) ,
7
8
UnexpectedCode ( String ) ,
8
9
}
9
10
10
11
impl fmt:: Display for UnmarshalError {
11
12
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
12
13
match * self {
13
14
UnmarshalError :: Io ( ref e) => write ! ( f, "I/O error:" ) . and_then ( |_| e. fmt ( f) ) ,
15
+ UnmarshalError :: Decoding ( ref e) => write ! ( f, "Decoding error:" ) . and_then ( |_| e. fmt ( f) ) ,
14
16
UnmarshalError :: UnexpectedCode ( ref s) => write ! ( f, "{}" , s) ,
15
17
}
16
18
}
@@ -37,14 +39,12 @@ pub enum Object {
37
39
//List,
38
40
//Dict,
39
41
//Code,
40
- //Unicode,
41
42
//Unknown,
42
43
//Set,
43
44
//FrozenSet,
44
45
//Ref,
45
46
46
47
Bytes ( Vec < u8 > ) , // aka. ASCII in CPython's marshal
47
- //AsciiInterned,
48
48
//SmallTuple,
49
49
//ShortAscii,
50
50
//ShortAsciiInterned
@@ -89,6 +89,19 @@ fn read_ascii_string<R: io::Read>(r: &mut R, size: usize) -> Result<String, Unma
89
89
Ok ( string)
90
90
}
91
91
92
+ fn read_unicode_string < R : io:: Read > ( r : & mut R , size : usize ) -> Result < String , UnmarshalError > {
93
+ let mut buf = Vec :: < u8 > :: new ( ) ;
94
+ buf. resize ( size, 0 ) ;
95
+ match r. read_exact ( & mut buf) {
96
+ Err ( err) => return Err ( UnmarshalError :: Io ( err) ) ,
97
+ Ok ( ( ) ) => ( )
98
+ } ;
99
+ match String :: from_utf8 ( buf) {
100
+ Err ( err) => return Err ( UnmarshalError :: Decoding ( err) ) ,
101
+ Ok ( s) => Ok ( s)
102
+ }
103
+ }
104
+
92
105
pub fn read_object < R : io:: Read > ( r : & mut R ) -> Result < Object , UnmarshalError > {
93
106
let byte = read_byte ! ( r) ;
94
107
let _flag = byte & 0b10000000 ; // TODO: do something with this
@@ -103,6 +116,11 @@ pub fn read_object<R: io::Read>(r: &mut R) -> Result<Object, UnmarshalError> {
103
116
let size = read_byte ! ( r) as usize ;
104
117
Object :: String ( try!( read_ascii_string ( r, size) ) )
105
118
} ,
119
+ 'u' => { // “unicode”
120
+ let size = try!( read_long ( r) ) as usize ; // TODO: overflow check if usize is smaller than u32
121
+ Object :: String ( try!( read_unicode_string ( r, size) ) )
122
+ }
123
+
106
124
_ => panic ! ( format!( "Unsupported opcode: {}" , opcode as char ) ) ,
107
125
} ;
108
126
Ok ( object)
@@ -139,4 +157,7 @@ fn test_string() {
139
157
140
158
let mut reader: & [ u8 ] = b"\xda \x04 foo\xe9 " ; // Note: this string was not generated with the marshal module
141
159
assert_eq ! ( Object :: String ( "fooé" . to_string( ) ) , read_object( & mut reader) . unwrap( ) ) ;
160
+
161
+ let mut reader: & [ u8 ] = b"\xf5 \x05 \x00 \x00 \x00 foo\xc3 \xa9 " ;
162
+ assert_eq ! ( Object :: String ( "fooé" . to_string( ) ) , read_object( & mut reader) . unwrap( ) ) ;
142
163
}
0 commit comments