1use std::fmt;
2use std::collections::HashMap;
3use std::mem::transmute;
4
5use dbus_serialize::types::{Value,BasicValue,Path,Signature,Struct,Variant,Array,Dictionary};
6
7#[derive(Debug, Clone)]
8pub enum DemarshalError {
9 MessageTooShort,
10 CorruptedMessage,
11 BadUTF8,
12 BadSignature,
13 ElementTooBig,
14 MismatchedParens,
15}
16
17impl fmt::Display for DemarshalError {
18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 let msg = match *self {
20 DemarshalError::MessageTooShort => "message too short",
21 DemarshalError::CorruptedMessage => "corrupted message",
22 DemarshalError::BadUTF8 => "bad utf-8",
23 DemarshalError::BadSignature => "bad signature",
24 DemarshalError::ElementTooBig => "element too big",
25 DemarshalError::MismatchedParens => "mismatched parens",
26 };
27
28 write!(f, "{}", msg)
29 }
30}
31
32pub fn get_alignment(sig: char) -> usize {
33 match sig {
34 'y' => 1,
35 'b' => 1,
36 'n' => 2,
37 'q' => 2,
38 'i' => 4,
39 'u' => 4,
40 'x' => 8,
41 't' => 8,
42 's' => 4,
43 'o' => 4,
44 'g' => 1,
45
46 'a' => 4,
47 '(' => 8,
48 '{' => 8,
49 'v' => 1,
50 _ => panic!("Bogus type")
51 }
52}
53
54fn demarshal_byte(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
55 if buf.len() < 1 {
56 return Err(DemarshalError::MessageTooShort);
57 }
58 let byte = buf.remove(0);
59 *offset += 1;
60 Ok(Value::BasicValue(BasicValue::Byte(byte)))
61}
62
63fn align_to(buf: &mut Vec<u8>, offset: &mut usize, align: usize) -> Result<(),DemarshalError> {
64 if *offset % align == 0 {
65 return Ok(());
66 }
67 let delta = align - (*offset % align);
68 if buf.len() < delta {
69 return Err(DemarshalError::MessageTooShort);
70 }
71 for _ in 0..delta {
72 buf.remove(0);
73 *offset += 1;
74 }
75 Ok(())
76}
77
78fn demarshal_bool(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
79 try!(align_to(buf, offset, 4));
80 if buf.len() < 4 {
81 return Err(DemarshalError::MessageTooShort);
82 }
83 let byte = buf.remove(0);
84 *offset += 1;
85 for _ in 0..3 {
87 *offset += 1;
88 if buf.remove(0) != 0 {
90 return Err(DemarshalError::CorruptedMessage);
91 }
92 }
93 match byte {
94 0 => Ok(Value::BasicValue(BasicValue::Boolean(false))),
95 1 => Ok(Value::BasicValue(BasicValue::Boolean(true))),
96 _ => Err(DemarshalError::CorruptedMessage)
97 }
98}
99
100fn demarshal_int(buf: &mut Vec<u8>, offset: &mut usize, len: usize, is_signed: bool) -> Result<Value,DemarshalError> {
101 try!(align_to(buf, offset, len));
102 if buf.len() < len {
103 return Err(DemarshalError::MessageTooShort);
104 }
105 let mut intbuf = [0; 8];
106 for i in 0..len {
107 intbuf[i] = buf.remove(0);
108 *offset += 1;
109 }
110 if is_signed && (intbuf[len-1] & 128 == 128) {
112 for i in len..8 {
113 intbuf[i] = 0xff;
114 }
115 }
116 let val : u64 = unsafe { transmute(intbuf) };
117 if is_signed {
118 match len {
119 2 => Ok(Value::BasicValue(BasicValue::Int16(val as i16))),
120 4 => Ok(Value::BasicValue(BasicValue::Int32(val as i32))),
121 8 => Ok(Value::BasicValue(BasicValue::Int64(val as i64))),
122 _ => panic!("Bogus length {}", len)
123 }
124 } else {
125 match len {
126 1 => Ok(Value::BasicValue(BasicValue::Byte(val as u8))),
127 2 => Ok(Value::BasicValue(BasicValue::Uint16(val as u16))),
128 4 => Ok(Value::BasicValue(BasicValue::Uint32(val as u32))),
129 8 => Ok(Value::BasicValue(BasicValue::Uint64(val))),
130 _ => panic!("Bogus length {}", len)
131 }
132 }
133}
134
135fn demarshal_string(buf: &mut Vec<u8>, offset: &mut usize, count_size: usize, is_path: bool) -> Result<Value,DemarshalError> {
136 let len = match demarshal_int(buf, offset, count_size, false) {
138 Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
139 Ok(Value::BasicValue(BasicValue::Byte(x))) => x as u32,
140 _ => return Err(DemarshalError::CorruptedMessage),
141 };
142 let mut strbuf = Vec::new();
143 for _ in 0..len {
144 strbuf.push(buf.remove(0));
145 *offset += 1
146 }
147 if buf.remove(0) != 0 {
149 return Err(DemarshalError::CorruptedMessage);
150 }
151 *offset += 1;
152 let val = try!(String::from_utf8(strbuf).or(Err(DemarshalError::BadUTF8)));
153 if is_path {
154 Ok(Value::BasicValue(BasicValue::ObjectPath(Path(val))))
155 } else {
156 if count_size == 4 {
157 Ok(Value::BasicValue(BasicValue::String(val)))
158 } else {
159 Ok(Value::BasicValue(BasicValue::Signature(Signature(val))))
160 }
161 }
162}
163
164fn demarshal_array(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
165 if sig.len() < 1 {
166 return Err(DemarshalError::BadSignature);
167 }
168 let typ = sig.chars().next().unwrap();
169 let is_dict = typ == '{';
170 let array_len = match demarshal_int(buf, offset, 4, false) {
172 Ok(Value::BasicValue(BasicValue::Uint32(x))) => x,
173 _ => return Err(DemarshalError::CorruptedMessage),
174 };
175 if array_len > 1 << 26 {
176 return Err(DemarshalError::ElementTooBig);
177 }
178 try!(align_to(buf, offset, get_alignment(typ)));
179 if buf.len() < (array_len as usize) {
180 return Err(DemarshalError::MessageTooShort);
181 }
182
183 let mut vec = Vec::new();
184 let start_offset = *offset;
185 let mut sig_copy = "".to_owned();
186 while *offset < start_offset+(array_len as usize) {
187 sig_copy = sig.to_owned();
189 vec.push(try!(demarshal(buf, offset, &mut sig_copy)));
190 }
191 let mut mysig = sig.clone();
193 mysig.truncate(sig.len() - sig_copy.len());
194 mysig.insert(0, 'a');
195 *sig = sig_copy;
196
197 if is_dict {
198 let mut map : HashMap<BasicValue,Value> = HashMap::new();
199 for x in vec {
200 let mut s = match x {
201 Value::Struct(x) => x,
202 _ => panic!("Dictionaries should contain structs")
203 };
204 let val = s.objects.remove(1);
205 let key = match s.objects[0] {
206 Value::BasicValue(ref x) => x,
207 _ => panic!("Dictionaries require BasicValue keys")
208 };
209 map.insert(key.clone(), val);
210 }
211 return Ok(Value::Dictionary(Dictionary::new_with_sig(map, mysig)));
212 }
213
214 Ok(Value::Array(Array::new_with_sig(vec, mysig)))
215}
216
217fn demarshal_struct(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
218 if sig.len() < 1 {
219 return Err(DemarshalError::BadSignature);
220 }
221 try!(align_to(buf, offset, 8));
222
223 let mut vec = Vec::new();
224 let mut mysig = sig.to_owned();
225 loop {
226 let typ = match sig.chars().next() {
227 Some(x) => x,
228 None => return Err(DemarshalError::MismatchedParens)
229 };
230 if typ == ')' {
231 sig.remove(0);
232 break;
233 }
234 vec.push(try!(demarshal(buf, offset, sig)));
235 }
236 let oldlen = mysig.len();
238 mysig.truncate(oldlen - sig.len());
239 mysig.insert(0, '(');
240
241 Ok(Value::Struct(Struct{
242 objects: vec,
243 signature: Signature(mysig)
244 }))
245}
246
247fn demarshal_variant(buf: &mut Vec<u8>, offset: &mut usize) -> Result<Value,DemarshalError> {
248 let mut variant_sig = "g".to_owned();
249 let sigval = try!(demarshal(buf, offset, &mut variant_sig));
250 let sig = match sigval {
251 Value::BasicValue(BasicValue::Signature(x)) => x,
252 _ => return Err(DemarshalError::CorruptedMessage)
253 };
254 let mut s = sig.0.to_owned();
255 let var = try!(demarshal(buf, offset, &mut s));
256 Ok(Value::Variant(Variant{
257 object: Box::new(var),
258 signature: sig
259 }))
260}
261
262pub fn demarshal(buf: &mut Vec<u8>, offset: &mut usize, sig: &mut String) -> Result<Value,DemarshalError> {
263 let typ = sig.remove(0);
264 match typ {
265 'y' => demarshal_byte(buf, offset),
266 'b' => demarshal_bool(buf, offset),
267 'n' => demarshal_int(buf, offset, 2, true),
268 'q' => demarshal_int(buf, offset, 2, false),
269 'i' => demarshal_int(buf, offset, 4, true),
270 'u' => demarshal_int(buf, offset, 4, false),
271 'x' => demarshal_int(buf, offset, 8, true),
272 't' => demarshal_int(buf, offset, 8, false),
273 's' => demarshal_string(buf, offset, 4, false),
274 'o' => demarshal_string(buf, offset, 4, true),
275 'g' => demarshal_string(buf, offset, 1, false),
276
277 'a' => demarshal_array(buf, offset, sig),
278 '(' => demarshal_struct(buf, offset, sig),
279 '{' => demarshal_struct(buf, offset, sig),
280 'v' => demarshal_variant(buf, offset),
281 _ => Err(DemarshalError::BadSignature)
282 }
283}
284
285#[cfg(test)]
286mod test {
287 use marshal::Marshal;
288 use demarshal::demarshal;
289 use dbus_serialize::types::{Value,BasicValue,Signature};
290
291 #[test]
292 fn test_demarshal_u32() {
293 let mut buf = Vec::new();
294 let x = 16 as u32;
295 let mut sig = x.get_type().to_string();
296 x.dbus_encode(&mut buf);
297
298 let mut offset = 0;
299 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
300 assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
301 assert_eq!(buf.len(), 0);
302 assert_eq!(sig, "");
303 }
304
305 #[test]
306 fn test_demarshal_u32_offset() {
307 let mut buf = Vec::new();
308 buf.insert(0, 0);
309 let x = 16 as u32;
310 let mut sig = x.get_type();
311 x.dbus_encode(&mut buf);
312
313 buf.remove(0);
314 let mut offset = 1;
315 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
316 assert_eq!(v, Value::BasicValue(BasicValue::Uint32(16)));
317 assert_eq!(buf.len(), 0);
318 assert_eq!(sig, "");
319 }
320
321 #[test]
322 fn test_string() {
323 let mut buf = Vec::new();
324 let x = "swalter".to_string();
325 let mut sig = x.get_type();
326 x.dbus_encode(&mut buf);
327
328 let mut offset = 0;
329 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
330 assert_eq!(v, Value::BasicValue(BasicValue::String("swalter".to_string())));
331 assert_eq!(buf.len(), 0);
332 assert_eq!(sig, "");
333 }
334
335 #[test]
336 fn test_array() {
337 let mut buf = Vec::new();
338 let x = vec![1 as u32, 2 as u32, 3 as u32];
339 let mut sig = "au".to_string();
340 x.dbus_encode(&mut buf);
341
342 let mut offset = 0;
343 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
344 let arr = match v {
345 Value::Array(x) => x,
346 _ => panic!("Bad return from demarshal {:?}", v)
347 };
348 let golden = vec![
349 Value::BasicValue(BasicValue::Uint32(1)),
350 Value::BasicValue(BasicValue::Uint32(2)),
351 Value::BasicValue(BasicValue::Uint32(3)),
352 ];
353 assert_eq!(arr.objects, golden);
354 assert_eq!(buf.len(), 0);
355 assert_eq!(sig, "");
356 }
357
358 #[test]
359 fn test_array_bytes() {
360 let mut buf = Vec::new();
361 let x = vec![1 as u8, 2 as u8, 3 as u8];
362 let mut sig = "ay".to_string();
363 x.dbus_encode(&mut buf);
364
365 let mut offset = 0;
366 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
367 let arr = match v {
368 Value::Array(x) => x,
369 _ => panic!("Bad return from demarshal {:?}", v)
370 };
371 let golden = vec![
372 Value::BasicValue(BasicValue::Byte(1)),
373 Value::BasicValue(BasicValue::Byte(2)),
374 Value::BasicValue(BasicValue::Byte(3)),
375 ];
376 assert_eq!(arr.objects, golden);
377 assert_eq!(buf.len(), 0);
378 assert_eq!(sig, "");
379 }
380
381 #[test]
382 fn test_struct() {
383 let mut buf = Vec::new();
384 let x = "swalter".to_string();
385 let mut sig = "(ss)".to_string();
386 x.dbus_encode(&mut buf);
387 x.dbus_encode(&mut buf);
388
389 let mut offset = 0;
390 let v = demarshal(&mut buf, &mut offset, &mut sig).unwrap();
391 assert_eq!(buf.len(), 0);
392 assert_eq!(sig, "");
393 let s = match v {
394 Value::Struct(x) => x,
395 _ => panic!("Bad return from demarshal {:?}", v)
396 };
397 assert_eq!(s.signature, Signature("(ss)".to_string()));
398 }
399}