1use crate::alloc;
2use crate::ast::Span;
3use crate::parse::NonZeroId;
4
5pub use rune_macros::OptionSpanned;
7
8pub use rune_macros::Spanned;
10
11pub(crate) fn from_fn<F>(function: F) -> FromFn<F> {
13 FromFn { function }
14}
15
16#[derive(Clone, Copy)]
18pub(crate) struct FromFn<F> {
19 function: F,
20}
21
22impl<F> Spanned for FromFn<F>
23where
24 F: Fn() -> Span,
25{
26 #[inline]
27 fn span(&self) -> Span {
28 (self.function)()
29 }
30}
31
32pub trait Spanned {
34 fn span(&self) -> Span;
36}
37
38impl Spanned for syntree::Span<u32> {
39 fn span(&self) -> Span {
40 Span::new(self.start, self.end)
41 }
42}
43
44impl<A, B> Spanned for (A, B)
45where
46 A: Spanned,
47 B: OptionSpanned,
48{
49 fn span(&self) -> Span {
50 if let Some(end) = self.1.option_span() {
51 self.0.span().join(end)
52 } else {
53 self.0.span()
54 }
55 }
56}
57
58impl Spanned for Span {
59 fn span(&self) -> Span {
60 *self
61 }
62}
63
64impl<T> Spanned for alloc::Box<T>
65where
66 T: Spanned,
67{
68 #[inline]
69 fn span(&self) -> Span {
70 Spanned::span(&**self)
71 }
72}
73
74impl<T> Spanned for &T
75where
76 T: ?Sized + Spanned,
77{
78 fn span(&self) -> Span {
79 Spanned::span(*self)
80 }
81}
82
83impl<T> Spanned for &mut T
84where
85 T: ?Sized + Spanned,
86{
87 fn span(&self) -> Span {
88 Spanned::span(*self)
89 }
90}
91
92impl<S> Spanned for (S, NonZeroId)
93where
94 S: Spanned,
95{
96 fn span(&self) -> Span {
97 self.0.span()
98 }
99}
100
101pub trait OptionSpanned {
103 fn option_span(&self) -> Option<Span>;
105}
106
107impl<T> OptionSpanned for [T]
110where
111 T: Spanned,
112{
113 fn option_span(&self) -> Option<Span> {
114 let span = self.first()?.span();
115
116 if let Some(last) = self.last() {
117 Some(span.join(last.span()))
118 } else {
119 Some(span)
120 }
121 }
122}
123
124impl<T> OptionSpanned for Option<T>
125where
126 T: Spanned,
127{
128 #[inline]
129 fn option_span(&self) -> Option<Span> {
130 Some(self.as_ref()?.span())
131 }
132}
133
134impl<T> OptionSpanned for alloc::Box<T>
135where
136 T: OptionSpanned,
137{
138 #[inline]
139 fn option_span(&self) -> Option<Span> {
140 OptionSpanned::option_span(&**self)
141 }
142}