Skip to main content

read

Function read 

Source
pub fn read<'a, R, T>(
    reader: &'a mut R,
) -> 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 using default options.

This is a convenience wrapper around read_with_options that uses the same defaults as Options::default except it disables the max_reader_input_bytes budget to better support long-lived streams.

  • It streams the reader without loading the whole input into memory.
  • Each item produced by the returned iterator is one deserialized YAML document of type T.
  • Empty, untagged null-like, and explicit !!null documents are skipped. Application-tagged roots are deserialized, even with null payloads.

Generic parameters

  • R: the concrete reader type implementing std::io::Read. You almost never need to write this explicitly; the compiler will infer it from the reader you pass. When using turbofish, write _ to let the compiler infer R.
  • T: the type to deserialize each YAML document into. Must implement [serde::de::DeserializeOwned].

Lifetimes

  • 'a: the lifetime of the returned iterator, tied to the lifetime of the provided reader. The iterator cannot outlive the reader it was created from.

Limits and budget

  • Uses the same limits as Options::default() (events, nodes, nesting depth, total scalar bytes, total comment bytes) and the default alias-replay caps. The only change is that Budget::max_reader_input_bytes is set to None so the streaming iterator can handle arbitrarily long inputs. To customize these limits, call read_with_options and set Options::budget.max_reader_input_bytes in the provided Options.
  • Alias replay limits are also enforced with their default values 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), `_` lets the compiler infer it.
let iter = serde_saphyr::read::<_, Simple>(&mut reader);
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 skips to the next document boundary (---) and continues.
  • After a syntax error or budget/alias limit exceeded, the iterator ends.
  • Null documents without an application tag are skipped and produce no items.

Note Some content of the next document is read before the current parsed document is emitted. Hence, while streaming is good for safely parsing large files with multiple documents without loading it into RAM in advance, it does not emit each document exactly after --- is encountered.