1use crate::budget::EnforcingPolicy;
2use crate::live_events::LiveEvents;
3
4use super::api::{ReaderSnippetContext, StrSnippetContext};
5use super::{Cfg, Error, Events, Options, YamlDeserializer};
6
7pub(crate) fn run_with_document_scope<'de, R, F, W, P>(
8 src: &mut LiveEvents<'de>,
9 f: F,
10 wrap_err: W,
11 synthesized_null_should_be_eof: P,
12) -> Result<R, Error>
13where
14 F: FnOnce(&mut LiveEvents<'de>) -> Result<R, Error>,
15 W: Fn(Error, &LiveEvents<'de>) -> Error,
16 P: Fn(&Error) -> bool,
17{
18 let value_res = crate::anchor_store::with_document_scope(|| {
19 crate::properties_redaction::with_interp_redaction_scope(|| f(src))
20 });
21 match value_res {
22 Ok(v) => {
23 src.finalize_document_budget()
24 .map_err(|e| wrap_err(e, src))?;
25 Ok(v)
26 }
27 Err(e) => {
28 if src.synthesized_null_emitted() && synthesized_null_should_be_eof(&e) {
29 Err(wrap_err(
33 Error::eof().with_location(src.last_location()),
34 src,
35 ))
36 } else {
37 Err(wrap_err(e, src))
38 }
39 }
40 }
41}
42
43pub(crate) fn deserialize_with_scope_and_null_policy<'de, R, F, W, P>(
44 src: &mut LiveEvents<'de>,
45 cfg: Cfg,
46 f: F,
47 wrap_err: W,
48 synthesized_null_should_be_eof: P,
49) -> Result<R, Error>
50where
51 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
52 W: Fn(Error, &LiveEvents<'de>) -> Error,
53 P: Fn(&Error) -> bool,
54{
55 run_with_document_scope(
56 src,
57 |src| super::with_root_redaction(YamlDeserializer::new(src, cfg), f),
58 wrap_err,
59 synthesized_null_should_be_eof,
60 )
61}
62
63pub(crate) fn deserialize_with_scope<'de, R, F, W>(
64 src: &mut LiveEvents<'de>,
65 cfg: Cfg,
66 f: F,
67 wrap_err: W,
68) -> Result<R, Error>
69where
70 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
71 W: Fn(Error, &LiveEvents<'de>) -> Error,
72{
73 deserialize_with_scope_and_null_policy(src, cfg, f, wrap_err, |_| true)
74}
75
76pub(crate) fn deserialize_document_unless_null<'de, R, F, W>(
79 src: &mut LiveEvents<'de>, cfg: Cfg, f: F, wrap_err: W, ) -> Result<Option<R>, Error>
84where
85 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
86 W: Fn(Error, &LiveEvents<'de>) -> Error,
87{
88 run_with_document_scope(
89 src,
90 |src| {
91 super::deserializer::with_root_redaction_unless_null(YamlDeserializer::new(src, cfg), f)
92 },
93 wrap_err,
94 |_| false,
95 )
96}
97
98pub(crate) fn enforce_single_document_and_finish<'de, W>(
99 src: &mut LiveEvents<'de>,
100 multiple_docs_hint: &'static str,
101 wrap_err: W,
102) -> Result<(), Error>
103where
104 W: Fn(Error, &LiveEvents<'de>) -> Error,
105{
106 match src.peek() {
110 Ok(Some(_)) => {
111 return Err(wrap_err(
112 Error::multiple_documents(multiple_docs_hint).with_location(src.last_location()),
113 src,
114 ));
115 }
116 Ok(None) => {}
117 Err(e) => return Err(wrap_err(e, src)),
118 }
119
120 src.finish().map_err(|e| wrap_err(e, src))
121}
122
123pub fn with_deserializer_from_str_with_options<'de, R, F>(
132 input: &'de str,
133 options: Options,
134 f: F,
135) -> Result<R, Error>
136where
137 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
138{
139 let with_snippet = options.with_snippet;
141 let crop_radius = options.crop_radius;
142
143 let cfg = Cfg::from_options(&options);
144 let mut src = LiveEvents::from_str(input, options);
146 let snippet_ctx = StrSnippetContext::new(input, with_snippet, crop_radius);
147
148 let wrap_err = |e, src: &LiveEvents<'de>| snippet_ctx.attach_snippet(e, src);
149
150 let value = deserialize_with_scope(&mut src, cfg, f, wrap_err)?;
151 enforce_single_document_and_finish(
152 &mut src,
153 "use from_str_multiple or from_str_multiple_with_options",
154 wrap_err,
155 )?;
156 Ok(value)
157}
158
159pub fn with_deserializer_from_str<'de, R, F>(input: &'de str, f: F) -> Result<R, Error>
162where
163 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
164{
165 with_deserializer_from_str_with_options(input, Options::default(), f)
166}
167
168pub fn with_deserializer_from_slice<'de, R, F>(bytes: &'de [u8], f: F) -> Result<R, Error>
172where
173 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
174{
175 with_deserializer_from_slice_with_options(bytes, Options::default(), f)
176}
177
178pub fn with_deserializer_from_slice_with_options<'de, R, F>(
181 bytes: &'de [u8],
182 options: Options,
183 f: F,
184) -> Result<R, Error>
185where
186 for<'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<R, Error>,
187{
188 let s = std::str::from_utf8(bytes).map_err(|_| Error::InvalidUtf8Input)?;
189 with_deserializer_from_str_with_options(s, options, f)
190}
191
192pub fn with_deserializer_from_reader<R, Out, F>(reader: R, f: F) -> Result<Out, Error>
199where
200 for<'de, 'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<Out, Error>,
201 R: std::io::Read,
202{
203 with_deserializer_from_reader_with_options(reader, Options::default(), f)
204}
205
206pub fn with_deserializer_from_reader_with_options<R, Out, F>(
209 reader: R,
210 options: Options,
211 f: F,
212) -> Result<Out, Error>
213where
214 for<'de, 'e> F: FnOnce(crate::Deserializer<'de, 'e>) -> Result<Out, Error>,
215 R: std::io::Read,
216{
217 let with_snippet = options.with_snippet;
218 let crop_radius = options.crop_radius;
219 let cfg = Cfg::from_options(&options);
220 let (snippet_ctx, ring_handle) = ReaderSnippetContext::new(reader, with_snippet, crop_radius);
221 let mut src = LiveEvents::from_reader(ring_handle, options, EnforcingPolicy::AllContent);
222
223 let wrap_err = |e, src: &LiveEvents<'_>| snippet_ctx.attach_snippet(e, src);
224
225 let value = deserialize_with_scope(&mut src, cfg, f, wrap_err)?;
226 enforce_single_document_and_finish(
227 &mut src,
228 "use read or read_with_options to obtain the iterator",
229 wrap_err,
230 )?;
231 Ok(value)
232}