use crate::budget::EnforcingPolicy;
use crate::live_events::LiveEvents;
use super::{Cfg, Error, Events, Options, YamlDeserializer};
fn normalize_str_input(input: &str) -> &str {
input.strip_prefix('\u{FEFF}').unwrap_or(input)
}
fn deserialize_with_scope<'de, R, F, W>(
src: &mut LiveEvents<'de>,
cfg: Cfg,
f: F,
wrap_err: W,
) -> Result<R, Error>
where
for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
W: Fn(Error, &LiveEvents<'de>) -> Error,
{
let value_res = crate::anchor_store::with_document_scope(|| {
crate::properties_redaction::with_interp_redaction_scope(|| {
super::with_root_redaction(YamlDeserializer::new(src, cfg), f)
})
});
match value_res {
Ok(v) => Ok(v),
Err(e) => {
if src.synthesized_null_emitted() {
Err(wrap_err(
Error::eof().with_location(src.last_location()),
src,
))
} else {
Err(wrap_err(e, src))
}
}
}
}
fn enforce_single_document_and_finish<'de, W>(
src: &mut LiveEvents<'de>,
multiple_docs_hint: &'static str,
wrap_err: W,
) -> Result<(), Error>
where
W: Fn(Error, &LiveEvents<'de>) -> Error,
{
match src.peek() {
Ok(Some(_)) => {
return Err(wrap_err(
Error::multiple_documents(multiple_docs_hint).with_location(src.last_location()),
src,
));
}
Ok(None) => {}
Err(e) => {
if src.seen_doc_end() {
} else {
return Err(wrap_err(e, src));
}
}
}
src.finish().map_err(|e| wrap_err(e, src))
}
#[allow(deprecated)]
pub fn with_deserializer_from_str_with_options<'de, R, F>(
input: &'de str,
options: Options,
f: F,
) -> Result<R, Error>
where
for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
{
let input = normalize_str_input(input);
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = Cfg::from_options(&options);
let mut src = LiveEvents::from_str(input, options, false);
let wrap_err = |e, src: &LiveEvents<'de>| {
crate::maybe_with_snippet_from_events(e, input, src, with_snippet, crop_radius)
};
let value = deserialize_with_scope(&mut src, cfg, f, wrap_err)?;
enforce_single_document_and_finish(
&mut src,
"use from_multiple or from_multiple_with_options",
wrap_err,
)?;
Ok(value)
}
pub fn with_deserializer_from_str<'de, R, F>(input: &'de str, f: F) -> Result<R, Error>
where
for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
{
with_deserializer_from_str_with_options(input, Options::default(), f)
}
pub fn with_deserializer_from_slice<'de, R, F>(bytes: &'de [u8], f: F) -> Result<R, Error>
where
for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
{
with_deserializer_from_slice_with_options(bytes, Options::default(), f)
}
pub fn with_deserializer_from_slice_with_options<'de, R, F>(
bytes: &'de [u8],
options: Options,
f: F,
) -> Result<R, Error>
where
for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
{
let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
with_deserializer_from_str_with_options(s, options, f)
}
pub fn with_deserializer_from_reader<R, Out, F>(reader: R, f: F) -> Result<Out, Error>
where
for<'de, 'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<Out, Error>,
R: std::io::Read,
{
with_deserializer_from_reader_with_options(reader, Options::default(), f)
}
#[allow(deprecated)]
pub fn with_deserializer_from_reader_with_options<R, Out, F>(
reader: R,
options: Options,
f: F,
) -> Result<Out, Error>
where
for<'de, 'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<Out, Error>,
R: std::io::Read,
{
let with_snippet = options.with_snippet;
let crop_radius = options.crop_radius;
let cfg = Cfg::from_options(&options);
let shared_ring = crate::ring_reader::SharedRingReader::new(reader);
let ring_handle = crate::ring_reader::SharedRingReaderHandle::new(&shared_ring);
let mut src = LiveEvents::from_reader(ring_handle, options, false, EnforcingPolicy::AllContent);
let wrap_err = |e, src: &LiveEvents<'_>| {
if !with_snippet || crop_radius == 0 {
return e;
}
match shared_ring.get_recent() {
Ok(snapshot) => {
let text = String::from_utf8_lossy(&snapshot.bytes);
let root = crate::RootFragment {
text: text.as_ref(),
start_line: snapshot.start_line,
source_name: "input",
};
crate::maybe_with_snippet_from_events_and_root_fragment(
e,
Some(&root),
text.as_ref(),
src,
with_snippet,
crop_radius,
)
}
Err(_) => e,
}
};
let value = deserialize_with_scope(&mut src, cfg, f, wrap_err)?;
enforce_single_document_and_finish(
&mut src,
"use read or read_with_options to obtain the iterator",
wrap_err,
)?;
Ok(value)
}