Skip to main content

TlvReader

Struct TlvReader 

Source
pub struct TlvReader<'a> { /* private fields */ }
Expand description

A streaming TLV decoder over a borrowed byte slice.

Implementations§

Source§

impl<'a> TlvReader<'a>

Source

pub fn new(bytes: &'a [u8]) -> Self

Construct a reader that walks bytes from the start, using the DEFAULT_ELEMENT_BUDGET for tree-builder decodes.

Source

pub fn with_element_budget(bytes: &'a [u8], budget: usize) -> Self

Construct a reader with a custom total-element budget for tree-builder decoding (see DEFAULT_ELEMENT_BUDGET).

A Self::read_value call that would materialise more than budget Value elements fails with Error::ElementBudgetExceeded. The budget only affects the tree-builder path; the streaming Self::next API is unaffected because it allocates nothing per element.

Source

pub fn is_empty(&self) -> bool

Whether there is no more input to consume.

Source

pub fn next(&mut self) -> Result<Option<Element>>

Advance one TLV element, returning an Element that owns its string/bytes payloads. Implemented over Self::next_ref — the borrowed walk IS the decode core, so the two can never disagree. Returns Ok(None) at end of input. See Self::next_ref for the zero-copy variant, which borrows string/bytes payloads from the input instead of allocating.

§Errors

Returns Err if the input is malformed:

§Note on naming

This method is deliberately named next to match the streaming-reader idiom established by e.g. serde’s Deserializer. It returns Result<Option<T>> rather than Option<Result<T>> so that callers use ? naturally. Implementing std::iter::Iterator is deferred to a later phase when a fallible-iterator adapter is available.

Source

pub fn next_ref(&mut self) -> Result<Option<ElementRef<'a>>>

Advance one TLV element, returning an ElementRef whose string/bytes payloads borrow directly from the reader’s input — the zero-copy sibling of Self::next, and the single decode core both methods share. Returns Ok(None) at end of input.

§Errors

Returns Err if the input is malformed:

Source

pub fn skip_container(&mut self) -> Result<()>

Skip the remaining body of the container whose ContainerStart was just returned by Self::next, consuming through its matching ContainerEnd.

Call this immediately after next() yields a ContainerStart you want to discard — for example an unknown field carried by a struct from a newer Matter revision. On return the reader is positioned at the first element after the skipped container. The container body is skipped as a raw byte walk: nothing is materialised, and string payloads inside the skipped (unobserved) region are not UTF-8 validated. Cost is bounded by the input size and nesting by MAX_DEPTH.

§Errors

After a successful skip, Self::element_span reports the whole skipped container (header through end-of-container marker) — same as calling Self::skip_container_span and discarding the return value.

§Examples
use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter};
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous)?;
w.start_structure(Tag::Context(9))?; // an unknown nested field
w.end_container()?;
w.put_uint(Tag::Context(1), 42)?;
w.end_container()?;

let mut r = TlvReader::new(&buf);
r.next()?; // open the outer struct
// next() returns the nested ctx9 ContainerStart we want to discard:
assert!(matches!(
    r.next()?,
    Some(Element::ContainerStart { kind: ContainerKind::Structure, .. })
));
r.skip_container()?; // drain the nested struct
// the field after the unknown container is still readable:
assert!(matches!(r.next()?, Some(Element::Scalar { tag: Tag::Context(1), .. })));

After an Err from this method, the reader’s position and depth are unspecified — discard the reader rather than continuing to iterate.

Source

pub fn skip_container_span(&mut self) -> Result<ElementSpan>

Like Self::skip_container, but returns the skipped container’s ElementSpan (marked at the ContainerStart just returned by next(); ended at the read position after the raw skip).

This method has a precondition: the immediately preceding Self::next / Self::next_ref call must have returned a ContainerStart. Anywhere else — after a scalar, after an end-of-container, after a Self::read_value that walked a whole tree, after another skip, or before any element at all — it consumes nothing and returns Error::UnexpectedEndOfContainer, rather than handing back a span over unrelated bytes that a retag caller would re-emit as malformed TLV.

§Errors

Error::UnexpectedEndOfContainer if the precondition above does not hold, plus every error Self::skip_container can return. Misuse is always an error — never a panic, and never a meaningless span.

After an Err from this method, the reader’s position and depth are unspecified — discard the reader rather than continuing to iterate.

Source

pub fn element_span(&self) -> Option<ElementSpan>

Span of the element most recently returned by Self::next / Self::next_ref (or the whole container after a skip_container* call). None before the first element; unchanged by calls that return Ok(None) or an error.

Tree-builder reads drive the same core: Self::read_value walks its element via Self::next_ref internally, so afterwards the span refers to the last interior element it consumed, not the tree as a whole. Read the span only immediately after the next / next_ref call whose element you care about.

Source

pub fn span_bytes(&self, range: Range<usize>) -> &'a [u8]

Resolve a range produced by this reader’s span APIs against the reader’s input. Returns an empty slice for a range that does not lie within the input (only possible with a span from a different reader).

Source

pub fn read_value(&mut self) -> Result<(Tag, Value)>

Materialise one full TLV element as a (Tag, Value). Scalars are returned directly; containers are read recursively up to MAX_DEPTH levels (enforced by Self::next’s depth counter).

§Errors

Auto Trait Implementations§

§

impl<'a> Freeze for TlvReader<'a>

§

impl<'a> RefUnwindSafe for TlvReader<'a>

§

impl<'a> Send for TlvReader<'a>

§

impl<'a> Sync for TlvReader<'a>

§

impl<'a> Unpin for TlvReader<'a>

§

impl<'a> UnsafeUnpin for TlvReader<'a>

§

impl<'a> UnwindSafe for TlvReader<'a>

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> 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<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, 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.