Skip to main content

read_with_options

Function read_with_options 

Source
pub fn read_with_options<'a, R, T>(
    reader: &'a mut R,
    options: Options,
) -> impl Iterator<Item = Result<T, Error>> + 'a
where R: Read + 'a, T: DeserializeOwned + 'a,
Expand description

Create an iterator over YAML documents from any std::io::Read, with configurable options.

This is the multi-document counterpart to from_reader_with_options. It does not load the entire input into memory. Instead, it streams the reader, deserializing one document at a time into values of type T, yielding them through the returned iterator. Documents that are empty, untagged null-like, or explicitly tagged !!null are skipped. With DockerComposeWithNulls, interpolated nulls are also skipped. Application-tagged roots are deserialized, even with null payloads. Like from_reader_with_options, BOM-marked UTF-8, UTF-16LE, and UTF-16BE inputs are transcoded to UTF-8 internally before parsing. If no recognized BOM is present, the input bytes are treated as UTF-8.

Generic parameters

  • R: the concrete reader type that implements std::io::Read. You rarely need to spell this out; it is almost always inferred from the reader value you pass in. When using turbofish, you can write _ for this parameter to let the compiler infer it.
  • T: the type to deserialize each YAML document into. This must implement [serde::de::DeserializeOwned].

Lifetimes

  • 'a: the lifetime of the returned iterator. It is tied to the lifetime of the provided reader value because the iterator borrows internal state that references the reader. In practice, this means the iterator cannot outlive the reader it was created from.

Limits and budget

  • All parsing limits configured via Options::budget (such as maximum events, nodes, nesting depth, total scalar bytes, total comment bytes) are enforced while streaming. The reader input-byte cap is also enforced via Budget::max_reader_input_bytes (256 MiB by default). Set this to None if the stream may legitimately run without a fixed byte cap.
  • Alias replay limits from Options::alias_limits are also enforced to mitigate alias bombs.
use serde::Deserialize;

#[derive(Debug, Deserialize, PartialEq)]
struct Simple { id: usize }

let yaml = b"id: 1\n---\nid: 2\n";
let mut reader = std::io::Cursor::new(&yaml[..]);

// Type `T` is inferred from the collection target (Vec<Simple>).
let values: Vec<Simple> = serde_saphyr::read(&mut reader)
    .map(|r| r.unwrap())
    .collect();
assert_eq!(values.len(), 2);
assert_eq!(values[0].id, 1);

Specifying only T with turbofish and letting R be inferred using _:

use serde::Deserialize;

#[derive(Debug, Deserialize, PartialEq)]
struct Simple { id: usize }

let yaml = b"id: 10\n---\nid: 20\n";
let mut reader = std::io::Cursor::new(&yaml[..]);

// First turbofish parameter is R (reader type) which we let the compiler infer via `_`.
let iter = serde_saphyr::read_with_options::<_, Simple>(&mut reader, serde_saphyr::Options::default());
let ids: Vec<usize> = iter.map(|res| res.unwrap().id).collect();
assert_eq!(ids, vec![10, 20]);
  • Each next() yields either Ok(T) for a successfully deserialized document or Err(Error) if parsing or deserialization fails.
  • After a deserialization error (e.g., type mismatch, missing field), the iterator automatically recovers by skipping to the next document boundary (---) and continues iteration. This allows processing subsequent valid documents even when some fail.
  • After a syntax error or budget/alias limit exceeded, the iterator ends because the parser state may be unrecoverable.
  • Null documents without an application tag are skipped and produce no items.