1use alloc::string::String;
11use alloc::vec::Vec;
12use core::fmt;
13
14#[derive(Debug, Clone)]
16pub enum Value {
17 Nil,
18 Bool(bool),
19 UInt(u64),
20 Int(i64),
21 Float(f64),
22 Bin(Vec<u8>),
23 Str(String),
24 Array(Vec<Value>),
25 Map(Vec<(Value, Value)>),
26}
27
28impl PartialEq for Value {
29 fn eq(&self, other: &Self) -> bool {
30 match (self, other) {
31 (Value::Nil, Value::Nil) => true,
32 (Value::Bool(a), Value::Bool(b)) => a == b,
33 (Value::UInt(a), Value::UInt(b)) => a == b,
34 (Value::Int(a), Value::Int(b)) => a == b,
35 (Value::Float(a), Value::Float(b)) => a.to_bits() == b.to_bits(),
36 (Value::Bin(a), Value::Bin(b)) => a == b,
37 (Value::Str(a), Value::Str(b)) => a == b,
38 (Value::Array(a), Value::Array(b)) => a == b,
39 (Value::Map(a), Value::Map(b)) => a == b,
40 _ => false,
41 }
42 }
43}
44
45impl Value {
46 pub fn as_uint(&self) -> Option<u64> {
48 match self {
49 Value::UInt(v) => Some(*v),
50 _ => None,
51 }
52 }
53
54 pub fn as_int(&self) -> Option<i64> {
56 match self {
57 Value::Int(v) => Some(*v),
58 _ => None,
59 }
60 }
61
62 pub fn as_integer(&self) -> Option<i64> {
64 match self {
65 Value::UInt(v) => {
66 if *v <= i64::MAX as u64 {
67 Some(*v as i64)
68 } else {
69 None
70 }
71 }
72 Value::Int(v) => Some(*v),
73 _ => None,
74 }
75 }
76
77 pub fn as_bool(&self) -> Option<bool> {
79 match self {
80 Value::Bool(v) => Some(*v),
81 _ => None,
82 }
83 }
84
85 pub fn as_float(&self) -> Option<f64> {
87 match self {
88 Value::Float(v) => Some(*v),
89 _ => None,
90 }
91 }
92
93 pub fn as_number(&self) -> Option<f64> {
95 match self {
96 Value::Float(v) => Some(*v),
97 Value::UInt(v) => Some(*v as f64),
98 Value::Int(v) => Some(*v as f64),
99 _ => None,
100 }
101 }
102
103 pub fn as_bin(&self) -> Option<&[u8]> {
105 match self {
106 Value::Bin(v) => Some(v),
107 _ => None,
108 }
109 }
110
111 pub fn as_str(&self) -> Option<&str> {
113 match self {
114 Value::Str(v) => Some(v),
115 _ => None,
116 }
117 }
118
119 pub fn as_array(&self) -> Option<&[Value]> {
121 match self {
122 Value::Array(v) => Some(v),
123 _ => None,
124 }
125 }
126
127 pub fn as_map(&self) -> Option<&[(Value, Value)]> {
129 match self {
130 Value::Map(v) => Some(v),
131 _ => None,
132 }
133 }
134
135 pub fn is_nil(&self) -> bool {
137 matches!(self, Value::Nil)
138 }
139
140 pub fn map_get(&self, key: &str) -> Option<&Value> {
142 self.as_map().and_then(|entries| {
143 entries.iter().find_map(|(k, v)| {
144 if let Value::Str(s) = k {
145 if s == key {
146 return Some(v);
147 }
148 }
149 None
150 })
151 })
152 }
153}
154
155const MAX_DEPTH: usize = 32;
157
158#[derive(Debug, Clone, PartialEq, Eq)]
160pub enum Error {
161 UnexpectedEof,
162 UnsupportedFormat(u8),
163 InvalidUtf8,
164 TrailingData,
165 MaxDepthExceeded,
166}
167
168impl fmt::Display for Error {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 match self {
171 Error::UnexpectedEof => write!(f, "Unexpected end of msgpack data"),
172 Error::UnsupportedFormat(b) => write!(f, "Unsupported msgpack format: 0x{:02x}", b),
173 Error::InvalidUtf8 => write!(f, "Invalid UTF-8 in msgpack string"),
174 Error::TrailingData => write!(f, "Trailing data after msgpack value"),
175 Error::MaxDepthExceeded => write!(f, "Maximum nesting depth exceeded"),
176 }
177 }
178}
179
180pub fn pack(value: &Value) -> Vec<u8> {
186 let mut buf = Vec::new();
187 pack_into(value, &mut buf);
188 buf
189}
190
191fn pack_into(value: &Value, buf: &mut Vec<u8>) {
192 match value {
193 Value::Nil => buf.push(0xc0),
194 Value::Bool(true) => buf.push(0xc3),
195 Value::Bool(false) => buf.push(0xc2),
196 Value::UInt(v) => pack_uint(*v, buf),
197 Value::Int(v) => pack_int(*v, buf),
198 Value::Float(v) => {
199 buf.push(0xcb);
200 buf.extend_from_slice(&v.to_bits().to_be_bytes());
201 }
202 Value::Bin(data) => pack_bin(data, buf),
203 Value::Str(s) => pack_str(s, buf),
204 Value::Array(items) => pack_array(items, buf),
205 Value::Map(entries) => pack_map(entries, buf),
206 }
207}
208
209fn pack_uint(v: u64, buf: &mut Vec<u8>) {
210 if v <= 127 {
211 buf.push(v as u8);
212 } else if v <= 0xFF {
213 buf.push(0xcc);
214 buf.push(v as u8);
215 } else if v <= 0xFFFF {
216 buf.push(0xcd);
217 buf.extend_from_slice(&(v as u16).to_be_bytes());
218 } else if v <= 0xFFFF_FFFF {
219 buf.push(0xce);
220 buf.extend_from_slice(&(v as u32).to_be_bytes());
221 } else {
222 buf.push(0xcf);
223 buf.extend_from_slice(&v.to_be_bytes());
224 }
225}
226
227fn pack_int(v: i64, buf: &mut Vec<u8>) {
228 if v >= 0 {
229 pack_uint(v as u64, buf);
230 } else if v >= -32 {
231 buf.push(v as u8); } else if v >= -128 {
233 buf.push(0xd0);
234 buf.push(v as i8 as u8);
235 } else if v >= -32768 {
236 buf.push(0xd1);
237 buf.extend_from_slice(&(v as i16).to_be_bytes());
238 } else if v >= -2_147_483_648 {
239 buf.push(0xd2);
240 buf.extend_from_slice(&(v as i32).to_be_bytes());
241 } else {
242 buf.push(0xd3);
243 buf.extend_from_slice(&v.to_be_bytes());
244 }
245}
246
247fn pack_bin(data: &[u8], buf: &mut Vec<u8>) {
248 let len = data.len();
249 if len <= 0xFF {
250 buf.push(0xc4);
251 buf.push(len as u8);
252 } else if len <= 0xFFFF {
253 buf.push(0xc5);
254 buf.extend_from_slice(&(len as u16).to_be_bytes());
255 } else {
256 buf.push(0xc6);
257 buf.extend_from_slice(&(len as u32).to_be_bytes());
258 }
259 buf.extend_from_slice(data);
260}
261
262fn pack_str(s: &str, buf: &mut Vec<u8>) {
263 let bytes = s.as_bytes();
264 let len = bytes.len();
265 if len <= 31 {
266 buf.push(0xa0 | len as u8);
267 } else if len <= 0xFF {
268 buf.push(0xd9);
269 buf.push(len as u8);
270 } else if len <= 0xFFFF {
271 buf.push(0xda);
272 buf.extend_from_slice(&(len as u16).to_be_bytes());
273 } else {
274 buf.push(0xdb);
275 buf.extend_from_slice(&(len as u32).to_be_bytes());
276 }
277 buf.extend_from_slice(bytes);
278}
279
280fn pack_array(items: &[Value], buf: &mut Vec<u8>) {
281 let len = items.len();
282 if len <= 15 {
283 buf.push(0x90 | len as u8);
284 } else if len <= 0xFFFF {
285 buf.push(0xdc);
286 buf.extend_from_slice(&(len as u16).to_be_bytes());
287 } else {
288 buf.push(0xdd);
289 buf.extend_from_slice(&(len as u32).to_be_bytes());
290 }
291 for item in items {
292 pack_into(item, buf);
293 }
294}
295
296fn pack_map(entries: &[(Value, Value)], buf: &mut Vec<u8>) {
297 let len = entries.len();
298 if len <= 15 {
299 buf.push(0x80 | len as u8);
300 } else if len <= 0xFFFF {
301 buf.push(0xde);
302 buf.extend_from_slice(&(len as u16).to_be_bytes());
303 } else {
304 buf.push(0xdf);
305 buf.extend_from_slice(&(len as u32).to_be_bytes());
306 }
307 for (k, v) in entries {
308 pack_into(k, buf);
309 pack_into(v, buf);
310 }
311}
312
313pub fn pack_str_map(entries: &[(&str, Value)]) -> Vec<u8> {
315 let map: Vec<(Value, Value)> = entries
316 .iter()
317 .map(|(k, v)| (Value::Str(String::from(*k)), v.clone()))
318 .collect();
319 pack(&Value::Map(map))
320}
321
322pub fn unpack(data: &[u8]) -> Result<(Value, usize), Error> {
329 unpack_depth(data, 0)
330}
331
332fn unpack_depth(data: &[u8], depth: usize) -> Result<(Value, usize), Error> {
333 if data.is_empty() {
334 return Err(Error::UnexpectedEof);
335 }
336 if depth > MAX_DEPTH {
337 return Err(Error::MaxDepthExceeded);
338 }
339 let b = data[0];
340 match b {
341 0x00..=0x7f => Ok((Value::UInt(b as u64), 1)),
343
344 0x80..=0x8f => {
346 let len = (b & 0x0f) as usize;
347 unpack_map_entries(data, 1, len, depth)
348 }
349
350 0x90..=0x9f => {
352 let len = (b & 0x0f) as usize;
353 unpack_array_entries(data, 1, len, depth)
354 }
355
356 0xa0..=0xbf => {
358 let len = (b & 0x1f) as usize;
359 unpack_str_bytes(data, 1, len)
360 }
361
362 0xc0 => Ok((Value::Nil, 1)),
364
365 0xc1 => Err(Error::UnsupportedFormat(b)),
367
368 0xc2 => Ok((Value::Bool(false), 1)),
370 0xc3 => Ok((Value::Bool(true), 1)),
371
372 0xca => {
374 ensure_len(data, 5)?;
375 let bits = u32::from_be_bytes([data[1], data[2], data[3], data[4]]);
376 Ok((Value::Float(f32::from_bits(bits) as f64), 5))
377 }
378
379 0xcb => {
381 ensure_len(data, 9)?;
382 let bits = u64::from_be_bytes([
383 data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
384 ]);
385 Ok((Value::Float(f64::from_bits(bits)), 9))
386 }
387
388 0xc4 => {
390 ensure_len(data, 2)?;
391 let len = data[1] as usize;
392 let needed = 2usize.checked_add(len).ok_or(Error::UnexpectedEof)?;
393 ensure_len(data, needed)?;
394 Ok((Value::Bin(data[2..2 + len].to_vec()), 2 + len))
395 }
396
397 0xc5 => {
399 ensure_len(data, 3)?;
400 let len = u16::from_be_bytes([data[1], data[2]]) as usize;
401 let needed = 3usize.checked_add(len).ok_or(Error::UnexpectedEof)?;
402 ensure_len(data, needed)?;
403 Ok((Value::Bin(data[3..3 + len].to_vec()), 3 + len))
404 }
405
406 0xc6 => {
408 ensure_len(data, 5)?;
409 let len = u32::from_be_bytes([data[1], data[2], data[3], data[4]]) as usize;
410 let needed = 5usize.checked_add(len).ok_or(Error::UnexpectedEof)?;
411 ensure_len(data, needed)?;
412 Ok((Value::Bin(data[5..5 + len].to_vec()), 5 + len))
413 }
414
415 0xcc => {
417 ensure_len(data, 2)?;
418 Ok((Value::UInt(data[1] as u64), 2))
419 }
420
421 0xcd => {
423 ensure_len(data, 3)?;
424 let v = u16::from_be_bytes([data[1], data[2]]);
425 Ok((Value::UInt(v as u64), 3))
426 }
427
428 0xce => {
430 ensure_len(data, 5)?;
431 let v = u32::from_be_bytes([data[1], data[2], data[3], data[4]]);
432 Ok((Value::UInt(v as u64), 5))
433 }
434
435 0xcf => {
437 ensure_len(data, 9)?;
438 let v = u64::from_be_bytes([
439 data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
440 ]);
441 Ok((Value::UInt(v), 9))
442 }
443
444 0xd0 => {
446 ensure_len(data, 2)?;
447 Ok((Value::Int(data[1] as i8 as i64), 2))
448 }
449
450 0xd1 => {
452 ensure_len(data, 3)?;
453 let v = i16::from_be_bytes([data[1], data[2]]);
454 Ok((Value::Int(v as i64), 3))
455 }
456
457 0xd2 => {
459 ensure_len(data, 5)?;
460 let v = i32::from_be_bytes([data[1], data[2], data[3], data[4]]);
461 Ok((Value::Int(v as i64), 5))
462 }
463
464 0xd3 => {
466 ensure_len(data, 9)?;
467 let v = i64::from_be_bytes([
468 data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
469 ]);
470 Ok((Value::Int(v), 9))
471 }
472
473 0xd9 => {
475 ensure_len(data, 2)?;
476 let len = data[1] as usize;
477 unpack_str_bytes(data, 2, len)
478 }
479
480 0xda => {
482 ensure_len(data, 3)?;
483 let len = u16::from_be_bytes([data[1], data[2]]) as usize;
484 unpack_str_bytes(data, 3, len)
485 }
486
487 0xdb => {
489 ensure_len(data, 5)?;
490 let len = u32::from_be_bytes([data[1], data[2], data[3], data[4]]) as usize;
491 unpack_str_bytes(data, 5, len)
492 }
493
494 0xdc => {
496 ensure_len(data, 3)?;
497 let len = u16::from_be_bytes([data[1], data[2]]) as usize;
498 unpack_array_entries(data, 3, len, depth)
499 }
500
501 0xdd => {
503 ensure_len(data, 5)?;
504 let len = u32::from_be_bytes([data[1], data[2], data[3], data[4]]) as usize;
505 unpack_array_entries(data, 5, len, depth)
506 }
507
508 0xde => {
510 ensure_len(data, 3)?;
511 let len = u16::from_be_bytes([data[1], data[2]]) as usize;
512 unpack_map_entries(data, 3, len, depth)
513 }
514
515 0xdf => {
517 ensure_len(data, 5)?;
518 let len = u32::from_be_bytes([data[1], data[2], data[3], data[4]]) as usize;
519 unpack_map_entries(data, 5, len, depth)
520 }
521
522 0xe0..=0xff => Ok((Value::Int(b as i8 as i64), 1)),
524
525 _ => Err(Error::UnsupportedFormat(b)),
526 }
527}
528
529pub fn unpack_exact(data: &[u8]) -> Result<Value, Error> {
531 let (value, consumed) = unpack(data)?;
532 if consumed != data.len() {
533 return Err(Error::TrailingData);
534 }
535 Ok(value)
536}
537
538fn ensure_len(data: &[u8], needed: usize) -> Result<(), Error> {
539 if data.len() < needed {
540 Err(Error::UnexpectedEof)
541 } else {
542 Ok(())
543 }
544}
545
546fn unpack_str_bytes(data: &[u8], offset: usize, len: usize) -> Result<(Value, usize), Error> {
547 let needed = offset.checked_add(len).ok_or(Error::UnexpectedEof)?;
548 ensure_len(data, needed)?;
549 let bytes = &data[offset..offset + len];
550 let s = core::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8)?;
551 Ok((Value::Str(String::from(s)), offset + len))
552}
553
554fn unpack_array_entries(
555 data: &[u8],
556 start: usize,
557 count: usize,
558 depth: usize,
559) -> Result<(Value, usize), Error> {
560 if count > data.len().saturating_sub(start) {
561 return Err(Error::UnexpectedEof);
562 }
563 let mut offset = start;
564 let mut items = Vec::with_capacity(count);
565 for _ in 0..count {
566 let (v, consumed) = unpack_depth(&data[offset..], depth + 1)?;
567 items.push(v);
568 offset += consumed;
569 }
570 Ok((Value::Array(items), offset))
571}
572
573fn unpack_map_entries(
574 data: &[u8],
575 start: usize,
576 count: usize,
577 depth: usize,
578) -> Result<(Value, usize), Error> {
579 if count.checked_mul(2).map_or(true, |minimum_items| {
580 minimum_items > data.len().saturating_sub(start)
581 }) {
582 return Err(Error::UnexpectedEof);
583 }
584 let mut offset = start;
585 let mut entries = Vec::with_capacity(count);
586 for _ in 0..count {
587 let (k, kc) = unpack_depth(&data[offset..], depth + 1)?;
588 offset += kc;
589 let (v, vc) = unpack_depth(&data[offset..], depth + 1)?;
590 offset += vc;
591 entries.push((k, v));
592 }
593 Ok((Value::Map(entries), offset))
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599
600 fn roundtrip(v: &Value) -> Value {
601 let packed = pack(v);
602 let (unpacked, consumed) = unpack(&packed).unwrap();
603 assert_eq!(consumed, packed.len(), "all bytes consumed");
604 unpacked
605 }
606
607 #[test]
608 fn test_nil() {
609 let packed = pack(&Value::Nil);
610 assert_eq!(packed, vec![0xc0]);
611 assert_eq!(roundtrip(&Value::Nil), Value::Nil);
612 }
613
614 #[test]
615 fn test_bool() {
616 assert_eq!(pack(&Value::Bool(true)), vec![0xc3]);
617 assert_eq!(pack(&Value::Bool(false)), vec![0xc2]);
618 assert_eq!(roundtrip(&Value::Bool(true)), Value::Bool(true));
619 assert_eq!(roundtrip(&Value::Bool(false)), Value::Bool(false));
620 }
621
622 #[test]
623 fn test_positive_fixint() {
624 assert_eq!(pack(&Value::UInt(0)), vec![0x00]);
625 assert_eq!(pack(&Value::UInt(127)), vec![0x7f]);
626 assert_eq!(roundtrip(&Value::UInt(0)), Value::UInt(0));
627 assert_eq!(roundtrip(&Value::UInt(42)), Value::UInt(42));
628 assert_eq!(roundtrip(&Value::UInt(127)), Value::UInt(127));
629 }
630
631 #[test]
632 fn test_uint8() {
633 assert_eq!(pack(&Value::UInt(128)), vec![0xcc, 0x80]);
634 assert_eq!(pack(&Value::UInt(255)), vec![0xcc, 0xff]);
635 assert_eq!(roundtrip(&Value::UInt(128)), Value::UInt(128));
636 assert_eq!(roundtrip(&Value::UInt(255)), Value::UInt(255));
637 }
638
639 #[test]
640 fn test_uint16() {
641 assert_eq!(pack(&Value::UInt(256)), vec![0xcd, 0x01, 0x00]);
642 assert_eq!(roundtrip(&Value::UInt(256)), Value::UInt(256));
643 assert_eq!(roundtrip(&Value::UInt(0xFFFF)), Value::UInt(0xFFFF));
644 }
645
646 #[test]
647 fn test_uint32() {
648 assert_eq!(
649 pack(&Value::UInt(0x10000)),
650 vec![0xce, 0x00, 0x01, 0x00, 0x00]
651 );
652 assert_eq!(roundtrip(&Value::UInt(0x10000)), Value::UInt(0x10000));
653 assert_eq!(roundtrip(&Value::UInt(0xFFFFFFFF)), Value::UInt(0xFFFFFFFF));
654 }
655
656 #[test]
657 fn test_uint64() {
658 let big = 0x1_0000_0000u64;
659 assert_eq!(roundtrip(&Value::UInt(big)), Value::UInt(big));
660 let huge = u64::MAX;
661 assert_eq!(roundtrip(&Value::UInt(huge)), Value::UInt(huge));
662 }
663
664 #[test]
665 fn test_negative_fixint() {
666 assert_eq!(pack(&Value::Int(-1)), vec![0xff]);
668 assert_eq!(pack(&Value::Int(-32)), vec![0xe0]);
669 assert_eq!(roundtrip(&Value::Int(-1)), Value::Int(-1));
670 assert_eq!(roundtrip(&Value::Int(-32)), Value::Int(-32));
671 }
672
673 #[test]
674 fn test_int8() {
675 assert_eq!(pack(&Value::Int(-33)), vec![0xd0, 0xdf]);
676 assert_eq!(roundtrip(&Value::Int(-33)), Value::Int(-33));
677 assert_eq!(roundtrip(&Value::Int(-128)), Value::Int(-128));
678 }
679
680 #[test]
681 fn test_int16() {
682 assert_eq!(roundtrip(&Value::Int(-129)), Value::Int(-129));
683 assert_eq!(roundtrip(&Value::Int(-32768)), Value::Int(-32768));
684 }
685
686 #[test]
687 fn test_int32() {
688 assert_eq!(roundtrip(&Value::Int(-32769)), Value::Int(-32769));
689 }
690
691 #[test]
692 fn test_positive_int_packed_as_uint() {
693 let packed = pack(&Value::Int(42));
695 assert_eq!(packed, vec![42]); }
697
698 #[test]
699 fn test_fixstr() {
700 let v = Value::Str(String::from("t"));
701 let packed = pack(&v);
702 assert_eq!(packed[0], 0xa1); assert_eq!(roundtrip(&v), v);
704
705 let v = Value::Str(String::from("hello"));
706 assert_eq!(roundtrip(&v), v);
707
708 let v = Value::Str(String::new());
710 assert_eq!(pack(&v), vec![0xa0]);
711 assert_eq!(roundtrip(&v), v);
712 }
713
714 #[test]
715 fn test_str8() {
716 let s: String = "a".repeat(32);
717 let v = Value::Str(s);
718 let packed = pack(&v);
719 assert_eq!(packed[0], 0xd9);
720 assert_eq!(packed[1], 32);
721 assert_eq!(roundtrip(&v), v);
722 }
723
724 #[test]
725 fn test_bin8() {
726 let v = Value::Bin(vec![1, 2, 3]);
727 let packed = pack(&v);
728 assert_eq!(packed[0], 0xc4);
729 assert_eq!(packed[1], 3);
730 assert_eq!(roundtrip(&v), v);
731 }
732
733 #[test]
734 fn test_bin16() {
735 let data = vec![0xAB; 300];
736 let v = Value::Bin(data);
737 let packed = pack(&v);
738 assert_eq!(packed[0], 0xc5);
739 assert_eq!(roundtrip(&v), v);
740 }
741
742 #[test]
743 fn test_bin32() {
744 let data = vec![0xCD; 70000];
747 let v = Value::Bin(data);
748 let packed = pack(&v);
749 assert_eq!(packed[0], 0xc6);
750 assert_eq!(roundtrip(&v), v);
751 }
752
753 #[test]
754 fn test_fixarray() {
755 let v = Value::Array(vec![Value::UInt(1), Value::UInt(2), Value::UInt(3)]);
756 let packed = pack(&v);
757 assert_eq!(packed[0], 0x93); assert_eq!(roundtrip(&v), v);
759
760 let v = Value::Array(vec![]);
762 assert_eq!(pack(&v), vec![0x90]);
763 assert_eq!(roundtrip(&v), v);
764 }
765
766 #[test]
767 fn test_fixmap() {
768 let v = Value::Map(vec![
769 (Value::Str(String::from("a")), Value::UInt(1)),
770 (Value::Str(String::from("b")), Value::UInt(2)),
771 ]);
772 let packed = pack(&v);
773 assert_eq!(packed[0], 0x82); assert_eq!(roundtrip(&v), v);
775 }
776
777 #[test]
778 fn test_nested_structure() {
779 let v = Value::Map(vec![
780 (Value::Str(String::from("t")), Value::UInt(1000)),
781 (Value::Str(String::from("m")), Value::Bin(vec![0xAA; 10])),
782 (Value::Str(String::from("q")), Value::Nil),
783 ]);
784 assert_eq!(roundtrip(&v), v);
785 }
786
787 #[test]
788 fn test_pack_str_map() {
789 let packed = pack_str_map(&[("x", Value::UInt(42)), ("y", Value::Bool(true))]);
790 let (v, _) = unpack(&packed).unwrap();
791 assert_eq!(v.map_get("x").unwrap().as_uint(), Some(42));
792 assert_eq!(v.map_get("y").unwrap().as_bool(), Some(true));
793 }
794
795 #[test]
796 fn test_map_get_missing_key() {
797 let v = Value::Map(vec![(Value::Str(String::from("a")), Value::UInt(1))]);
798 assert!(v.map_get("b").is_none());
799 }
800
801 #[test]
802 fn test_hmu_array_format() {
803 let v = Value::Array(vec![
805 Value::UInt(2),
806 Value::Bin(vec![0x11, 0x22, 0x33, 0x44, 0xAA, 0xBB, 0xCC, 0xDD]),
807 ]);
808 assert_eq!(roundtrip(&v), v);
809 }
810
811 #[test]
812 fn test_decode_error_eof() {
813 assert_eq!(unpack(&[]), Err(Error::UnexpectedEof));
814 assert_eq!(unpack(&[0xc4, 0x05]), Err(Error::UnexpectedEof));
816 }
817
818 #[test]
819 fn test_declared_array_length_cannot_force_large_allocation() {
820 let data = [0xdd, 0xff, 0xff, 0xff, 0xff];
821 assert_eq!(unpack(&data), Err(Error::UnexpectedEof));
822 }
823
824 #[test]
825 fn test_declared_map_length_cannot_force_large_allocation() {
826 let data = [0xdf, 0x7f, 0xff, 0xff, 0xff];
827 assert_eq!(unpack(&data), Err(Error::UnexpectedEof));
828 }
829
830 #[test]
831 fn test_unpack_exact_trailing() {
832 let packed = pack(&Value::UInt(42));
833 let mut with_extra = packed.clone();
834 with_extra.push(0x00);
835 assert!(unpack_exact(&with_extra).is_err());
836 assert!(unpack_exact(&packed).is_ok());
837 }
838
839 #[test]
840 fn test_value_accessors() {
841 assert_eq!(Value::UInt(42).as_uint(), Some(42));
842 assert_eq!(Value::UInt(42).as_int(), None);
843 assert_eq!(Value::UInt(42).as_integer(), Some(42));
844 assert_eq!(Value::Int(-5).as_integer(), Some(-5));
845 assert_eq!(Value::Bool(true).as_bool(), Some(true));
846 assert_eq!(Value::Bin(vec![1]).as_bin(), Some(&[1u8][..]));
847 assert_eq!(Value::Str(String::from("x")).as_str(), Some("x"));
848 assert!(Value::Nil.is_nil());
849 }
850
851 #[test]
852 fn test_max_depth_exceeded() {
853 let mut data = Vec::new();
855 data.extend(core::iter::repeat_n(0x91, MAX_DEPTH + 2)); data.push(0x01); assert_eq!(unpack(&data), Err(Error::MaxDepthExceeded));
858 }
859
860 #[test]
861 fn test_depth_within_limit() {
862 let mut data = Vec::new();
864 data.extend(core::iter::repeat_n(0x91, 5)); data.push(0x01); let (val, _) = unpack(&data).unwrap();
867 let mut current = &val;
869 for _ in 0..5 {
870 current = ¤t.as_array().unwrap()[0];
871 }
872 assert_eq!(current.as_uint(), Some(1));
873 }
874
875 #[test]
876 fn test_int64_roundtrip() {
877 let v = Value::Int(i64::MIN);
878 assert_eq!(roundtrip(&v), v);
879 let v = Value::Int(-2_147_483_649); assert_eq!(roundtrip(&v), v);
881 }
882
883 #[test]
884 fn test_str16_roundtrip() {
885 let s: String = "x".repeat(256);
886 let v = Value::Str(s);
887 let packed = pack(&v);
888 assert_eq!(packed[0], 0xda); assert_eq!(roundtrip(&v), v);
890 }
891
892 #[test]
893 fn test_array16_roundtrip() {
894 let items: Vec<Value> = (0..16).map(Value::UInt).collect();
895 let v = Value::Array(items);
896 let packed = pack(&v);
897 assert_eq!(packed[0], 0xdc); assert_eq!(roundtrip(&v), v);
899 }
900
901 #[test]
902 fn test_map16_roundtrip() {
903 let entries: Vec<(Value, Value)> = (0..16)
904 .map(|i| (Value::UInt(i), Value::Bool(i % 2 == 0)))
905 .collect();
906 let v = Value::Map(entries);
907 let packed = pack(&v);
908 assert_eq!(packed[0], 0xde); assert_eq!(roundtrip(&v), v);
910 }
911
912 #[test]
913 fn test_unsupported_format() {
914 assert_eq!(unpack(&[0xc1]), Err(Error::UnsupportedFormat(0xc1)));
916 }
917}