dbus_bytestream/
demarshal.rs

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    // XXX: assumes LE
86    for _ in 0..3 {
87        *offset += 1;
88        // Only the first byte should have a non-zero value
89        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    // Check for sign-extension
111    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    // demarshal_int ensure we're correctly aligned with input
137    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    // Check the NUL byte
148    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    // demarshal_int ensure we're correctly aligned with input
171    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        // We want to pass the same signature to each call of demarshal
188        sig_copy = sig.to_owned();
189        vec.push(try!(demarshal(buf, offset, &mut sig_copy)));
190    }
191    // Now that we're done with our elements we can forget the elements consumed by demarshal
192    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    // Only keep the characters that were consumed by demarshal
237    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}