1use serde::{ser::Serializer, Deserialize, Deserializer, Serialize};
4use std::{
5 fmt::{self, Debug, Display},
6 hash::{Hash, Hasher},
7 ops::Deref,
8};
9
10mod span;
11
12pub use span::Marker;
13pub use span::Span;
14
15pub struct Spanned<T> {
22 span: Span,
23 node: T,
24}
25
26impl<'de, T> Spanned<T>
27where
28 T: Deserialize<'de>,
29{
30 pub fn new(node: T) -> Self {
32 Spanned {
33 span: Default::default(),
34 node,
35 }
36 }
37}
38
39impl<T> Spanned<T> {
40 pub fn map<U, F>(self, f: F) -> Spanned<U>
42 where
43 F: FnOnce(T) -> U,
44 {
45 Spanned {
46 span: self.span,
47 node: f(self.node),
48 }
49 }
50
51 pub fn map_span<F>(self, f: F) -> Self
53 where
54 F: FnOnce(Span) -> Span,
55 {
56 Self {
57 span: f(self.span),
58 ..self
59 }
60 }
61
62 pub fn into_inner(self) -> T {
64 self.node
65 }
66
67 pub fn span(&self) -> &Span {
69 &self.span
70 }
71
72 pub fn has_valid_span(&self) -> bool {
74 self.span.is_valid()
75 }
76}
77
78impl<T> Deref for Spanned<T> {
79 type Target = T;
80
81 fn deref(&self) -> &Self::Target {
82 &self.node
83 }
84}
85
86impl<T> AsRef<T> for Spanned<T> {
87 fn as_ref(&self) -> &T {
88 &self.node
89 }
90}
91
92impl<T> AsMut<T> for Spanned<T> {
93 fn as_mut(&mut self) -> &mut T {
94 &mut self.node
95 }
96}
97
98impl<T> Clone for Spanned<T>
99where
100 T: Clone,
101{
102 fn clone(&self) -> Self {
103 Spanned {
104 span: self.span.clone(),
105 node: self.node.clone(),
106 }
107 }
108}
109
110impl<T> Debug for Spanned<T>
111where
112 T: Debug,
113{
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 write!(f, "{{{:?}}} ", self.span)?;
116 Debug::fmt(&self.node, f)
117 }
118}
119
120impl<T> Default for Spanned<T>
121where
122 T: Default,
123{
124 fn default() -> Self {
125 Spanned {
126 span: Default::default(),
127 node: T::default(),
128 }
129 }
130}
131
132impl<'de, T> From<T> for Spanned<T>
133where
134 T: Deserialize<'de>,
135{
136 fn from(node: T) -> Self {
137 Spanned::new(node)
138 }
139}
140
141impl<T> PartialEq for Spanned<T>
142where
143 T: PartialEq,
144{
145 fn eq(&self, other: &Self) -> bool {
146 self.node == other.node
147 }
148}
149
150impl<T> Eq for Spanned<T> where T: Eq {}
151
152impl<T> PartialOrd for Spanned<T>
153where
154 T: PartialOrd,
155{
156 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
157 self.node.partial_cmp(&other.node)
158 }
159}
160
161impl<T> Ord for Spanned<T>
162where
163 T: Ord,
164{
165 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
166 self.node.cmp(&other.node)
167 }
168}
169
170impl<T> Hash for Spanned<T>
171where
172 T: Hash,
173{
174 fn hash<H: Hasher>(&self, state: &mut H) {
175 self.node.hash(state);
176 }
177}
178
179impl<T> Display for Spanned<T>
180where
181 T: Display,
182{
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 <T as Display>::fmt(&self.node, f)
185 }
186}
187
188impl<T> Serialize for Spanned<T>
189where
190 T: Serialize,
191{
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: Serializer,
195 {
196 set_span(self.span.clone());
197 T::serialize(&self.node, serializer)
198 }
199}
200
201impl<'de, T> Deserialize<'de> for Spanned<T>
202where
203 T: Deserialize<'de>,
204{
205 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
206 where
207 D: Deserializer<'de>,
208 {
209 let start_marker = get_marker();
210 let node = T::deserialize(deserializer)?;
211 let end_marker = get_marker();
212 let span: Span = (start_marker..end_marker).into();
213
214 #[cfg(feature = "filename")]
215 let span = span.maybe_capture_filename();
216
217 Ok(Spanned { span, node })
218 }
219}
220
221#[cfg(feature = "schemars")]
222impl<T> schemars::JsonSchema for Spanned<T>
223where
224 T: schemars::JsonSchema,
225{
226 fn schema_name() -> String {
227 T::schema_name()
228 }
229
230 fn json_schema(generator: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
231 T::json_schema(generator)
232 }
233
234 fn is_referenceable() -> bool {
235 T::is_referenceable()
236 }
237
238 fn schema_id() -> std::borrow::Cow<'static, str> {
239 T::schema_id()
240 }
241
242 #[doc(hidden)]
243 fn _schemars_private_non_optional_json_schema(
244 generator: &mut schemars::gen::SchemaGenerator,
245 ) -> schemars::schema::Schema {
246 T::_schemars_private_non_optional_json_schema(generator)
247 }
248
249 #[doc(hidden)]
250 fn _schemars_private_is_option() -> bool {
251 T::_schemars_private_is_option()
252 }
253}
254
255#[cfg(feature = "filename")]
256pub struct WithFilenameScope {
258 original: Option<std::sync::Arc<std::path::PathBuf>>,
259}
260
261#[cfg(feature = "filename")]
262impl Drop for WithFilenameScope {
263 fn drop(&mut self) {
264 FILENAME.with(|f| *f.borrow_mut() = std::mem::take(&mut self.original));
265 }
266}
267
268#[cfg(feature = "filename")]
269pub fn with_filename(filename: Option<std::path::PathBuf>) -> WithFilenameScope {
273 let original = FILENAME.with(|f| f.borrow_mut().take());
274 FILENAME.with(|f| *f.borrow_mut() = filename.map(std::sync::Arc::new));
275 WithFilenameScope { original }
276}
277
278pub fn set_marker(marker: impl Into<Marker>) {
283 MARKER.with(|m| *m.borrow_mut() = Some(marker.into()));
284}
285
286pub fn reset_marker() {
288 MARKER.with(|m| *m.borrow_mut() = None);
289}
290
291pub(crate) fn get_marker() -> Option<Marker> {
293 MARKER.with(|m| *m.borrow())
294}
295
296pub(crate) fn set_span(span: Span) {
297 SPAN.with(|s| *s.borrow_mut() = Some(span));
298}
299
300pub(crate) fn take_span() -> Option<Span> {
301 SPAN.with(|s| s.borrow_mut().take())
302}
303
304#[cfg(feature = "filename")]
305pub(crate) fn set_filename(filename: std::sync::Arc<std::path::PathBuf>) {
307 FILENAME.with(|f| *f.borrow_mut() = Some(filename));
308}
309
310#[cfg(feature = "filename")]
311pub(crate) fn get_filename() -> Option<std::sync::Arc<std::path::PathBuf>> {
313 FILENAME.with(|f| f.borrow().clone())
314}
315
316thread_local! {
318 static MARKER: std::cell::RefCell<Option<Marker>> = const {
319 std::cell::RefCell::new(None)
320 };
321
322 #[cfg(feature = "filename")]
323 static FILENAME: std::cell::RefCell<Option<std::sync::Arc<std::path::PathBuf>>> = const {
324 std::cell::RefCell::new(None)
325 };
326}
327
328thread_local! {
330 static SPAN: std::cell::RefCell<Option<Span>> = const {
331 std::cell::RefCell::new(None)
332 };
333}