rune/ast/
spanned.rs

1use crate::alloc;
2use crate::ast::Span;
3use crate::parse::NonZeroId;
4
5/// Helper derive to implement [`Spanned`].
6pub use rune_macros::Spanned;
7
8/// Helper derive to implement [`OptionSpanned`].
9pub use rune_macros::OptionSpanned;
10
11/// Defer building a span from a function.
12pub(crate) fn from_fn<F>(function: F) -> FromFn<F> {
13    FromFn { function }
14}
15
16/// Function used to build a [`Span`].
17#[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
32/// Types for which we can get a span.
33pub trait Spanned {
34    /// Get the span of the type.
35    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
64#[cfg(feature = "alloc")]
65impl<T> Spanned for ::rust_alloc::boxed::Box<T>
66where
67    T: Spanned,
68{
69    fn span(&self) -> Span {
70        Spanned::span(&**self)
71    }
72}
73
74impl<T> Spanned for alloc::Box<T>
75where
76    T: Spanned,
77{
78    fn span(&self) -> Span {
79        Spanned::span(&**self)
80    }
81}
82
83impl<T> Spanned for &T
84where
85    T: ?Sized + Spanned,
86{
87    fn span(&self) -> Span {
88        Spanned::span(*self)
89    }
90}
91
92impl<T> Spanned for &mut T
93where
94    T: ?Sized + Spanned,
95{
96    fn span(&self) -> Span {
97        Spanned::span(*self)
98    }
99}
100
101impl<S> Spanned for (S, NonZeroId)
102where
103    S: Spanned,
104{
105    fn span(&self) -> Span {
106        self.0.span()
107    }
108}
109
110/// Types for which we can optionally get a span.
111pub trait OptionSpanned {
112    /// Get the optional span of the type.
113    fn option_span(&self) -> Option<Span>;
114}
115
116/// Take the span of a vector of spanned.
117/// Provides the span between the first and the last element.
118impl<T> OptionSpanned for [T]
119where
120    T: Spanned,
121{
122    fn option_span(&self) -> Option<Span> {
123        let span = self.first()?.span();
124
125        if let Some(last) = self.last() {
126            Some(span.join(last.span()))
127        } else {
128            Some(span)
129        }
130    }
131}
132
133impl<T> OptionSpanned for Option<T>
134where
135    T: Spanned,
136{
137    fn option_span(&self) -> Option<Span> {
138        Some(self.as_ref()?.span())
139    }
140}
141
142#[cfg(feature = "alloc")]
143impl<T> OptionSpanned for ::rust_alloc::boxed::Box<T>
144where
145    T: OptionSpanned,
146{
147    fn option_span(&self) -> Option<Span> {
148        OptionSpanned::option_span(&**self)
149    }
150}
151
152impl<T> OptionSpanned for alloc::Box<T>
153where
154    T: OptionSpanned,
155{
156    fn option_span(&self) -> Option<Span> {
157        OptionSpanned::option_span(&**self)
158    }
159}