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