1use std::{
4 cmp::{Eq, PartialEq},
5 ops::{Deref, DerefMut},
6};
7
8use proc_macro2::Span;
9use sealed::sealed;
10use syn::spanned::Spanned;
11
12#[sealed]
15pub trait IntoSpan {
16 #[must_use]
18 fn into_span(self) -> Span;
19}
20
21#[sealed]
22impl IntoSpan for Span {
23 #[inline]
24 fn into_span(self) -> Self {
25 self
26 }
27}
28
29#[sealed]
30impl<T: Spanned> IntoSpan for &T {
31 #[inline]
32 fn into_span(self) -> Span {
33 self.span()
34 }
35}
36
37#[sealed]
38impl<T> IntoSpan for &Spanning<T> {
39 #[inline]
40 fn into_span(self) -> Span {
41 self.span()
42 }
43}
44
45#[derive(Clone, Copy, Debug)]
47pub struct Spanning<T: ?Sized> {
48 span: Span,
50
51 item: T,
53}
54
55impl<T> Spanning<T> {
56 #[must_use]
59 pub fn new<S: IntoSpan>(item: T, span: S) -> Self {
60 Self { span: span.into_span(), item }
61 }
62
63 #[allow(clippy::missing_const_for_fn)]
66 #[must_use]
67 pub fn into_inner(self) -> T {
68 self.item
69 }
70}
71
72impl<T: ?Sized> Spanning<T> {
73 #[must_use]
75 pub const fn span(&self) -> Span {
76 self.span
77 }
78}
79
80impl<T: ?Sized> Deref for Spanning<T> {
81 type Target = T;
82
83 fn deref(&self) -> &Self::Target {
84 &self.item
85 }
86}
87
88impl<T: ?Sized> DerefMut for Spanning<T> {
89 fn deref_mut(&mut self) -> &mut Self::Target {
90 &mut self.item
91 }
92}
93
94impl<T, V> PartialEq<Spanning<V>> for Spanning<T>
95where
96 T: PartialEq<V> + ?Sized,
97 V: ?Sized,
98{
99 fn eq(&self, other: &Spanning<V>) -> bool {
100 self.item.eq(&other.item)
101 }
102}
103
104impl<T: PartialEq + ?Sized> Eq for Spanning<T> {}
105
106impl From<Spanning<&str>> for syn::LitStr {
107 fn from(s: Spanning<&str>) -> Self {
108 Self::new(s.item, s.span)
109 }
110}
111
112impl From<Spanning<String>> for syn::LitStr {
113 fn from(s: Spanning<String>) -> Self {
114 Self::new(&s.item, s.span)
115 }
116}