Skip to main content

DecodeOptions

Struct DecodeOptions 

Source
pub struct DecodeOptions { /* private fields */ }
Expand description

Configuration for CBOR decoding.

DecodeOptions controls the input format (Binary, Hex, or Diagnostic) and the limits the decoder enforces against hostile or malformed input. Construct it with DecodeOptions::new (or Default), adjust settings with the builder methods, and call decode or read_from for a single item, or sequence_decoder / sequence_reader for a CBOR sequence.

The convenience methods on Value (decode, decode_hex, read_from, read_hex_from) all forward to a default DecodeOptions. Use this type directly when you need to decode diagnostic notation, iterate a sequence, relax a limit for a known input, or tighten one for untrusted input.

§Options

OptionDefaultPurpose
formatBinaryInput syntax: binary, hex text, or diagnostic notation.
recursion_limit200Maximum nesting depth of arrays, maps, and tags.
length_limit1,000,000,000Maximum declared element count of a single array, map, byte string, or text string.
oom_mitigation100,000,000Byte budget for speculative pre-allocation.

§recursion_limit

Each array, map, or tag consumes one unit of recursion budget for its contents. Exceeding the limit returns Error::NestingTooDeep. The limit protects against stack overflow on adversarial input and should be well below the stack a thread has available.

§length_limit

Applies to the length field in the CBOR head of arrays, maps, byte strings, and text strings. It caps the declared size before any bytes are read, so a malicious header claiming a petabyte-long string is rejected immediately with Error::LengthTooLarge. The limit does not restrict total input size; a valid document may contain many items each up to the limit.

§oom_mitigation

CBOR encodes lengths in the head, so a decoder is tempted to pre-allocate a Vec of the declared capacity. On hostile input that is a trivial amplification attack: a few bytes on the wire reserve gigabytes of memory. oom_mitigation is a byte budget, shared across the current decode, that caps the total amount of speculative capacity the decoder may reserve for array backing storage. Once the budget is exhausted, further arrays start empty and grow on demand. Decoding still succeeds if the input is well-formed; only the up-front reservation is bounded.

The budget is consumed, not refilled: a deeply nested structure with many small arrays can drain it early and decode the tail with zero pre-allocation. That is the intended behavior.

§Examples

Decode binary CBOR with default limits:

use cbor_core::DecodeOptions;

let v = DecodeOptions::new().decode([0x18, 42]).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

Switch the input format to hex text or diagnostic notation:

use cbor_core::{DecodeOptions, Format};

let v = DecodeOptions::new().format(Format::Hex).decode("182a").unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

let v = DecodeOptions::new().format(Format::Diagnostic).decode("42").unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

Tighten limits for input from an untrusted source:

use cbor_core::DecodeOptions;

let strict = DecodeOptions::new()
    .recursion_limit(16)
    .length_limit(4096)
    .oom_mitigation(64 * 1024);

assert!(strict.decode([0x18, 42]).is_ok());

Implementations§

Source§

impl DecodeOptions

Source

pub const fn new() -> Self

Create a new set of options with the crate defaults.

use cbor_core::DecodeOptions;

let opts = DecodeOptions::new();
let v = opts.decode([0x18, 42]).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);
Source

pub const fn format(self, format: Format) -> Self

Select the input format: Binary, Hex, or Diagnostic.

Default: Format::Binary.

use cbor_core::{DecodeOptions, Format};

let hex = DecodeOptions::new().format(Format::Hex).decode("182a").unwrap();
let bin = DecodeOptions::new().decode([0x18, 0x2a]).unwrap();
assert_eq!(hex, bin);

let v = DecodeOptions::new().format(Format::Diagnostic).decode("42").unwrap();
assert_eq!(v.to_u32().unwrap(), 42);
Source

pub const fn recursion_limit(self, limit: u16) -> Self

Set the maximum nesting depth of arrays, maps, and tags.

Default: 200. Input that exceeds the limit returns Error::NestingTooDeep.

use cbor_core::{DecodeOptions, Error};

// Two nested one-element arrays: 0x81 0x81 0x00
let err = DecodeOptions::new()
    .recursion_limit(1)
    .decode([0x81, 0x81, 0x00])
    .unwrap_err();
assert_eq!(err, Error::NestingTooDeep);
Source

pub const fn length_limit(self, limit: u64) -> Self

Set the maximum declared length for byte strings, text strings, arrays, and maps.

Default: 1,000,000,000. Checked against the length field in the CBOR head before any bytes are consumed; an oversized declaration returns Error::LengthTooLarge.

use cbor_core::{DecodeOptions, Error};

// A five-byte text string: 0x65 'h' 'e' 'l' 'l' 'o'
let err = DecodeOptions::new()
    .length_limit(4)
    .decode(b"\x65hello")
    .unwrap_err();
