Skip to main content

ploit_malper/
msgpack.rs

1use std::collections::BTreeMap;
2
3use crate::error::{AppError, Result};
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum MsgValue {
7    Nil,
8    Bool(bool),
9    Int(i64),
10    UInt(u64),
11    Float(f64),
12    String(String),
13    Array(Vec<MsgValue>),
14    Map(BTreeMap<String, MsgValue>),
15}
16
17impl MsgValue {
18    pub fn get(&self, key: &str) -> Option<&MsgValue> {
19        match self {
20            MsgValue::Map(map) => map.get(key),
21            _ => None,
22        }
23    }
24
25    pub fn as_str(&self) -> Option<&str> {
26        match self {
27            MsgValue::String(value) => Some(value.as_str()),
28            _ => None,
29        }
30    }
31
32    pub fn as_array(&self) -> Option<&[MsgValue]> {
33        match self {
34            MsgValue::Array(values) => Some(values.as_slice()),
35            _ => None,
36        }
37    }
38
39    pub fn as_map(&self) -> Option<&BTreeMap<String, MsgValue>> {
40        match self {
41            MsgValue::Map(map) => Some(map),
42            _ => None,
43        }
44    }
45
46    pub fn as_u64(&self) -> Option<u64> {
47        match self {
48            MsgValue::UInt(value) => Some(*value),
49            MsgValue::Int(value) if *value >= 0 => Some(*value as u64),
50            _ => None,
51        }
52    }
53}
54
55pub fn encode(value: &MsgValue) -> Vec<u8> {
56    let mut buffer = Vec::new();
57    encode_value(value, &mut buffer);
58    buffer
59}
60
61pub fn decode(bytes: &[u8]) -> Result<MsgValue> {
62    let (value, consumed) = decode_value(bytes, 0)?;
63    if consumed != bytes.len() {
64        return Err(AppError::Msgpack(
65            "trailing bytes in msgpack payload".to_string(),
66        ));
67    }
68    Ok(value)
69}
70
71fn encode_value(value: &MsgValue, buffer: &mut Vec<u8>) {
72    match value {
73        MsgValue::Nil => buffer.push(0xc0),
74        MsgValue::Bool(false) => buffer.push(0xc2),
75        MsgValue::Bool(true) => buffer.push(0xc3),
76        MsgValue::Int(value) => encode_int(*value, buffer),
77        MsgValue::UInt(value) => encode_uint(*value, buffer),
78        MsgValue::Float(value) => {
79            buffer.push(0xcb);
80            buffer.extend_from_slice(&value.to_be_bytes());
81        }
82        MsgValue::String(value) => encode_str(value, buffer),
83        MsgValue::Array(values) => encode_array(values, buffer),
84        MsgValue::Map(map) => encode_map(map, buffer),
85    }
86}
87
88fn encode_uint(value: u64, buffer: &mut Vec<u8>) {
89    match value {
90        0..=127 => buffer.push(value as u8),
91        128..=255 => {
92            buffer.push(0xcc);
93            buffer.push(value as u8);
94        }
95        256..=65_535 => {
96            buffer.push(0xcd);
97            buffer.extend_from_slice(&(value as u16).to_be_bytes());
98        }
99        65_536..=4_294_967_295 => {
100            buffer.push(0xce);
101            buffer.extend_from_slice(&(value as u32).to_be_bytes());
102        }
103        _ => {
104            buffer.push(0xcf);
105            buffer.extend_from_slice(&value.to_be_bytes());
106        }
107    }
108}
109
110fn encode_int(value: i64, buffer: &mut Vec<u8>) {
111    if (-32..=127).contains(&value) {
112        if value >= 0 {
113            buffer.push(value as u8);
114        } else {
115            buffer.push((value as i8) as u8);
116        }
117        return;
118    }
119
120    if (-128..=-33).contains(&value) {
121        buffer.push(0xd0);
122        buffer.push(value as i8 as u8);
123    } else if (-32_768..=-129).contains(&value) {
124        buffer.push(0xd1);
125        buffer.extend_from_slice(&(value as i16).to_be_bytes());
126    } else if (-2_147_483_648..=-32_769).contains(&value) {
127        buffer.push(0xd2);
128        buffer.extend_from_slice(&(value as i32).to_be_bytes());
129    } else {
130        buffer.push(0xd3);
131        buffer.extend_from_slice(&value.to_be_bytes());
132    }
133}
134
135fn encode_str(value: &str, buffer: &mut Vec<u8>) {
136    let bytes = value.as_bytes();
137    let len = bytes.len();
138    if len <= 31 {
139        buffer.push(0xa0 | (len as u8));
140    } else if len <= 255 {
141        buffer.push(0xd9);
142        buffer.push(len as u8);
143    } else if len <= 65_535 {
144        buffer.push(0xda);
145        buffer.extend_from_slice(&(len as u16).to_be_bytes());
146    } else {
147        buffer.push(0xdb);
148        buffer.extend_from_slice(&(len as u32).to_be_bytes());
149    }
150    buffer.extend_from_slice(bytes);
151}
152
153fn encode_array(values: &[MsgValue], buffer: &mut Vec<u8>) {
154    let len = values.len();
155    if len <= 15 {
156        buffer.push(0x90 | (len as u8));
157    } else if len <= 65_535 {
158        buffer.push(0xdc);
159        buffer.extend_from_slice(&(len as u16).to_be_bytes());
160    } else {
161        buffer.push(0xdd);
162        buffer.extend_from_slice(&(len as u32).to_be_bytes());
163    }
164    for value in values {
165        encode_value(value, buffer);
166    }
167}
168
169fn encode_map(map: &BTreeMap<String, MsgValue>, buffer: &mut Vec<u8>) {
170    let len = map.len();
171    if len <= 15 {
172        buffer.push(0x80 | (len as u8));
173    } else if len <= 65_535 {
174        buffer.push(0xde);
175        buffer.extend_from_slice(&(len as u16).to_be_bytes());
176    } else {
177        buffer.push(0xdf);
178        buffer.extend_from_slice(&(len as u32).to_be_bytes());
179    }
180    for (key, value) in map {
181        encode_str(key, buffer);
182        encode_value(value, buffer);
183    }
184}
185
186fn decode_value(bytes: &[u8], index: usize) -> Result<(MsgValue, usize)> {
187    let prefix = *bytes
188        .get(index)
189        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack payload".to_string()))?;
190
191    match prefix {
192        0xc0 => Ok((MsgValue::Nil, index + 1)),
193        0xc2 => Ok((MsgValue::Bool(false), index + 1)),
194        0xc3 => Ok((MsgValue::Bool(true), index + 1)),
195        0xc4 => {
196            let len = read_u8(bytes, index + 1)? as usize;
197            let slice = bytes.get(index + 2..index + 2 + len).ok_or_else(|| {
198                AppError::Msgpack("unexpected end of msgpack binary data".to_string())
199            })?;
200            let value = String::from_utf8_lossy(slice).into_owned();
201            Ok((MsgValue::String(value), index + 2 + len))
202        }
203        0xc5 => {
204            let len = read_u16(bytes, index + 1)? as usize;
205            let slice = bytes.get(index + 3..index + 3 + len).ok_or_else(|| {
206                AppError::Msgpack("unexpected end of msgpack binary data".to_string())
207            })?;
208            let value = String::from_utf8_lossy(slice).into_owned();
209            Ok((MsgValue::String(value), index + 3 + len))
210        }
211        0xc6 => {
212            let len = read_u32(bytes, index + 1)? as usize;
213            let slice = bytes.get(index + 5..index + 5 + len).ok_or_else(|| {
214                AppError::Msgpack("unexpected end of msgpack binary data".to_string())
215            })?;
216            let value = String::from_utf8_lossy(slice).into_owned();
217            Ok((MsgValue::String(value), index + 5 + len))
218        }
219        0xca => {
220            let end = index + 5;
221            let slice = bytes.get(index + 1..end).ok_or_else(|| {
222                AppError::Msgpack("unexpected end of msgpack payload".to_string())
223            })?;
224            let value = f32::from_be_bytes([slice[0], slice[1], slice[2], slice[3]]);
225            Ok((MsgValue::Float(value as f64), end))
226        }
227        0xcb => {
228            let end = index + 9;
229            let slice = bytes.get(index + 1..end).ok_or_else(|| {
230                AppError::Msgpack("unexpected end of msgpack payload".to_string())
231            })?;
232            let value = f64::from_be_bytes([
233                slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
234            ]);
235            Ok((MsgValue::Float(value), end))
236        }
237        0xcc => {
238            let value = read_u8(bytes, index + 1)? as u64;
239            Ok((MsgValue::UInt(value), index + 2))
240        }
241        0xcd => {
242            let value = read_u16(bytes, index + 1)? as u64;
243            Ok((MsgValue::UInt(value), index + 3))
244        }
245        0xce => {
246            let value = read_u32(bytes, index + 1)? as u64;
247            Ok((MsgValue::UInt(value), index + 5))
248        }
249        0xcf => {
250            let value = read_u64(bytes, index + 1)?;
251            Ok((MsgValue::UInt(value), index + 9))
252        }
253        0xd0 => {
254            let value = read_i8(bytes, index + 1)? as i64;
255            Ok((MsgValue::Int(value), index + 2))
256        }
257        0xd1 => {
258            let value = read_i16(bytes, index + 1)? as i64;
259            Ok((MsgValue::Int(value), index + 3))
260        }
261        0xd2 => {
262            let value = read_i32(bytes, index + 1)? as i64;
263            Ok((MsgValue::Int(value), index + 5))
264        }
265        0xd3 => {
266            let value = read_i64(bytes, index + 1)?;
267            Ok((MsgValue::Int(value), index + 9))
268        }
269        0xd9 => {
270            let len = read_u8(bytes, index + 1)? as usize;
271            decode_str(bytes, index + 2, len)
272        }
273        0xda => {
274            let len = read_u16(bytes, index + 1)? as usize;
275            decode_str(bytes, index + 3, len)
276        }
277        0xdb => {
278            let len = read_u32(bytes, index + 1)? as usize;
279            decode_str(bytes, index + 5, len)
280        }
281        0xdc => {
282            let len = read_u16(bytes, index + 1)? as usize;
283            decode_array(bytes, index + 3, len)
284        }
285        0xdd => {
286            let len = read_u32(bytes, index + 1)? as usize;
287            decode_array(bytes, index + 5, len)
288        }
289        0xde => {
290            let len = read_u16(bytes, index + 1)? as usize;
291            decode_map(bytes, index + 3, len)
292        }
293        0xdf => {
294            let len = read_u32(bytes, index + 1)? as usize;
295            decode_map(bytes, index + 5, len)
296        }
297        0x80..=0x8f => {
298            let len = (prefix & 0x0f) as usize;
299            decode_map(bytes, index + 1, len)
300        }
301        0x90..=0x9f => {
302            let len = (prefix & 0x0f) as usize;
303            decode_array(bytes, index + 1, len)
304        }
305        0xa0..=0xbf => {
306            let len = (prefix & 0x1f) as usize;
307            decode_str(bytes, index + 1, len)
308        }
309        0xe0..=0xff => Ok((MsgValue::Int((prefix as i8) as i64), index + 1)),
310        0x00..=0x7f => Ok((MsgValue::UInt(prefix as u64), index + 1)),
311        _ => Err(AppError::Msgpack(format!(
312            "unsupported msgpack prefix: 0x{prefix:02x}"
313        ))),
314    }
315}
316
317fn decode_str(bytes: &[u8], index: usize, len: usize) -> Result<(MsgValue, usize)> {
318    let end = index
319        .checked_add(len)
320        .ok_or_else(|| AppError::Msgpack("msgpack string length overflow".to_string()))?;
321    let slice = bytes
322        .get(index..end)
323        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack string".to_string()))?;
324    let value = String::from_utf8(slice.to_vec())
325        .map_err(|e| AppError::Msgpack(format!("invalid utf-8 string: {e}")))?;
326    Ok((MsgValue::String(value), end))
327}
328
329fn decode_array(bytes: &[u8], mut index: usize, len: usize) -> Result<(MsgValue, usize)> {
330    let mut values = Vec::with_capacity(len);
331    for _ in 0..len {
332        let (value, next) = decode_value(bytes, index)?;
333        values.push(value);
334        index = next;
335    }
336    Ok((MsgValue::Array(values), index))
337}
338
339fn decode_map(bytes: &[u8], mut index: usize, len: usize) -> Result<(MsgValue, usize)> {
340    let mut map = BTreeMap::new();
341    for _ in 0..len {
342        let (key_value, next_key) = decode_value(bytes, index)?;
343        index = next_key;
344        let key = match &key_value {
345            MsgValue::String(value) => value.clone(),
346            MsgValue::UInt(value) => value.to_string(),
347            MsgValue::Int(value) => value.to_string(),
348            MsgValue::Float(value) => value.to_string(),
349            MsgValue::Bool(value) => value.to_string(),
350            MsgValue::Nil => String::new(),
351            _ => {
352                return Err(AppError::Msgpack(
353                    "msgpack map key was not a string".to_string(),
354                ));
355            }
356        };
357        let (value, next_value) = decode_value(bytes, index)?;
358        index = next_value;
359        map.insert(key, value);
360    }
361    Ok((MsgValue::Map(map), index))
362}
363
364fn read_u8(bytes: &[u8], index: usize) -> Result<u8> {
365    bytes
366        .get(index)
367        .copied()
368        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack payload".to_string()))
369}
370
371fn read_i8(bytes: &[u8], index: usize) -> Result<i8> {
372    Ok(read_u8(bytes, index)? as i8)
373}
374
375fn read_u16(bytes: &[u8], index: usize) -> Result<u16> {
376    let end = index + 2;
377    let slice = bytes
378        .get(index..end)
379        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack payload".to_string()))?;
380    Ok(u16::from_be_bytes([slice[0], slice[1]]))
381}
382
383fn read_i16(bytes: &[u8], index: usize) -> Result<i16> {
384    Ok(i16::from_be_bytes(read_u16(bytes, index)?.to_be_bytes()))
385}
386
387fn read_u32(bytes: &[u8], index: usize) -> Result<u32> {
388    let end = index + 4;
389    let slice = bytes
390        .get(index..end)
391        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack payload".to_string()))?;
392    Ok(u32::from_be_bytes([slice[0], slice[1], slice[2], slice[3]]))
393}
394
395fn read_i32(bytes: &[u8], index: usize) -> Result<i32> {
396    Ok(i32::from_be_bytes(read_u32(bytes, index)?.to_be_bytes()))
397}
398
399fn read_u64(bytes: &[u8], index: usize) -> Result<u64> {
400    let end = index + 8;
401    let slice = bytes
402        .get(index..end)
403        .ok_or_else(|| AppError::Msgpack("unexpected end of msgpack payload".to_string()))?;
404    Ok(u64::from_be_bytes([
405        slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
406    ]))
407}
408
409fn read_i64(bytes: &[u8], index: usize) -> Result<i64> {
410    Ok(i64::from_be_bytes(read_u64(bytes, index)?.to_be_bytes()))
411}
412
413#[cfg(test)]
414mod tests {
415    use super::*;
416
417    #[test]
418    fn roundtrip_nil() {
419        let v = MsgValue::Nil;
420        let bytes = encode(&v);
421        let decoded = decode(&bytes).unwrap();
422        assert_eq!(v, decoded);
423    }
424
425    #[test]
426    fn roundtrip_bool() {
427        for b in [true, false] {
428            let v = MsgValue::Bool(b);
429            let bytes = encode(&v);
430            let decoded = decode(&bytes).unwrap();
431            assert_eq!(v, decoded);
432        }
433    }
434
435    #[test]
436    fn roundtrip_positive_fixint() {
437        for i in [0u64, 1, 127] {
438            let v = MsgValue::UInt(i);
439            let bytes = encode(&v);
440            let decoded = decode(&bytes).unwrap();
441            assert_eq!(v, decoded);
442        }
443    }
444
445    #[test]
446    fn roundtrip_u8() {
447        let v = MsgValue::UInt(200);
448        let bytes = encode(&v);
449        assert_eq!(bytes[0], 0xcc);
450        assert_eq!(bytes[1], 200);
451        let decoded = decode(&bytes).unwrap();
452        assert_eq!(v, decoded);
453    }
454
455    #[test]
456    fn roundtrip_u16() {
457        let v = MsgValue::UInt(1000);
458        let bytes = encode(&v);
459        assert_eq!(bytes[0], 0xcd);
460        let decoded = decode(&bytes).unwrap();
461        assert_eq!(v, decoded);
462    }
463
464    #[test]
465    fn roundtrip_u32() {
466        let v = MsgValue::UInt(100_000);
467        let bytes = encode(&v);
468        assert_eq!(bytes[0], 0xce);
469        let decoded = decode(&bytes).unwrap();
470        assert_eq!(v, decoded);
471    }
472
473    #[test]
474    fn roundtrip_negative_fixint() {
475        for i in [-1i64, -32] {
476            let v = MsgValue::Int(i);
477            let bytes = encode(&v);
478            let decoded = decode(&bytes).unwrap();
479            assert_eq!(v, decoded);
480        }
481    }
482
483    #[test]
484    fn roundtrip_i8() {
485        let v = MsgValue::Int(-100);
486        let bytes = encode(&v);
487        assert_eq!(bytes[0], 0xd0);
488        let decoded = decode(&bytes).unwrap();
489        assert_eq!(v, decoded);
490    }
491
492    #[test]
493    fn roundtrip_fixstr() {
494        let v = MsgValue::String("hello".to_string());
495        let bytes = encode(&v);
496        assert_eq!(bytes[0], 0xa5);
497        let decoded = decode(&bytes).unwrap();
498        assert_eq!(v, decoded);
499    }
500
501    #[test]
502    fn roundtrip_str8() {
503        let s = "a".repeat(32);
504        let v = MsgValue::String(s);
505        let bytes = encode(&v);
506        assert_eq!(bytes[0], 0xd9);
507        assert_eq!(bytes[1], 32);
508        let decoded = decode(&bytes).unwrap();
509        assert_eq!(v, decoded);
510    }
511
512    #[test]
513    fn roundtrip_fixarray() {
514        let v = MsgValue::Array(vec![
515            MsgValue::UInt(1),
516            MsgValue::String("two".to_string()),
517            MsgValue::Bool(true),
518        ]);
519        let bytes = encode(&v);
520        assert_eq!(bytes[0], 0x93);
521        let decoded = decode(&bytes).unwrap();
522        assert_eq!(v, decoded);
523    }
524
525    #[test]
526    fn roundtrip_fixmap() {
527        let mut map = BTreeMap::new();
528        map.insert("key".to_string(), MsgValue::String("value".to_string()));
529        let v = MsgValue::Map(map);
530        let bytes = encode(&v);
531        assert_eq!(bytes[0], 0x81);
532        let decoded = decode(&bytes).unwrap();
533        assert_eq!(v, decoded);
534    }
535
536    #[test]
537    fn decode_bin8() {
538        // bin 8 format: 0xc4 <len> <bytes>
539        let bytes = vec![0xc4, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f];
540        let decoded = decode(&bytes).unwrap();
541        assert_eq!(decoded, MsgValue::String("hello".to_string()));
542    }
543
544    #[test]
545    fn decode_bin16() {
546        // bin 16 format: 0xc5 <len_u16_be> <bytes>
547        let mut bytes = vec![0xc5, 0x00, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64];
548        let decoded = decode(&bytes).unwrap();
549        assert_eq!(decoded, MsgValue::String("world".to_string()));
550
551        // Larger string
552        let long = "x".repeat(300);
553        bytes = vec![0xc5, 0x01, 0x2c];
554        bytes.extend_from_slice(long.as_bytes());
555        let decoded = decode(&bytes).unwrap();
556        assert_eq!(decoded, MsgValue::String(long));
557    }
558
559    #[test]
560    fn decode_bin32() {
561        let long = "z".repeat(70000);
562        let mut bytes = vec![0xc6, 0x00, 0x01, 0x11, 0x70];
563        bytes.extend_from_slice(long.as_bytes());
564        let decoded = decode(&bytes).unwrap();
565        assert_eq!(decoded, MsgValue::String(long));
566    }
567
568    #[test]
569    fn decode_float32() {
570        let mut bytes = vec![0xca];
571        bytes.extend_from_slice(&3.14f32.to_be_bytes());
572        let decoded = decode(&bytes).unwrap();
573        match decoded {
574            MsgValue::Float(f) => assert!((f - 3.14).abs() < 0.001),
575            _ => panic!("expected Float"),
576        }
577    }
578
579    #[test]
580    fn decode_float64() {
581        let mut bytes = vec![0xcb];
582        bytes.extend_from_slice(&std::f64::consts::PI.to_be_bytes());
583        let decoded = decode(&bytes).unwrap();
584        match decoded {
585            MsgValue::Float(f) => assert!((f - std::f64::consts::PI).abs() < 1e-15),
586            _ => panic!("expected Float"),
587        }
588    }
589
590    #[test]
591    fn decode_map_with_integer_keys() {
592        // fixmap with 2 entries keyed by positive fixints:
593        // { 0 => "Automatic Target", 1 => "Windows 7" }
594        let mut bytes = vec![0x82];
595        bytes.push(0x00); // key 0
596        bytes.extend_from_slice(&encode(&MsgValue::String("Automatic Target".into())));
597        bytes.push(0x01); // key 1
598        bytes.extend_from_slice(&encode(&MsgValue::String("Windows 7".into())));
599        let decoded = decode(&bytes).unwrap();
600        let map = decoded.as_map().unwrap();
601        assert_eq!(
602            map.get("0"),
603            Some(&MsgValue::String("Automatic Target".into()))
604        );
605        assert_eq!(map.get("1"), Some(&MsgValue::String("Windows 7".into())));
606    }
607
608    #[test]
609    fn decode_map_with_negative_int_keys() {
610        // map(1, key=-1, "neg")
611        let mut bytes = vec![0x81];
612        bytes.push(0xff); // fixint -1
613        bytes.extend_from_slice(b"neg".as_slice()); // placeholder replaced below
614        let payload = encode(&MsgValue::String("neg".into()));
615        bytes.truncate(2);
616        bytes.extend_from_slice(&payload);
617        let decoded = decode(&bytes).unwrap();
618        let map = decoded.as_map().unwrap();
619        assert_eq!(map.get("-1"), Some(&MsgValue::String("neg".into())));
620    }
621
622    #[test]
623    fn decode_msf_auth_response() {
624        // Simulated MSF-RPC auth.login response:
625        // {"result": "success", "token": "abcd1234"}
626        let mut bytes = Vec::new();
627        // fixmap with 2 elements
628        bytes.push(0x82);
629        // bin 8 "result"
630        bytes.extend_from_slice(&[0xc4, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74]);
631        // bin 8 "success"
632        bytes.extend_from_slice(&[0xc4, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73]);
633        // bin 8 "token"
634        bytes.extend_from_slice(&[0xc4, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e]);
635        // bin 8 "abcd1234"
636        bytes.extend_from_slice(&[0xc4, 0x08, 0x61, 0x62, 0x63, 0x64, 0x31, 0x32, 0x33, 0x34]);
637
638        let decoded = decode(&bytes).unwrap();
639        let result = decoded.get("result").and_then(|v| v.as_str()).unwrap();
640        let token = decoded.get("token").and_then(|v| v.as_str()).unwrap();
641        assert_eq!(result, "success");
642        assert_eq!(token, "abcd1234");
643    }
644
645    #[test]
646    fn decode_msf_error_response() {
647        // Simulated MSF error response using bin 8 for error_string
648        // {"error": true, "error_string": "Invalid Message Format"}
649        let mut bytes = Vec::new();
650        bytes.push(0x82); // fixmap 2
651        bytes.extend_from_slice(&[0xc4, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72]); // bin8 "error"
652        bytes.push(0xc3); // true
653        bytes.extend_from_slice(&[
654            0xc4, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
655        ]); // bin8 "error_string"
656        bytes.extend_from_slice(&[
657            0xc4, 0x16, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x4d, 0x65, 0x73, 0x73,
658            0x61, 0x67, 0x65, 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74,
659        ]); // bin8 "Invalid Message Format"
660
661        let decoded = decode(&bytes).unwrap();
662        let error = decoded.get("error").unwrap();
663        assert_eq!(error, &MsgValue::Bool(true));
664        let error_string = decoded
665            .get("error_string")
666            .and_then(|v| v.as_str())
667            .unwrap();
668        assert_eq!(error_string, "Invalid Message Format");
669    }
670
671    #[test]
672    fn decode_trailing_bytes_fails() {
673        let mut bytes = vec![0xa5, 0x68, 0x65, 0x6c, 0x6c, 0x6f]; // fixstr "hello"
674        bytes.push(0x00); // extra byte
675        let result = decode(&bytes);
676        assert!(result.is_err());
677        assert!(result.unwrap_err().to_string().contains("trailing bytes"));
678    }
679
680    #[test]
681    fn encode_array_format_auth_login() {
682        // Test encoding in the format the MSF server expects:
683        // ["auth.login", "Mithun", "Mithun@2806"]
684        let v = MsgValue::Array(vec![
685            MsgValue::String("auth.login".to_string()),
686            MsgValue::String("Mithun".to_string()),
687            MsgValue::String("Mithun@2806".to_string()),
688        ]);
689        let bytes = encode(&v);
690        // Should be 0x93 (fixarray 3) + 3 strings
691        assert_eq!(bytes[0], 0x93);
692        let decoded = decode(&bytes).unwrap();
693        assert_eq!(v, decoded);
694    }
695}