@@ -30,7 +30,7 @@ pub enum Object {
30
30
//BinaryFloat,
31
31
//Complex,
32
32
//BinaryComplex,
33
- // String,
33
+ String ( :: std :: string :: String ) ,
34
34
//Interned,
35
35
//Ref_,
36
36
//Tuple,
@@ -43,7 +43,7 @@ pub enum Object {
43
43
//FrozenSet,
44
44
//Ref,
45
45
46
- //Ascii,
46
+ Bytes ( Vec < u8 > ) , // aka. ASCII in CPython's marshal
47
47
//AsciiInterned,
48
48
//SmallTuple,
49
49
//ShortAscii,
@@ -66,6 +66,29 @@ macro_rules! read_byte {
66
66
} } ;
67
67
}
68
68
69
+ fn read_long < R : io:: Read > ( r : & mut R ) -> Result < u32 , UnmarshalError > {
70
+ let mut buf = [ 0 , 0 , 0 , 0 ] ;
71
+ match r. read_exact ( & mut buf) {
72
+ Err ( err) => return Err ( UnmarshalError :: Io ( err) ) ,
73
+ Ok ( ( ) ) => Ok ( buf[ 0 ] as u32 + 256 * ( buf[ 1 ] as u32 + 256 * ( buf[ 2 ] as u32 + 256 * ( buf[ 3 ] as u32 ) ) ) )
74
+ }
75
+ }
76
+
77
+ fn read_ascii_string < R : io:: Read > ( r : & mut R , size : usize ) -> Result < String , UnmarshalError > {
78
+ let mut buf = Vec :: < u8 > :: new ( ) ;
79
+ buf. resize ( size, 0 ) ;
80
+ match r. read_exact ( & mut buf) {
81
+ Err ( err) => return Err ( UnmarshalError :: Io ( err) ) ,
82
+ Ok ( ( ) ) => ( )
83
+ } ;
84
+ let mut string = String :: new ( ) ;
85
+ string. reserve ( buf. len ( ) ) ; // The string will use more bytes than this if there are extended ascii characters, but it can't hurt to reserve anyway
86
+ for c in buf {
87
+ string. push ( c as char ) ;
88
+ }
89
+ Ok ( string)
90
+ }
91
+
69
92
pub fn read_object < R : io:: Read > ( r : & mut R ) -> Result < Object , UnmarshalError > {
70
93
let byte = read_byte ! ( r) ;
71
94
let _flag = byte & 0b10000000 ; // TODO: do something with this
@@ -75,13 +98,10 @@ pub fn read_object<R: io::Read>(r: &mut R) -> Result<Object, UnmarshalError> {
75
98
'N' => Object :: None ,
76
99
'F' => Object :: False ,
77
100
'T' => Object :: True ,
78
- 'i' => {
79
- let mut buf = [ 0 , 0 , 0 , 0 ] ;
80
- match r. read_exact ( & mut buf) {
81
- Err ( err) => return Err ( UnmarshalError :: Io ( err) ) ,
82
- Ok ( ( ) ) => ( )
83
- } ;
84
- Object :: Int ( buf[ 0 ] as u32 + 256 * ( buf[ 1 ] as u32 + 256 * ( buf[ 2 ] as u32 + 256 * ( buf[ 3 ] as u32 ) ) ) )
101
+ 'i' => Object :: Int ( try!( read_long ( r) ) ) ,
102
+ 'z' | 'Z' => { // “short ascii”, “short ascii interned”
103
+ let size = read_byte ! ( r) as usize ;
104
+ Object :: String ( try!( read_ascii_string ( r, size) ) )
85
105
} ,
86
106
_ => panic ! ( format!( "Unsupported opcode: {}" , opcode as char ) ) ,
87
107
} ;
@@ -111,3 +131,12 @@ fn test_int() {
111
131
let mut reader: & [ u8 ] = b"\xe9 \xe8 \x03 \x00 \x00 " ;
112
132
assert_eq ! ( Object :: Int ( 1000 ) , read_object( & mut reader) . unwrap( ) ) ;
113
133
}
134
+
135
+ #[ test]
136
+ fn test_string ( ) {
137
+ let mut reader: & [ u8 ] = b"\xda \x03 foo" ;
138
+ assert_eq ! ( Object :: String ( "foo" . to_string( ) ) , read_object( & mut reader) . unwrap( ) ) ;
139
+
140
+ let mut reader: & [ u8 ] = b"\xda \x04 foo\xe9 " ; // Note: this string was not generated with the marshal module
141
+ assert_eq ! ( Object :: String ( "fooé" . to_string( ) ) , read_object( & mut reader) . unwrap( ) ) ;
142
+ }
0 commit comments