syntree/
span.rs

1use core::fmt;
2use core::ops;
3
4use crate::index::Index;
5
6/// A span in the source code, akin to `start..end` so the end of the span is
7/// exclusive.
8#[derive(Clone, Copy, Eq, PartialOrd, Ord, Hash)]
9#[non_exhaustive]
10pub struct Span<I> {
11    /// The start of the span.
12    pub start: I,
13    /// The end of the span.
14    pub end: I,
15}
16
17impl<A, B> PartialEq<Span<A>> for Span<B>
18where
19    B: PartialEq<A>,
20{
21    fn eq(&self, other: &Span<A>) -> bool {
22        self.start == other.start && self.end == other.end
23    }
24}
25
26impl<I> Span<I> {
27    /// Construct a new span.
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// use syntree::Span;
33    ///
34    /// let span = Span::new(4u32, 8u32);
35    ///
36    /// assert_eq!(span.start, 4);
37    /// assert_eq!(span.end, 8);
38    /// ```
39    #[must_use]
40    pub const fn new(start: I, end: I) -> Self {
41        Self { start, end }
42    }
43
44    /// Construct a span corresponding to the given point.
45    ///
46    /// # Examples
47    ///
48    /// ```
49    /// use syntree::Span;
50    ///
51    /// assert_eq!(Span::point(4u32), Span::new(4u32, 4u32));
52    /// ```
53    #[must_use]
54    pub const fn point(at: I) -> Self
55    where
56        I: Copy,
57    {
58        Self { start: at, end: at }
59    }
60
61    /// Join the current span with another.
62    ///
63    /// # Examples
64    ///
65    /// ```
66    /// use syntree::Span;
67    ///
68    /// let a = Span::new(4u32, 8u32);
69    /// let b = Span::new(5u32, 9u32);
70    ///
71    /// let span = a.join(&b);
72    ///
73    /// assert_eq!(span.start, 4);
74    /// assert_eq!(span.end, 9);
75    /// assert_eq!(span, b.join(&a));
76    /// ```
77    #[must_use]
78    #[inline]
79    pub fn join(&self, other: &Self) -> Self
80    where
81        I: Copy + Ord,
82    {
83        Self {
84            start: self.start.min(other.start),
85            end: self.end.max(other.end),
86        }
87    }
88
89    /// Test if the span is empty.
90    ///
91    /// # Examples
92    ///
93    /// ```
94    /// use syntree::Span;
95    ///
96    /// assert!(Span::new(0u32, 0u32).is_empty());
97    /// assert!(!Span::new(0u32, 10u32).is_empty());
98    /// ```
99    #[must_use]
100    #[inline]
101    pub fn is_empty(&self) -> bool
102    where
103        I: Eq,
104    {
105        self.end == self.start
106    }
107
108    /// Test if span contains the given index.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use syntree::Span;
114    ///
115    /// assert!(!Span::new(2u32, 2u32).contains(&2));
116    /// assert!(Span::new(2u32, 3u32).contains(&2));
117    /// assert!(!Span::new(2u32, 3u32).contains(&3));
118    /// ```
119    #[must_use]
120    #[inline]
121    pub fn contains<U>(self, index: &U) -> bool
122    where
123        I: PartialOrd<U>,
124        U: PartialOrd<I> + ?Sized,
125    {
126        &self.start <= index && index < &self.end
127    }
128}
129
130impl<I> Span<I>
131where
132    I: Index,
133{
134    /// Coerce into a [`ops::Range`] which is useful for slicing.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use syntree::Span;
140    ///
141    /// let a = Span::new(4u32, 8u32);
142    ///
143    /// assert_eq!(a.range(), 4..8);
144    /// ```
145    #[must_use]
146    pub fn range(self) -> ops::Range<usize> {
147        self.start.as_usize()..self.end.as_usize()
148    }
149
150    /// The length of the span.
151    ///
152    /// # Examples
153    ///
154    /// ```
155    /// use syntree::Span;
156    ///
157    /// assert_eq!(Span::new(0u32, 0u32).len(), 0);
158    /// assert_eq!(Span::new(0u32, 10u32).len(), 10);
159    /// ```
160    #[must_use]
161    #[inline]
162    pub fn len(&self) -> I::Length {
163        self.start.len_to(self.end)
164    }
165}
166
167impl<I> fmt::Display for Span<I>
168where
169    I: fmt::Display,
170{
171    #[inline]
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        write!(f, "{}..{}", self.start, self.end)
174    }
175}
176
177impl<I> fmt::Debug for Span<I>
178where
179    I: fmt::Debug,
180{
181    #[inline]
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        (&self.start, &self.end).fmt(f)
184    }
185}
186
187impl<I> PartialEq<&Span<I>> for Span<I>
188where
189    I: PartialEq,
190{
191    #[inline]
192    fn eq(&self, other: &&Span<I>) -> bool {
193        *self == **other
194    }
195}
196
197impl<I> PartialEq<Span<I>> for &Span<I>
198where
199    I: PartialEq,
200{
201    #[inline]
202    fn eq(&self, other: &Span<I>) -> bool {
203        **self == *other
204    }
205}