assert_eq!(err, Error::LengthTooLarge);
Source

pub const fn oom_mitigation(self, bytes: usize) -> Self

Set the byte budget for speculative pre-allocation of array backing storage.

Default: 100,000,000. Lower values trade a small amount of decoding throughput for stronger resistance to memory-amplification attacks. Valid input decodes regardless; only the up-front reservation is bounded.

use cbor_core::DecodeOptions;

// A two-element array: 0x82 0x01 0x02
let v = DecodeOptions::new()
    .oom_mitigation(0)
    .decode([0x82, 0x01, 0x02])
    .unwrap();
assert_eq!(v.len(), Some(2));
Source

pub fn decode(&self, bytes: impl AsRef<[u8]>) -> Result<Value>

Decode exactly one CBOR data item from an in-memory buffer.

Accepts any AsRef<[u8]>: &[u8], Vec<u8>, &str, String, and so on. The input must contain exactly one value: any bytes remaining after a successful decode cause Error::InvalidFormat. In Format::Diagnostic mode trailing whitespace and comments are accepted, but nothing else. Use sequence_decoder when the input is a CBOR sequence.

An empty buffer (and, for diagnostic notation, one containing only whitespace and comments) returns Error::UnexpectedEof. A partial value returns Error::UnexpectedEof too.

use cbor_core::{DecodeOptions, Format};

let v = DecodeOptions::new().decode([0x18, 42]).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

let v = DecodeOptions::new().format(Format::Hex).decode("182a").unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

let v = DecodeOptions::new()
    .format(Format::Diagnostic)
    .decode("42  / trailing comment is fine /")
    .unwrap();
assert_eq!(v.to_u32().unwrap(), 42);
Source

pub fn read_from(&self, reader: impl Read) -> IoResult<Value>

Read a single CBOR data item from a stream.

Designed to be called repeatedly to pull successive elements of a CBOR sequence:

  • In Format::Binary and Format::Hex the reader is consumed only up to the end of the item; any bytes after remain in the stream.
  • In Format::Diagnostic trailing whitespace and comments are consumed up to either end of stream or a top-level separator comma (the comma is also consumed). Anything else after the value fails with Error::InvalidFormat.

I/O failures are returned as IoError::Io; malformed or oversized input as IoError::Data.

use cbor_core::{DecodeOptions, Format};

let mut bytes: &[u8] = &[0x18, 42];
let v = DecodeOptions::new().read_from(&mut bytes).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

let mut hex: &[u8] = b"182a";
let v = DecodeOptions::new().format(Format::Hex).read_from(&mut hex).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);

// Diagnostic: repeated read_from pulls successive sequence items.
let mut diag: &[u8] = b"1, 2, 3";
let opts = DecodeOptions::new().format(Format::Diagnostic);
let a = opts.read_from(&mut diag).unwrap();
let b = opts.read_from(&mut diag).unwrap();
let c = opts.read_from(&mut diag).unwrap();
assert_eq!(a.to_u32().unwrap(), 1);
assert_eq!(b.to_u32().unwrap(), 2);
assert_eq!(c.to_u32().unwrap(), 3);
Source

pub fn sequence_decoder<'a, B: AsRef<[u8]> + ?Sized>( &self, input: &'a B, ) -> SequenceDecoder<'a>

Create an iterator over a CBOR sequence stored in memory.

The returned SequenceDecoder yields each successive item of the sequence as Result<Value>. The iterator captures a snapshot of these options; subsequent changes to self do not affect it.

use cbor_core::{DecodeOptions, Format};

let opts = DecodeOptions::new().format(Format::Diagnostic);

let items: Vec<_> = opts
    .sequence_decoder(b"1, 2, 3,")
    .collect::<Result<_, _>>()
    .unwrap();
assert_eq!(items.len(), 3);
Source

pub fn sequence_reader<R: Read>(&self, reader: R) -> SequenceReader<R>

Create an iterator over a CBOR sequence read from a stream.

The returned SequenceReader yields each successive item as IoResult<Value>. None indicates a clean end between items; a truncated item produces Some(Err(_)).

use cbor_core::DecodeOptions;

// Binary CBOR sequence: three one-byte items 0x01 0x02 0x03.
let bytes: &[u8] = &[0x01, 0x02, 0x03];
let items: Vec<_> = DecodeOptions::new()
    .sequence_reader(bytes)
    .collect::<Result<_, _>>()
    .unwrap();
assert_eq!(items.len(), 3);

Trait Implementations§

Source§

impl Clone for DecodeOptions

Source§

fn clone(&self) -> DecodeOptions

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DecodeOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DecodeOptions

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> StrictAs for T

Source§

fn strict_as<Dst>(self) -> Dst
where T: StrictCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> StrictCastFrom<Src> for Dst
where Src: StrictCast<Dst>,

Source§

fn strict_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.