1use std::num::NonZeroUsize;
2
3use bstr::{ByteSlice, Utf8Error};
4
5use crate::rustc_stderr::Span;
6
7#[derive(Default, Debug, Clone, Copy)]
8pub struct MaybeSpanned<T> {
9 data: T,
10 span: Option<Span>,
11}
12
13impl<T> std::ops::Deref for MaybeSpanned<T> {
14 type Target = T;
15
16 fn deref(&self) -> &Self::Target {
17 &self.data
18 }
19}
20
21impl<T> MaybeSpanned<T> {
22 /// Values from the `Config` struct don't have lines.
23 pub fn new_config(data: T) -> Self {
24 Self { data, span: None }
25 }
26
27 pub fn span(&self) -> Option<Span> {
28 self.span
29 }
30
31 pub fn into_inner(self) -> T {
32 self.data
33 }
34}
35
36impl<T> From<Spanned<T>> for MaybeSpanned<T> {
37 fn from(value: Spanned<T>) -> Self {
38 Self {
39 data: value.data,
40 span: Some(value.span),
41 }
42 }
43}
44
45#[derive(Debug, Clone, Copy)]
46pub struct Spanned<T> {
47 data: T,
48 span: Span,
49}
50
51impl<T> std::ops::Deref for Spanned<T> {
52 type Target = T;
53
54 fn deref(&self) -> &Self::Target {
55 &self.data
56 }
57}
58
59impl<'a> Spanned<&'a str> {
60 pub fn strip_prefix(&self, prefix: &str) -> Option<Self> {
61 let data = self.data.strip_prefix(prefix)?;
62 let mut span = self.span;
63 span.column_start =
64 NonZeroUsize::new(span.column_start.get() + prefix.chars().count()).unwrap();
65 Some(Self { span, data })
66 }
67
68 pub fn strip_suffix(&self, suffix: &str) -> Option<Self> {
69 let data = self.data.strip_suffix(suffix)?;
70 let mut span = self.span;
71 span.column_end =
72 NonZeroUsize::new(span.column_end.get() - suffix.chars().count()).unwrap();
73 Some(Self { span, data })
74 }
75
76 pub fn trim_start(&self) -> Self {
77 let data = self.data.trim_start();
78 let mut span = self.span;
79 span.column_start = NonZeroUsize::new(
80 span.column_start.get() + self.data.chars().count() - data.chars().count(),
81 )
82 .unwrap();
83 Self { data, span }
84 }
85
86 pub fn trim_end(&self) -> Self {
87 let data = self.data.trim_end();
88 let mut span = self.span;
89 span.column_end = NonZeroUsize::new(
90 span.column_end.get() - (self.data.chars().count() - data.chars().count()),
91 )
92 .unwrap();
93 Self { data, span }
94 }
95
96 pub fn trim(&self) -> Self {
97 self.trim_start().trim_end()
98 }
99
100 pub fn split_at(&self, i: usize) -> (Self, Self) {
101 let (a, b) = self.data.split_at(i);
102 (
103 Self {
104 data: a,
105 span: Span {
106 column_end: NonZeroUsize::new(self.span.column_start.get() + a.chars().count())
107 .unwrap(),
108 ..self.span
109 },
110 },
111 Self {
112 data: b,
113 span: Span {
114 column_start: NonZeroUsize::new(
115 self.span.column_start.get() + a.chars().count(),
116 )
117 .unwrap(),
118 ..self.span
119 },
120 },
121 )
122 }
123
124 pub fn split_once(&self, splitter: &str) -> Option<(Self, Self)> {
125 let (a, b) = self.data.split_once(splitter)?;
126 Some((
127 Self {
128 data: a,
129 span: Span {
130 column_end: NonZeroUsize::new(self.span.column_start.get() + a.chars().count())
131 .unwrap(),
132 ..self.span
133 },
134 },
135 Self {
136 data: b,
137 span: Span {
138 column_start: NonZeroUsize::new(
139 self.span.column_start.get() + a.chars().count() + splitter.chars().count(),
140 )
141 .unwrap(),
142 ..self.span
143 },
144 },
145 ))
146 }
147}
148
149impl<'a> Spanned<&'a [u8]> {
150 pub fn strip_prefix(&self, prefix: &[u8]) -> Option<Self> {
151 let data = self.data.strip_prefix(prefix)?;
152 let mut span = self.span;
153 span.column_start = NonZeroUsize::new(span.column_start.get() + prefix.len()).unwrap();
154 Some(Self { span, data })
155 }
156
157 pub fn split_once_str(&self, splitter: &str) -> Option<(Self, Self)> {
158 let (a, b) = self.data.split_once_str(splitter)?;
159 Some((
160 Self {
161 data: a,
162 span: Span {
163 column_end: NonZeroUsize::new(self.span.column_start.get() + a.len()).unwrap(),
164 ..self.span
165 },
166 },
167 Self {
168 data: b,
169 span: Span {
170 column_start: NonZeroUsize::new(
171 self.span.column_start.get() + a.len() + splitter.len(),
172 )
173 .unwrap(),
174 ..self.span
175 },
176 },
177 ))
178 }
179
180 pub fn to_str(self) -> Result<Spanned<&'a str>, Utf8Error> {
181 Ok(Spanned {
182 data: self.data.to_str()?,
183 span: self.span,
184 })
185 }
186}
187
188impl<T> Spanned<T> {
189 pub fn new(data: T, span: Span) -> Self {
190 Self { data, span }
191 }
192
193 pub fn line(&self) -> NonZeroUsize {
194 self.span.line_start
195 }
196
197 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
198 Spanned {
199 data: f(self.data),
200 span: self.span,
201 }
202 }
203
204 pub fn into_inner(self) -> T {
205 self.data
206 }
207
208 pub fn span(&self) -> Span {
209 self.span
210 }
211}
212
213#[derive(Debug, Clone, Copy)]
214pub struct OptWithLine<T>(Option<Spanned<T>>);
215
216impl<T> std::ops::Deref for OptWithLine<T> {
217 type Target = Option<Spanned<T>>;
218
219 fn deref(&self) -> &Self::Target {
220 &self.0
221 }
222}
223
224impl<T> From<Option<Spanned<T>>> for OptWithLine<T> {
225 fn from(value: Option<Spanned<T>>) -> Self {
226 Self(value)
227 }
228}
229
230impl<T> From<Spanned<T>> for OptWithLine<T> {
231 fn from(value: Spanned<T>) -> Self {
232 Self(Some(value))
233 }
234}
235
236impl<T> Default for OptWithLine<T> {
237 fn default() -> Self {
238 Self(Default::default())
239 }
240}
241
242impl<T> OptWithLine<T> {
243 pub fn new(data: T, span: Span) -> Self {
244 Self(Some(Spanned::new(data, span)))
245 }
246
247 /// Tries to set the value if not already set. Returns newly passed
248 /// value in case there was already a value there.
249 #[must_use]
250 pub fn set(&mut self, data: T, span: Span) -> Option<Spanned<T>> {
251 let new: Spanned = Spanned::new(data, span);
252 if self.0.is_some() {
253 Some(new)
254 } else {
255 self.0 = Some(new);
256 None
257 }
258 }
259
260 #[must_use]
261 pub fn into_inner(self) -> Option<Spanned<T>> {
262 self.0
263 }
264}
265