facet_deserialize/
span.rs

1use core::fmt;
2use core::marker::PhantomData;
3
4/// A Cooked variant of a Span (byte indexed)
5#[derive(Debug, PartialEq)]
6pub enum Cooked {}
7
8/// A Raw variant of a Span (format-specific index)
9#[derive(Debug, PartialEq)]
10pub enum Raw {}
11
12/// Position in the input (byte index)
13pub type Pos = usize;
14
15/// A span in the input, with a start position and length
16#[derive(Debug, PartialEq, Eq)]
17pub struct Span<C = Cooked> {
18    /// Starting position of the span in bytes
19    pub start: Pos,
20    /// Length of the span in bytes
21    pub len: usize,
22    /// Hold on to C
23    _p: PhantomData<C>,
24}
25
26/// Trait for types that can be annotated with a Span.
27pub trait Spannable<C = Cooked>: Sized {
28    /// Annotate this value with a span, wrapping it in `Spanned<Self, C>`
29    fn with_span(self, span: Span<C>) -> Spanned<Self, C>;
30}
31
32impl<T, C> Spannable<C> for T {
33    fn with_span(self, span: Span<C>) -> Spanned<Self, C> {
34        Spanned { node: self, span }
35    }
36}
37
38impl<C> Span<C> {
39    /// Creates a new span with the given start position and length
40    pub fn new(start: Pos, len: usize) -> Self {
41        Span {
42            start,
43            len,
44            _p: PhantomData,
45        }
46    }
47    /// Start position of the span
48    pub fn start(&self) -> Pos {
49        self.start
50    }
51    /// Length of the span
52    pub fn len(&self) -> usize {
53        self.len
54    }
55    /// Returns `true` if this span has zero length
56    pub fn is_empty(&self) -> bool {
57        self.len == 0
58    }
59    /// End position (start + length)
60    pub fn end(&self) -> Pos {
61        self.start + self.len
62    }
63}
64
65impl<C> Default for Span<C> {
66    fn default() -> Self {
67        Span {
68            start: 0,
69            len: 0,
70            _p: PhantomData,
71        }
72    }
73}
74
75/// A value of type `T` annotated with its `Span`
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct Spanned<T, C = Cooked> {
78    /// The actual data/value being wrapped
79    pub node: T,
80    /// The span information indicating the position and length in the source
81    pub span: Span<C>,
82}
83
84impl<T: fmt::Display, C> fmt::Display for Spanned<T, C> {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        write!(
87            f,
88            "{} at {}-{}",
89            self.node,
90            self.span.start(),
91            self.span.end()
92        )
93    }
94}
95
96// Copy + Clone not auto-derived for PhantomData
97// https://stackoverflow.com/a/31371094/2668831
98
99impl<C> Clone for Span<C> {
100    fn clone(&self) -> Self {
101        *self
102    }
103}
104
105impl<C> Copy for Span<C> {}