use crate::de::ParserConfig;
use crate::error::{Error, Result};
use crate::parser;
use crate::prelude::*;
#[cfg(feature = "std")]
use crate::span_context::{self, SpanTree};
use crate::value::Value;
#[cfg(not(feature = "std"))]
use alloc::vec::IntoIter;
#[cfg(feature = "std")]
use core::marker::PhantomData;
#[cfg(feature = "std")]
use std::vec::IntoIter;
#[derive(Debug)]
pub struct DocumentIterator {
docs: IntoIter<Value>,
#[cfg(feature = "std")]
_span_trees: Vec<SpanTree>,
total: usize,
}
impl DocumentIterator {
#[must_use]
pub fn len(&self) -> usize {
self.total
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.total == 0
}
}
impl Iterator for DocumentIterator {
type Item = Result<Value>;
fn next(&mut self) -> Option<Self::Item> {
self.docs.next().map(Ok)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.docs.size_hint()
}
}
impl ExactSizeIterator for DocumentIterator {}
pub fn load_all(input: &str) -> Result<DocumentIterator> {
load_all_with_config(input, &ParserConfig::default())
}
pub fn load_all_with_config(input: &str, config: &ParserConfig) -> Result<DocumentIterator> {
if input.len() > config.max_document_length {
return Err(Error::Parse(format!(
"document exceeds maximum length of {} bytes",
config.max_document_length
)));
}
let parse_config = parser::ParseConfig::from(config);
#[cfg(feature = "std")]
{
let pairs = parser::parse(input, &parse_config)?;
let (docs, span_trees): (Vec<_>, Vec<_>) = pairs.into_iter().unzip();
let total = docs.len();
Ok(DocumentIterator {
docs: docs.into_iter(),
_span_trees: span_trees,
total,
})
}
#[cfg(not(feature = "std"))]
{
let docs = parser::parse_all_values(input, &parse_config)?;
let total = docs.len();
Ok(DocumentIterator {
docs: docs.into_iter(),
total,
})
}
}
pub fn try_load_all(input: &str) -> Result<DocumentIterator> {
load_all(input)
}
pub fn load_all_as<T>(input: &str) -> Result<Vec<T>>
where
T: for<'de> serde::Deserialize<'de> + 'static,
{
let parse_config = parser::ParseConfig::from(&ParserConfig::default());
#[cfg(feature = "std")]
{
let pairs = parser::parse(input, &parse_config)?;
let mut results = Vec::with_capacity(pairs.len());
let source: Arc<str> = input.into();
for (value, span_tree) in &pairs {
let spans = span_context::build_span_map(value, span_tree);
let ctx = span_context::SpanContext {
spans,
source: source.clone(),
};
let _guard = span_context::set_span_context(ctx);
let typed: T = crate::from_value(value)?;
results.push(typed);
}
Ok(results)
}
#[cfg(not(feature = "std"))]
{
let docs = parser::parse_all_values(input, &parse_config)?;
let mut results = Vec::with_capacity(docs.len());
for value in &docs {
let typed: T = crate::from_value(value)?;
results.push(typed);
}
Ok(results)
}
}
#[cfg(feature = "std")]
#[derive(Debug)]
pub struct DocumentReadIterator<T> {
docs: IntoIter<Value>,
_phantom: PhantomData<fn() -> T>,
}
#[cfg(feature = "std")]
impl<T> DocumentReadIterator<T> {
#[must_use]
pub fn len(&self) -> usize {
self.docs.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.docs.len() == 0
}
}
#[cfg(feature = "std")]
impl<T> Iterator for DocumentReadIterator<T>
where
T: for<'de> serde::Deserialize<'de> + 'static,
{
type Item = Result<T>;
fn next(&mut self) -> Option<Self::Item> {
let value = self.docs.next()?;
Some(crate::from_value(&value))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.docs.size_hint()
}
}
#[cfg(feature = "std")]
impl<T> ExactSizeIterator for DocumentReadIterator<T> where
T: for<'de> serde::Deserialize<'de> + 'static
{
}
#[cfg(feature = "std")]
pub fn read<R, T>(reader: R) -> Result<DocumentReadIterator<T>>
where
R: std::io::Read,
T: for<'de> serde::Deserialize<'de> + 'static,
{
read_with_config(reader, &ParserConfig::default())
}
#[cfg(feature = "std")]
pub fn read_with_config<R, T>(
mut reader: R,
config: &ParserConfig,
) -> Result<DocumentReadIterator<T>>
where
R: std::io::Read,
T: for<'de> serde::Deserialize<'de> + 'static,
{
let mut buf = String::new();
let _read_bytes = reader
.read_to_string(&mut buf)
.map_err(|e| Error::Parse(format!("reader I/O failed: {e}")))?;
if buf.len() > config.max_document_length.saturating_mul(64) {
return Err(Error::Parse(format!(
"reader payload exceeds 64× max_document_length ({} bytes)",
config.max_document_length
)));
}
let parse_config = parser::ParseConfig::from(config);
let pairs = parser::parse(&buf, &parse_config)?;
let docs: Vec<Value> = pairs.into_iter().map(|(value, _)| value).collect();
Ok(DocumentReadIterator {
docs: docs.into_iter(),
_phantom: PhantomData,
})
}