Skip to main content

check_msgpack_structure

Function check_msgpack_structure 

Source
pub fn check_msgpack_structure(
    bytes: &[u8],
    max_depth: usize,
) -> Result<(), MsgpackStructureError>
Expand description

Checks that bytes hold one MessagePack document whose declared structure the input can actually back, before any decoder sees them.

A header-only walk: str/bin/ext payloads are skipped by offset, never read, and nothing is decoded. It keeps one u64 per open non-empty collection, so at most min(max_depth, bytes.len()) of them (8 KiB at a depth of 1024), and allocates nothing proportional to any declared length.

Trailing bytes after the root element are left to the decoder.

max_depth is the caller’s bound. The protocol (spec/interop-mode.md → Decode bounds) requires one in 32..=1024; this function does not enforce that range and applies whatever value it is given.

§Errors

Returns a MsgpackStructureError naming the violated bound. It rejects:

  • nesting deeper than max_depth, counting every array or map header on the path (an empty one included);
  • a header declaring more payload bytes than the input holds;
  • more pending elements (across every open collection) than the remaining bytes can back. Every element costs at least one byte, so a decoder’s total container pre-allocation is bounded by the input length rather than by depth × declared length;
  • the reserved marker 0xc1, and input that ends mid-document.

§Examples

use cachekit_core::check_msgpack_structure;

// [[[]]]: three levels, because the empty innermost array counts as one.
let doc = [0x91, 0x91, 0x90];
assert_eq!(check_msgpack_structure(&doc, 3), Ok(()));
assert_eq!(
    check_msgpack_structure(&doc, 2).unwrap_err().to_string(),
    "nests deeper than 2 levels"
);

// An array32 header claiming 2^32 - 1 elements, in five bytes.
assert_eq!(
    check_msgpack_structure(&[0xdd, 0xff, 0xff, 0xff, 0xff], 100)
        .unwrap_err()
        .to_string(),
    "declares more elements than the input can back"
);