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}