#![forbid(unsafe_code)]
#![allow(deprecated)]
pub use anchors::{
ArcAnchor, ArcRecursion, ArcRecursive, ArcWeakAnchor, RcAnchor, RcRecursion, RcRecursive,
RcWeakAnchor,
};
pub use de::{Budget, DuplicateKeyPolicy, Error, Options};
pub use de_error::TransformReason;
pub use de_error::CroppedRegion;
pub use de_error::{MessageFormatter, RenderOptions, SnippetMode, UserMessageFormatter};
pub use localizer::{DefaultEnglishLocalizer, ExternalMessage, ExternalMessageSource, Localizer, DEFAULT_ENGLISH_LOCALIZER};
pub use message_formatters::{DefaultMessageFormatter, DeveloperMessageFormatter};
pub use location::{Location, Locations, Span};
pub use long_strings::{FoldStr, FoldString, LitStr, LitString};
pub use ser::{Commented, FlowMap, FlowSeq, SpaceAfter};
pub use spanned::Spanned;
use crate::budget::EnforcingPolicy;
use crate::de::{Ev, Events};
use crate::live_events::LiveEvents;
use crate::parse_scalars::scalar_is_nullish;
pub use crate::serializer_options::SerializerOptions;
use serde::de::DeserializeOwned;
use std::io::Read;
#[cfg(feature = "garde")]
use garde::Validate;
#[cfg(feature = "validator")]
use validator::Validate as ValidatorValidate;
mod anchor_store;
mod anchors;
mod base64;
pub mod budget;
mod de;
mod message_formatters;
mod de_error;
#[path = "localizer.rs"]
pub mod localizer;
#[path = "de/snippet.rs"]
mod de_snipped;
mod live_events;
mod long_strings;
pub mod options;
mod parse_scalars;
pub mod ser;
mod spanned;
#[cfg(any(feature = "garde", feature = "validator"))]
pub mod path_map;
pub mod ser_error;
pub use de::YamlDeserializer as Deserializer;
pub use ser::YamlSerializer as Serializer;
pub use de::{
with_deserializer_from_reader, with_deserializer_from_reader_with_options,
with_deserializer_from_slice, with_deserializer_from_slice_with_options,
with_deserializer_from_str, with_deserializer_from_str_with_options,
};
mod serializer_options;
mod macros;
mod tags;
pub(crate) mod ser_quoting;
mod buffered_input;
mod location;
#[cfg(feature = "robotics")]
pub mod robotics;
#[cfg(feature = "miette")]
pub mod miette;
#[cfg(feature = "figment")]
pub mod figment;
pub(crate) mod ring_reader;
mod wrapping;
mod zmij_format;
pub fn to_string<T: serde::Serialize>(value: &T) -> std::result::Result<String, crate::ser::Error> {
let mut out = String::new();
to_fmt_writer(&mut out, value)?;
Ok(out)
}
pub fn to_string_with_options<T: serde::Serialize>(
value: &T,
options: SerializerOptions,
) -> std::result::Result<String, crate::ser::Error> {
let mut out = String::new();
to_fmt_writer_with_options(&mut out, value, options)?;
Ok(out)
}
#[deprecated(
since = "0.0.7",
note = "Use `to_fmt_writer` for `fmt::Write` (String, fmt::Formatter) or `to_io_writer` for files/sockets."
)]
pub fn to_writer<W: std::fmt::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
) -> std::result::Result<(), crate::ser::Error> {
let mut ser = crate::ser::YamlSerializer::new(output);
value.serialize(&mut ser)
}
pub fn to_fmt_writer<W: std::fmt::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
) -> std::result::Result<(), crate::ser::Error> {
to_fmt_writer_with_options(output, value, SerializerOptions::default())
}
pub fn to_io_writer<W: std::io::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
) -> std::result::Result<(), crate::ser::Error> {
to_io_writer_with_options(output, value, SerializerOptions::default())
}
pub fn to_fmt_writer_with_options<W: std::fmt::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
mut options: SerializerOptions,
) -> std::result::Result<(), crate::ser::Error> {
options.consistent()?;
let mut ser = crate::ser::YamlSerializer::with_options(output, &mut options);
value.serialize(&mut ser)
}
pub fn to_io_writer_with_options<W: std::io::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
mut options: SerializerOptions,
) -> std::result::Result<(), crate::ser::Error> {
options.consistent()?;
struct Adapter<'a, W: std::io::Write> {
output: &'a mut W,
last_err: Option<std::io::Error>,
}
impl<'a, W: std::io::Write> std::fmt::Write for Adapter<'a, W> {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
if let Err(e) = self.output.write_all(s.as_bytes()) {
self.last_err = Some(e);
return Err(std::fmt::Error);
}
Ok(())
}
fn write_char(&mut self, c: char) -> std::fmt::Result {
let mut buf = [0u8; 4];
let s = c.encode_utf8(&mut buf);
self.write_str(s)
}
}
let mut adapter = Adapter {
output,
last_err: None,
};
let mut ser = crate::ser::YamlSerializer::with_options(&mut adapter, &mut options);
match value.serialize(&mut ser) {
Ok(()) => Ok(()),
Err(e) => {
if let Some(io_error) = adapter.last_err.take() {
return Err(crate::ser::Error::from(io_error));
}
Err(e)
}
}
}
#[deprecated(
since = "0.0.7",
note = "Use `to_fmt_writer_with_options` for fmt::Write or `to_io_writer_with_options` for io::Write."
)]
pub fn to_writer_with_options<W: std::fmt::Write, T: serde::Serialize>(
output: &mut W,
value: &T,
options: SerializerOptions,
) -> std::result::Result<(), crate::ser::Error> {
to_fmt_writer_with_options(output, value, options)
}
pub fn from_str<'de, T>(input: &'de str) -> Result<T, Error>
where
T: serde::de::Deserialize<'de>,
{
from_str_with_options(input, Options::default())
}
#[allow(deprecated)]
fn from_str_with_options_impl<'de, T>(input: &'de str, options: Options) -> Result<T, Error>
where
T: serde::de::Deserialize<'de>,
{
let input = if let Some(rest) = input.strip_prefix('\u{FEFF}') {
rest
} else {
input
};
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_str(
input,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
);
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new(&mut src, cfg))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if src.synthesized_null_emitted() {
let err = Error::eof().with_location(src.last_location());
return Err(maybe_with_snippet(err, input, with_snippet, crop_radius));
} else {
return Err(maybe_with_snippet(e, input, with_snippet, crop_radius));
}
}
};
match src.peek() {
Ok(Some(_)) => {
let err = Error::multiple_documents(
"use from_multiple or from_multiple_with_options",
)
.with_location(src.last_location());
return Err(maybe_with_snippet(err, input, with_snippet, crop_radius));
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(maybe_with_snippet(e, input, with_snippet, crop_radius));
}
}
}
src.finish()
.map_err(|e| maybe_with_snippet(e, input, with_snippet, crop_radius))?;
Ok(value)
}
#[allow(deprecated)]
pub fn from_str_with_options<'de, T>(input: &'de str, options: Options) -> Result<T, Error>
where
T: serde::de::Deserialize<'de>,
{
from_str_with_options_impl(input, options)
}
#[cfg(any(feature = "garde", feature = "validator"))]
#[allow(deprecated)]
fn from_str_with_options_and_path_recorder<T: DeserializeOwned>(
input: &str,
options: Options,
) -> Result<(T, crate::path_map::PathRecorder), Error> {
let input = if let Some(rest) = input.strip_prefix('\u{FEFF}') {
rest
} else {
input
};
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_str(
input,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
);
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut src,
cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if src.synthesized_null_emitted() {
let err = Error::eof().with_location(src.last_location());
return Err(maybe_with_snippet(err, input, with_snippet, crop_radius));
} else {
return Err(maybe_with_snippet(e, input, with_snippet, crop_radius));
}
}
};
match src.peek() {
Ok(Some(_)) => {
let err = Error::multiple_documents(
"use from_multiple or from_multiple_with_options",
)
.with_location(src.last_location());
return Err(maybe_with_snippet(err, input, with_snippet, crop_radius));
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(maybe_with_snippet(e, input, with_snippet, crop_radius));
}
}
}
src.finish()
.map_err(|e| maybe_with_snippet(e, input, with_snippet, crop_radius))?;
Ok((value, recorder))
}
#[cfg(feature = "garde")]
pub fn from_str_valid<T>(input: &str) -> Result<T, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
from_str_with_options_valid(input, Options::default())
}
#[cfg(feature = "garde")]
pub fn from_str_with_options_valid<T>(input: &str, options: Options) -> Result<T, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let (v, recorder) = from_str_with_options_and_path_recorder::<T>(input, options)?;
match Validate::validate(&v) {
Ok(()) => Ok(v),
Err(report) => {
let err = Error::ValidationError {
report,
locations: recorder.map,
};
Err(maybe_with_snippet(err, input, with_snippet, crop_radius))
}
}
}
#[cfg(feature = "garde")]
pub fn from_str_with_options_context_valid<T>(
input: &str,
options: Options,
context: &<T as garde::Validate>::Context,
) -> Result<T, Error>
where
T: DeserializeOwned + garde::Validate,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let (v, recorder) = from_str_with_options_and_path_recorder::<T>(input, options)?;
match Validate::validate_with(&v, context) {
Ok(()) => Ok(v),
Err(report) => {
let err = Error::ValidationError {
report,
locations: recorder.map,
};
Err(maybe_with_snippet(err, input, with_snippet, crop_radius))
}
}
}
#[cfg(feature = "garde")]
pub fn from_multiple_valid<T: DeserializeOwned + garde::Validate>(
input: &str,
) -> Result<Vec<T>, Error>
where
<T as garde::Validate>::Context: Default,
{
from_multiple_with_options_valid(input, Options::default())
}
#[cfg(feature = "garde")]
#[allow(deprecated)]
pub fn from_multiple_with_options_valid<T>(input: &str, options: Options) -> Result<Vec<T>, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_str(
input,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
);
let mut values = Vec::new();
let mut validation_errors: Vec<Error> = Vec::new();
loop {
match src.peek()? {
Some(Ev::Scalar {
value: s, style, ..
}) if scalar_is_nullish(s, style) => {
let _ = src.next()?; continue;
}
Some(_) => {
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut src,
cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => return Err(maybe_with_snippet(e, input, with_snippet, crop_radius)),
};
match Validate::validate(&value) {
Ok(()) => {
values.push(value);
}
Err(report) => {
let err = Error::ValidationError {
report,
locations: recorder.map,
};
validation_errors.push(maybe_with_snippet(
err,
input,
with_snippet,
crop_radius,
));
}
}
}
None => break,
}
}
src.finish()
.map_err(|e| maybe_with_snippet(e, input, with_snippet, crop_radius))?;
if validation_errors.is_empty() {
Ok(values)
} else {
Err(Error::ValidationErrors {
errors: validation_errors,
})
}
}
#[cfg(feature = "garde")]
pub fn from_slice_valid<T: DeserializeOwned + garde::Validate>(bytes: &[u8]) -> Result<T, Error>
where
<T as garde::Validate>::Context: Default,
{
from_slice_with_options_valid(bytes, Options::default())
}
#[cfg(feature = "garde")]
pub fn from_slice_with_options_valid<T: DeserializeOwned + garde::Validate>(
bytes: &[u8],
options: Options,
) -> Result<T, Error>
where
<T as garde::Validate>::Context: Default,
{
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_str_with_options_valid(s, options)
}
#[cfg(feature = "garde")]
pub fn from_slice_multiple_with_options_valid<T>(
bytes: &[u8],
options: Options,
) -> Result<Vec<T>, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_multiple_with_options_valid(s, options)
}
#[cfg(feature = "garde")]
pub fn from_reader_valid<R: std::io::Read, T>(reader: R) -> Result<T, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
from_reader_with_options_valid(reader, Options::default())
}
#[cfg(feature = "garde")]
#[allow(deprecated)]
pub fn from_reader_with_options_valid<R: std::io::Read, T>(
reader: R,
options: Options,
) -> Result<T, Error>
where
T: DeserializeOwned + garde::Validate,
<T as garde::Validate>::Context: Default,
{
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_reader(
reader,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::AllContent,
);
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut src,
cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if src.synthesized_null_emitted() {
return Err(Error::eof().with_location(src.last_location()));
} else {
return Err(e);
}
}
};
if let Err(report) = Validate::validate(&value) {
return Err(Error::ValidationError {
report,
locations: recorder.map,
});
}
match src.peek() {
Ok(Some(_)) => {
return Err(
Error::multiple_documents(
"use read_valid or read_with_options_valid to obtain the iterator",
)
.with_location(src.last_location()),
);
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(e);
}
}
}
src.finish()?;
Ok(value)
}
#[cfg(feature = "garde")]
pub fn read_valid<'a, R, T>(reader: &'a mut R) -> impl Iterator<Item = Result<T, Error>> + 'a
where
R: Read + 'a,
T: DeserializeOwned + garde::Validate + 'a,
<T as garde::Validate>::Context: Default,
{
read_with_options_valid(reader, Default::default())
}
#[cfg(feature = "garde")]
#[allow(deprecated)]
pub fn read_with_options_valid<'a, R, T>(
reader: &'a mut R,
options: Options,
) -> impl Iterator<Item = Result<T, Error>> + 'a
where
R: Read + 'a,
T: DeserializeOwned + garde::Validate + 'a,
<T as garde::Validate>::Context: Default,
{
struct ReadValidIter<'a, T> {
src: LiveEvents<'a>, cfg: crate::de::Cfg,
finished: bool,
_marker: std::marker::PhantomData<T>,
}
impl<'a, T> Iterator for ReadValidIter<'a, T>
where
T: DeserializeOwned + garde::Validate + 'a,
<T as garde::Validate>::Context: Default,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
loop {
match self.src.peek() {
Ok(Some(Ev::Scalar { value, style, .. }))
if scalar_is_nullish(value, style) =>
{
let _ = self.src.next();
continue;
}
Ok(Some(_)) => {
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut self.src,
self.cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if !self.src.skip_to_next_document() {
self.finished = true;
}
return Some(Err(e));
}
};
match Validate::validate(&value) {
Ok(()) => return Some(Ok(value)),
Err(report) => {
return Some(Err(Error::ValidationError {
report,
locations: recorder.map,
}));
}
}
}
Ok(None) => {
self.finished = true;
if let Err(e) = self.src.finish() {
return Some(Err(e));
}
return None;
}
Err(e) => {
self.finished = true;
let _ = self.src.finish();
return Some(Err(e));
}
}
}
}
}
let cfg = crate::de::Cfg::from_options(&options);
let src = LiveEvents::from_reader(
reader,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::PerDocument,
);
ReadValidIter::<T> {
src,
cfg,
finished: false,
_marker: std::marker::PhantomData,
}
}
#[cfg(feature = "validator")]
pub fn from_str_validate<T>(input: &str) -> Result<T, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
from_str_with_options_validate(input, Options::default())
}
#[cfg(feature = "validator")]
pub fn from_str_with_options_validate<T>(input: &str, options: Options) -> Result<T, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let (v, recorder) = from_str_with_options_and_path_recorder::<T>(input, options)?;
match ValidatorValidate::validate(&v) {
Ok(()) => Ok(v),
Err(errors) => {
let err = Error::ValidatorError {
errors,
locations: recorder.map,
};
Err(maybe_with_snippet(err, input, with_snippet, crop_radius))
}
}
}
#[cfg(feature = "validator")]
pub fn from_multiple_validate<T: DeserializeOwned + ValidatorValidate>(
input: &str,
) -> Result<Vec<T>, Error> {
from_multiple_with_options_validate(input, Options::default())
}
#[cfg(feature = "validator")]
#[allow(deprecated)]
pub fn from_multiple_with_options_validate<T>(
input: &str,
options: Options,
) -> Result<Vec<T>, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_str(
input,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
);
let mut values = Vec::new();
let mut validation_errors: Vec<Error> = Vec::new();
loop {
match src.peek()? {
Some(Ev::Scalar {
value: s, style, ..
}) if scalar_is_nullish(s, style) => {
let _ = src.next()?; continue;
}
Some(_) => {
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut src,
cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => return Err(maybe_with_snippet(e, input, with_snippet, crop_radius)),
};
match ValidatorValidate::validate(&value) {
Ok(()) => {
values.push(value);
}
Err(errors) => {
let err = Error::ValidatorError {
errors,
locations: recorder.map,
};
validation_errors.push(maybe_with_snippet(
err,
input,
with_snippet,
crop_radius,
));
}
}
}
None => break,
}
}
src.finish()
.map_err(|e| maybe_with_snippet(e, input, with_snippet, crop_radius))?;
if validation_errors.is_empty() {
Ok(values)
} else {
Err(Error::ValidatorErrors {
errors: validation_errors,
})
}
}
#[cfg(feature = "validator")]
pub fn from_slice_validate<T: DeserializeOwned + ValidatorValidate>(
bytes: &[u8],
) -> Result<T, Error> {
from_slice_with_options_validate(bytes, Options::default())
}
#[cfg(feature = "validator")]
pub fn from_slice_with_options_validate<T: DeserializeOwned + ValidatorValidate>(
bytes: &[u8],
options: Options,
) -> Result<T, Error> {
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_str_with_options_validate(s, options)
}
#[cfg(feature = "validator")]
pub fn from_slice_multiple_with_options_validate<T>(
bytes: &[u8],
options: Options,
) -> Result<Vec<T>, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_multiple_with_options_validate(s, options)
}
#[cfg(feature = "validator")]
pub fn from_reader_validate<R: std::io::Read, T>(reader: R) -> Result<T, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
from_reader_with_options_validate(reader, Options::default())
}
#[cfg(feature = "validator")]
#[allow(deprecated)]
pub fn from_reader_with_options_validate<R: std::io::Read, T>(
reader: R,
options: Options,
) -> Result<T, Error>
where
T: DeserializeOwned + ValidatorValidate,
{
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_reader(
reader,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::AllContent,
);
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut src,
cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if src.synthesized_null_emitted() {
return Err(Error::eof().with_location(src.last_location()));
} else {
return Err(e);
}
}
};
if let Err(errors) = ValidatorValidate::validate(&value) {
return Err(Error::ValidatorError {
errors,
locations: recorder.map,
});
}
match src.peek() {
Ok(Some(_)) => {
return Err(
Error::multiple_documents(
"use read_validate or read_with_options_validate to obtain the iterator",
)
.with_location(src.last_location()),
);
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(e);
}
}
}
src.finish()?;
Ok(value)
}
#[cfg(feature = "validator")]
pub fn read_validate<'a, R, T>(reader: &'a mut R) -> impl Iterator<Item = Result<T, Error>> + 'a
where
R: Read + 'a,
T: DeserializeOwned + ValidatorValidate + 'a,
{
read_with_options_validate(reader, Default::default())
}
#[cfg(feature = "validator")]
#[allow(deprecated)]
pub fn read_with_options_validate<'a, R, T>(
reader: &'a mut R,
options: Options,
) -> impl Iterator<Item = Result<T, Error>> + 'a
where
R: Read + 'a,
T: DeserializeOwned + ValidatorValidate + 'a,
{
struct ReadValidateIter<'a, T> {
src: LiveEvents<'a>, cfg: crate::de::Cfg,
finished: bool,
_marker: std::marker::PhantomData<T>,
}
impl<'a, T> Iterator for ReadValidateIter<'a, T>
where
T: DeserializeOwned + ValidatorValidate + 'a,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
loop {
match self.src.peek() {
Ok(Some(Ev::Scalar { value, style, .. }))
if scalar_is_nullish(value, style) =>
{
let _ = self.src.next();
continue;
}
Ok(Some(_)) => {
let mut recorder = crate::path_map::PathRecorder::new();
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new_with_path_recorder(
&mut self.src,
self.cfg,
&mut recorder,
))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if !self.src.skip_to_next_document() {
self.finished = true;
}
return Some(Err(e));
}
};
match ValidatorValidate::validate(&value) {
Ok(()) => return Some(Ok(value)),
Err(errors) => {
return Some(Err(Error::ValidatorError {
errors,
locations: recorder.map,
}));
}
}
}
Ok(None) => {
self.finished = true;
if let Err(e) = self.src.finish() {
return Some(Err(e));
}
return None;
}
Err(e) => {
self.finished = true;
let _ = self.src.finish();
return Some(Err(e));
}
}
}
}
}
let cfg = crate::de::Cfg::from_options(&options);
let src = LiveEvents::from_reader(
reader,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::PerDocument,
);
ReadValidateIter::<T> {
src,
cfg,
finished: false,
_marker: std::marker::PhantomData,
}
}
pub(crate) fn maybe_with_snippet(
err: Error,
input: &str,
with_snippet: bool,
crop_radius: usize,
) -> Error {
if with_snippet && crop_radius > 0 && err.location().is_some() {
err.with_snippet(input, crop_radius)
} else {
err
}
}
pub fn from_multiple<T: DeserializeOwned>(input: &str) -> Result<Vec<T>, Error> {
from_multiple_with_options(input, Options::default())
}
#[allow(deprecated)]
pub fn from_multiple_with_options<T: DeserializeOwned>(
input: &str,
options: Options,
) -> Result<Vec<T>, Error> {
let input = if let Some(rest) = input.strip_prefix('\u{FEFF}') {
rest
} else {
input
};
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = crate::de::Cfg::from_options(&options);
let mut src = LiveEvents::from_str(
input,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
);
let mut values = Vec::new();
loop {
match src.peek()? {
Some(Ev::Scalar {
value: s, style, ..
}) if scalar_is_nullish(s, style) => {
let _ = src.next()?; continue;
}
Some(_) => {
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new(&mut src, cfg))
});
let value = match value_res {
Ok(v) => v,
Err(e) => return Err(maybe_with_snippet(e, input, with_snippet, crop_radius)),
};
values.push(value);
}
None => break,
}
}
src.finish()
.map_err(|e| maybe_with_snippet(e, input, with_snippet, crop_radius))?;
Ok(values)
}
pub fn from_slice<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, Error> {
from_slice_with_options(bytes, Options::default())
}
pub fn from_slice_with_options<'de, T>(
bytes: &'de [u8],
options: Options,
) -> Result<T, Error>
where
T: serde::Deserialize<'de>,
{
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_str_with_options(s, options)
}
pub fn from_slice_multiple<T: DeserializeOwned>(bytes: &[u8]) -> Result<Vec<T>, Error> {
from_slice_multiple_with_options(bytes, Options::default())
}
pub fn from_slice_multiple_with_options<T: DeserializeOwned>(
bytes: &[u8],
options: Options,
) -> Result<Vec<T>, Error> {
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
from_multiple_with_options(s, options)
}
pub fn to_string_multiple<T: serde::Serialize>(
values: &[T],
) -> std::result::Result<String, crate::ser::Error> {
let mut out = String::new();
let mut first = true;
for v in values {
if !first {
out.push_str("---\n");
}
first = false;
to_fmt_writer(&mut out, v)?;
}
Ok(out)
}
pub fn from_reader<'a, R: std::io::Read + 'a, T: DeserializeOwned>(reader: R) -> Result<T, Error> {
from_reader_with_options(reader, Options::default())
}
#[allow(deprecated)]
pub fn from_reader_with_options<'a, R: std::io::Read + 'a, T: DeserializeOwned>(
reader: R,
options: Options,
) -> Result<T, Error> {
let cfg = crate::de::Cfg::from_options(&options);
let crop_radius = options.crop_radius;
let shared_ring = ring_reader::SharedRingReader::new(reader);
let ring_handle = ring_reader::SharedRingReaderHandle::new(&shared_ring);
let mut src = LiveEvents::from_reader(
ring_handle,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::AllContent,
);
let attach_snippet = |e: Error| -> Error {
if crop_radius == 0 {
return e;
}
match shared_ring.get_recent() {
Ok(snapshot) => {
let text = String::from_utf8_lossy(&snapshot.bytes);
e.with_snippet_offset(&text, snapshot.start_line, crop_radius)
}
Err(_) => e, }
};
let value_res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new(&mut src, cfg))
});
let value = match value_res {
Ok(v) => v,
Err(e) => {
if src.synthesized_null_emitted() {
return Err(attach_snippet(
Error::eof().with_location(src.last_location()),
));
} else {
return Err(attach_snippet(e));
}
}
};
match src.peek() {
Ok(Some(_)) => {
return Err(attach_snippet(
Error::multiple_documents(
"use read or read_with_options to obtain the iterator",
)
.with_location(src.last_location()),
));
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(attach_snippet(e));
}
}
}
if let Err(e) = src.finish() {
return Err(attach_snippet(e));
}
Ok(value)
}
pub fn read<'a, R, T>(reader: &'a mut R) -> Box<dyn Iterator<Item = Result<T, Error>> + 'a>
where
R: Read + 'a,
T: DeserializeOwned + 'a,
{
Box::new(read_with_options(
reader,
crate::options! {
budget: crate::budget! {
max_reader_input_bytes: None,
},
},
))
}
#[allow(deprecated)]
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,
{
struct ReadIter<'a, T> {
src: LiveEvents<'a>, cfg: crate::de::Cfg,
finished: bool,
_marker: std::marker::PhantomData<T>,
}
impl<'a, T> Iterator for ReadIter<'a, T>
where
T: DeserializeOwned + 'a,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
loop {
match self.src.peek() {
Ok(Some(Ev::Scalar { value, style, .. }))
if scalar_is_nullish(value, style) =>
{
let _ = self.src.next();
continue;
}
Ok(Some(_)) => {
let res = crate::anchor_store::with_document_scope(|| {
T::deserialize(crate::de::YamlDeserializer::new(
&mut self.src,
self.cfg,
))
});
if res.is_err() {
if !self.src.skip_to_next_document() {
self.finished = true;
}
}
return Some(res);
}
Ok(None) => {
self.finished = true;
if let Err(e) = self.src.finish() {
return Some(Err(e));
}
return None;
}
Err(e) => {
self.finished = true;
let _ = self.src.finish();
return Some(Err(e));
}
}
}
}
}
let cfg = crate::de::Cfg::from_options(&options);
let src = LiveEvents::from_reader(
reader,
options.budget,
options.budget_report,
options.budget_report_cb,
options.alias_limits,
false,
EnforcingPolicy::PerDocument,
);
ReadIter::<T> {
src,
cfg,
finished: false,
_marker: std::marker::PhantomData,
}
}