1#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
68
69use std::borrow::Cow;
70use std::fmt;
71use std::sync::Arc;
72use std::sync::OnceLock;
73use std::sync::atomic::{AtomicUsize, Ordering};
74
75use deser_core::State;
76use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle};
77use deser_core::ser::{Describe, Emit, Serialize};
78use deser_core::{Atom, ContainerShape, Error, Source};
79
80pub use deser_core::Position;
82
83#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
87pub struct Span {
88 pub start: Position,
90 pub end: Position,
92}
93
94impl fmt::Debug for Span {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(f, "{:?}-{:?}", self.start, self.end)
97 }
98}
99
100impl fmt::Display for Span {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "{}-{}", self.start, self.end)
103 }
104}
105
106pub struct SourceMap {
111 source: Arc<str>,
112 line_starts: OnceLock<Vec<usize>>,
113 last_line: AtomicUsize,
116}
117
118impl fmt::Debug for SourceMap {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 f.debug_struct("SourceMap")
121 .field("len", &self.source.len())
122 .finish()
123 }
124}
125
126impl SourceMap {
127 pub fn new<S: Into<Arc<str>>>(source: S) -> SourceMap {
129 SourceMap {
130 source: source.into(),
131 line_starts: OnceLock::new(),
132 last_line: AtomicUsize::new(0),
133 }
134 }
135
136 pub fn source(&self) -> &str {
138 &self.source
139 }
140
141 fn line_starts(&self) -> &[usize] {
142 self.line_starts.get_or_init(|| {
143 let mut rv = vec![0];
144 rv.extend(self.source.match_indices('\n').map(|(idx, _)| idx + 1));
145 rv
146 })
147 }
148
149 fn line_index(&self, offset: usize) -> usize {
151 let line_starts = self.line_starts();
152 let contains = |idx: usize| {
153 line_starts[idx] <= offset
154 && offset < line_starts.get(idx + 1).copied().unwrap_or(usize::MAX)
155 };
156 let hint = self.last_line.load(Ordering::Relaxed);
157 let idx = if hint < line_starts.len() && contains(hint) {
158 hint
159 } else if hint + 1 < line_starts.len() && contains(hint + 1) {
160 hint + 1
161 } else {
162 line_starts.partition_point(|&start| start <= offset) - 1
163 };
164 self.last_line.store(idx, Ordering::Relaxed);
165 idx
166 }
167
168 pub fn position(&self, offset: usize) -> Position {
172 let offset = offset.min(self.source.len());
173 let idx = self.line_index(offset);
174 let line_start = self.line_starts()[idx];
175 let mut rv = Position {
176 offset: line_start,
177 line: idx + 1,
178 column: 1,
179 };
180 rv.advance(&self.source.as_bytes()[line_start..offset]);
181 rv
182 }
183
184 pub fn span(&self, start: usize, end: usize) -> Span {
186 let start = self.position(start);
187 let end = end.min(self.source.len()).max(start.offset);
188 let bytes = &self.source.as_bytes()[start.offset..end];
191 let end = if bytes.contains(&b'\n') {
192 self.position(end)
193 } else {
194 let mut rv = start;
195 rv.advance(bytes);
196 rv
197 };
198 Span { start, end }
199 }
200}
201
202#[derive(Debug, Default, Clone)]
210pub struct Locations {
211 source_map: Option<Arc<SourceMap>>,
212}
213
214impl Locations {
215 pub fn source_map(state: &mut State) -> Option<Arc<SourceMap>> {
219 Locations::cached_source_map(state).cloned()
220 }
221
222 pub fn current_span(state: &mut State) -> Option<Span> {
224 let range = state.input_range()?;
225 let source_map = Locations::cached_source_map(state)?;
226 Some(source_map.span(range.start, range.end))
227 }
228
229 fn cached_source_map(state: &mut State) -> Option<&Arc<SourceMap>> {
230 let source = &state.get::<Source>()?.0;
231 let is_cached = matches!(
232 state.get::<Locations>(),
233 Some(Locations { source_map: Some(source_map) })
234 if Arc::ptr_eq(&source_map.source, source)
235 );
236 if !is_cached {
237 let source_map = SourceMap::new(source.clone());
238 state.get_mut::<Locations>().source_map = Some(Arc::new(source_map));
239 }
240 state.get::<Locations>()?.source_map.as_ref()
241 }
242}
243
244#[derive(Clone, PartialEq)]
253pub struct Spanned<T> {
254 pub value: T,
256 pub span: Option<Span>,
258}
259
260impl<T: fmt::Debug> fmt::Debug for Spanned<T> {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 fmt::Debug::fmt(&self.value, f)?;
263 match self.span {
264 Some(span) => write!(f, " (@ {:?})", span),
265 None => Ok(()),
266 }
267 }
268}
269
270impl<T> Spanned<T> {
271 pub fn new(value: T, span: Option<Span>) -> Spanned<T> {
273 Spanned { value, span }
274 }
275
276 pub fn into_inner(self) -> T {
278 self.value
279 }
280}
281
282impl<'de, T: Deserialize<'de>> Deserialize<'de> for Spanned<T> {
283 fn deserialize_into<'out>(
284 out: &'out mut Option<Self>,
285 state: &mut State,
286 ) -> SinkHandle<'out, 'de> {
287 SinkHandle::arena(
288 SpannedSink {
289 out,
290 slot: None,
291 compound: None,
292 span: None,
293 },
294 state,
295 )
296 }
297
298 fn expecting() -> Cow<'static, str> {
299 T::expecting()
300 }
301
302 fn describe_type(d: &mut dyn Describe) {
303 T::describe_type(d)
304 }
305}
306
307struct SpannedSink<'a, 'de, T> {
308 out: &'a mut Option<Spanned<T>>,
309 slot: Option<T>,
312 compound: Option<OwnedSink<'de, T>>,
313 span: Option<Span>,
314}
315
316impl<'a, 'de, T: Deserialize<'de>> SpannedSink<'a, 'de, T> {
317 fn compound(&mut self, state: &mut State) -> &mut dyn Sink<'de> {
318 self.compound
319 .get_or_insert_with(|| OwnedSink::deserialize(state))
320 .get_mut()
321 }
322}
323
324impl<'a, 'de, T: Deserialize<'de>> Sink<'de> for SpannedSink<'a, 'de, T> {
325 fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
326 self.span = Locations::current_span(state);
327 let mut sink = T::deserialize_into(&mut self.slot, state);
328 sink.atom(atom, state)?;
329 sink.finish(state)
330 }
331
332 fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
333 self.span = Locations::current_span(state);
334 let mut sink = T::deserialize_into(&mut self.slot, state);
335 sink.borrowed_atom(atom, state)?;
336 sink.finish(state)
337 }
338
339 fn map(&mut self, state: &mut State) -> Result<(), Error> {
340 self.span = Locations::current_span(state);
341 self.compound(state).map(state)
342 }
343
344 fn seq(&mut self, state: &mut State) -> Result<(), Error> {
345 self.span = Locations::current_span(state);
346 self.compound(state).seq(state)
347 }
348
349 fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
350 self.compound(state).next_key(state)
351 }
352
353 fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
354 self.compound(state).next_value(state)
355 }
356
357 fn value_for_key(
358 &mut self,
359 key: &str,
360 state: &mut State,
361 ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
362 self.compound(state).value_for_key(key, state)
363 }
364
365 fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
366 match self.compound {
367 Some(ref mut compound) => compound.get_mut().recover(err, state),
368 None => Err(err),
369 }
370 }
371
372 fn finish(&mut self, state: &mut State) -> Result<(), Error> {
373 let value = match self.compound {
374 Some(ref mut compound) => {
375 compound.get_mut().finish(state)?;
376 if let (Some(start), Some(end)) = (self.span, Locations::current_span(state)) {
379 self.span = Some(Span {
380 start: start.start,
381 end: end.end,
382 });
383 }
384 compound.take()
385 }
386 None => self.slot.take(),
387 };
388 let span = self.span;
389 *self.out = value.map(|value| Spanned { value, span });
390 Ok(())
391 }
392
393 fn expecting(&self) -> Cow<'_, str> {
394 if let Some(ref compound) = self.compound {
395 return compound.get().expecting();
396 }
397 T::expecting()
398 }
399}
400
401impl<T: Serialize> Serialize for Spanned<T> {
402 fn serialize<'a>(this: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
403 T::serialize(&this.value, state)
404 }
405
406 fn finish(this: &Self, state: &mut State) -> Result<(), Error> {
407 T::finish(&this.value, state)
408 }
409
410 fn is_optional(this: &Self) -> bool {
411 T::is_optional(&this.value)
412 }
413
414 fn container_shape(this: &Self) -> ContainerShape {
415 T::container_shape(&this.value)
416 }
417
418 fn describe(this: &Self, d: &mut dyn Describe) {
419 T::describe(&this.value, d)
420 }
421}
422
423#[test]
424fn test_source_map() {
425 let source_map = SourceMap::new("ab\ncäd\n\nx");
426 let pos = |offset| format!("{:?}", source_map.position(offset));
427 assert_eq!(pos(0), "1:1");
428 assert_eq!(pos(2), "1:3");
429 assert_eq!(pos(3), "2:1");
430 assert_eq!(pos(6), "2:3");
432 assert_eq!(pos(7), "2:4");
433 assert_eq!(pos(8), "3:1");
434 assert_eq!(pos(9), "4:1");
435 assert_eq!(pos(100), "4:2");
436 assert_eq!(format!("{:?}", source_map.span(3, 7)), "2:1-2:4");
437}
438
439#[test]
440fn test_debug() {
441 let span = SourceMap::new("[1, 23]").span(4, 6);
442 assert_eq!(
443 format!("{:?}", Spanned::new(23, Some(span))),
444 "23 (@ 1:5-1:7)"
445 );
446 assert_eq!(format!("{:?}", Spanned::new("x", None)), "\"x\"");
447 assert_eq!(
448 format!("{:#?}", Spanned::new(vec![1], Some(span))),
449 "[\n 1,\n] (@ 1:5-1:7)"
450 );
451}
452
453#[test]
454fn test_auto_traits() {
455 fn assert_send_sync<T: Send + Sync>() {}
456 assert_send_sync::<SourceMap>();
457 assert_send_sync::<Locations>();
458 assert_send_sync::<Spanned<String>>();
459}