Skip to main content

Reader

Struct Reader 

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

Reads the elements of one container, in order.

Cloning one keeps where it is and how deep it sits, so a caller that has to come back to a container later can put the reader aside rather than start again from the document and count the nesting as one.

Implementations§

Source§

impl<'a> Reader<'a>

Source

pub fn integer_reading( &self, element: &Element<'a>, ) -> Result<IntegerReading<'a>>

Recover the unique numeric value while retaining nonminimal spelling.

Unlike Self::integer, this explicit diagnostic operation reads redundant sign octets. It does not declare them conforming: X.690 §§8.3.1–8.3.3 requires primitive, nonempty, minimal two’s complement already under BER. Schema layers decide how to retain the fault. https://www.itu.int/rec/T-REC-X.690-202102-I/en

Use the Reader which produced element. Like the strict reader, this supports primitive IMPLICIT tagging and leaves tag selection to the schema. Original offsets, depth and cumulative local work are retained; future work and diagnostic storage use the current execution account. Payload bytes remain borrowed. Padding is scanned once, before any bounded numeric conversion requested on the returned view.

use std::sync::Arc;
use structured_asn1::{Parser, ErrorCode};
use structured_asn1::memory::{Memory, MemoryAccount};
let memory = Memory::new(Arc::new(MemoryAccount::new(1024, 1024)));
let parser = Parser::der(memory);
let mut reader = parser.read(&[2, 2, 0, 1], 400)?;
let element = reader.next_element()?.unwrap();
let reading = reader.integer_reading(&element)?;
assert_eq!(reading.as_bytes(), &[0, 1]);
let (value, fault) = reading.into_parts();
assert_eq!(value.as_u64(), Some(1));
let fault = fault.unwrap();
assert_eq!(fault.code(), ErrorCode::IntegerNotMinimal);
assert_eq!(fault.offset(), 400);
§Errors

Empty and constructed contents remain errors. Work is admitted before scanning; failure to retain the fault path is a resource refusal, never a successful reading without its diagnostic.

Source§

impl<'a> Reader<'a>

Source

pub fn memory(&self) -> &Memory

Current domain for deferred work, copies and new storage.

Source

pub fn execution(&self) -> Execution<'_>

Borrows both the current account and original cumulative work ceiling.

Schema scratch must use this boundary when work belongs to the parse: allocator growth, copying and sorting then retain the session ceiling as well as the aggregate account. Independently retained results use Self::memory instead.

§Examples
use std::sync::Arc;
use structured_asn1::{Parser, memory::{Memory, MemoryAccount, Work}};
let parser = Parser::ber(Memory::new(Arc::new(MemoryAccount::new(1024, 1024))));
let reader = parser.read(&[], 900).unwrap();
let mut scratch = reader.execution().vector();
scratch.try_push(7_u8)?;
assert_eq!(&*scratch, &[7]);
Source

pub fn execution_in<'work>(&self, memory: &'work Memory) -> Execution<'work>
where 'a: 'work,

Borrows the source/query budgets independently of this reader cursor.

Supply the operation account explicitly so scratch can keep the same admission while the cursor advances. This creates no allocation or owning account clone and cannot discard an inherited query ceiling.

Source

pub fn with_execution(self, execution: &Memory) -> Self

Selects the domain for subsequent execution without moving existing storage charges. Offsets, depth and parser-session cumulative limits remain unchanged; a new domain does not reset that session ceiling.

Source

pub fn with_query<'query>( self, query: &Reader<'query>, ) -> Result<Reader<'query>>
where 'a: 'query,

Moves this cursor into a current query without copying its retained path. Original parser, data, offsets and depth remain unchanged. Both source and operation admission apply before changing execution; existing path capacity keeps its original owner until actually freed.

Source

pub fn try_clone(&self) -> Result<Self>

Copies the reader position and diagnostic path fallibly in the same domain.

Source

pub fn is_empty(&self) -> bool

Whether every element here has been read.

Source

pub fn parser(&self) -> &'a Parser

Original parser, whose session ceilings remain cumulative across deferred reads. Use Self::memory for the current execution domain; the parser’s storage domain may belong to an earlier operation.

Source

pub fn charge(&self, amount: u64) -> Result<()>

Charges caller-side scanning to the shared work budget.

For a schema layer that walks an element’s contents itself, text validation and named-bit walks among them: the walk costs what the bytes cost, and a caller bounding work must see that cost on the same meter the reads use.

Source

pub fn depth(&self) -> u32

How many containers deep this reader sits, counted as the depth ceiling counts it. What Parser::read_nested is given for a value found here.

Source

pub fn offset(&self) -> u64

The offset of the next unread byte, in the document.

Ordinary arithmetic, because pos never exceeds the length of data and base plus that length was shown to fit when this reader was made.

Source

pub fn remaining(&self) -> &'a [u8] ⓘ

The bytes not yet read.

Source

pub fn path(&self) -> &Path

The path to this container, for a caller building its own diagnostics.

Source

pub fn encoding(&self) -> Encoding

Which encoding this reader accepts, for a schema whose own rules differ between the two, such as the ordering DER requires of a set.

Source

pub fn reread( &self, element: &Element<'a>, encoding: Encoding, ) -> Result<Reader<'a>>

A reader over an element’s own bytes, header included, under a chosen encoding.

For a structure whose schema fixes its encoding regardless of the container’s: a certificate is DER even when the envelope carrying it is BER, and reading it with the container’s leniency would let spellings survive that the certificate’s own rules refuse. The element’s header is read again under the chosen rules, so a header only the lenient encoding accepts is refused too. Offsets stay offsets in the document and the budget stays the shared one.

Source

pub fn next_element(&mut self) -> Result<Option<Element<'a>>>

Reads the next element, or None at the end of this container.

Source

pub fn expect(&mut self, tag: Tag) -> Result<Element<'a>>

Reads the next element and requires it to carry tag.

Source

pub fn skip(&mut self) -> Result<bool>

Reads and discards the next element, whatever it is.

This is how a schema layer steps over an extension it does not know: the element is skipped within its declared length, so an unknown tag costs what a known one costs and cannot make the reader wander.

Source

pub fn enter(&self, element: &Element<'a>) -> Result<Reader<'a>>

A reader over the contents of a constructed element read from here.

Refused for a primitive element: its contents are a value rather than further elements, and reading them as elements is how a parser is talked into finding structure inside an octet string that nobody put there.

Source

pub fn oid(&self, element: &Element<'a>) -> Result<Oid<'a>>

Reads an element’s contents as an object identifier.

Source

pub fn integer(&self, element: &Element<'a>) -> Result<Integer<'a>>

Reads an element’s contents as an integer.

Source

pub fn bit_string(&self, element: &Element<'a>) -> Result<BitString<'a>>

Reads an element’s contents as a bit string.

The segmented form BER allows for a constructed bit string is refused: every bit string this product reads is covered by a signature computed over the bytes, where one value with two spellings is one value too many.

Source

pub fn boolean(&self, element: &Element<'a>) -> Result<bool>

Reads an element’s contents as a boolean.

Source

pub fn null(&self, element: &Element<'a>) -> Result<()>

Reads an element’s contents as a null, which has none.

Source

pub fn real(&self, element: &Element<'a>) -> Result<()>

Reads an element’s contents as a real, and answers only whether they are a value of the type.

The number itself is not read: no schema this product parses has a real in it, and one arrives only inside a value preserved for somebody else, who is promised octets that are what they claim.

Source

pub fn read_oid(&mut self) -> Result<Oid<'a>>

Reads the next element as an object identifier.

Source

pub fn read_integer(&mut self) -> Result<Integer<'a>>

Reads the next element as an integer.

Source

pub fn read_bit_string(&mut self) -> Result<BitString<'a>>

Reads the next element as a bit string.

Source

pub fn read_boolean(&mut self) -> Result<bool>

Reads the next element as a boolean.

Source

pub fn fail_under(&self, code: ErrorCode, element: &Element<'a>) -> Error

An error naming an element read from this container.

Trait Implementations§

Source§

impl<'a> Debug for Reader<'a>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !Freeze for Reader<'a>

§

impl<'a> !RefUnwindSafe for Reader<'a>

§

impl<'a> !Send for Reader<'a>

§

impl<'a> !Sync for Reader<'a>

§

impl<'a> !UnwindSafe for Reader<'a>

§

impl<'a> Unpin for Reader<'a>

§

impl<'a> UnsafeUnpin for Reader<'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 = !

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

fn try_from(value: U) -> Result<T, !>

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.