1use crate::{Either, Span};
2
3use super::*;
4
5#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
6macro_rules! either {
7 ($v:expr, |$var:pat_param|$out:expr) => {
8 match $v {
9 Either::A($var) => $out,
10 Either::B($var) => $out,
11 }
12 };
13 ($v:expr, $f:expr) => {
14 either!($v, |v| $f(v))
15 };
16}
17
18macro_rules! either_map {
19 ($v:expr, |$var:pat_param|$out:expr) => {
20 match $v {
21 Either::A($var) => Either::A($out),
22 Either::B($var) => Either::B($out),
23 }
24 };
25 ($v:expr, $f:expr) => {
26 either_map!($v, |v| $f(v))
27 };
28}
29
30impl<A: MaybeSpan, B: MaybeSpan> sealed::MaybeSpan for Either<A, B> {}
31impl<A: MaybeSpan, B: MaybeSpan> MaybeSpan for Either<A, B> {
32 #[cfg(feature = "proc-macro")]
33 fn into_span_or_call_site(self) -> proc_macro::Span {
34 either!(self, MaybeSpan::into_span_or_call_site)
35 }
36 #[cfg(feature = "proc-macro")]
37 fn make_punct(self, punct: proc_macro::Punct) -> proc_macro::Punct {
38 either!(self, |v| v.make_punct(punct))
39 }
40 #[cfg(feature = "proc-macro")]
41 fn make_group(self, g: proc_macro::Group) -> proc_macro::Group {
42 either!(self, |v| v.make_group(g))
43 }
44 #[cfg(feature = "proc-macro")]
45 fn make_literal(self, literal: proc_macro::Literal) -> proc_macro::Literal {
46 either!(self, |v| v.make_literal(literal))
47 }
48
49 #[cfg(feature = "proc-macro2")]
50 fn into_span2_or_call_site(self) -> proc_macro2::Span {
51 either!(self, MaybeSpan::into_span2_or_call_site)
52 }
53 #[cfg(feature = "proc-macro2")]
54 fn make_punct2(self, punct: proc_macro2::Punct) -> proc_macro2::Punct {
55 either!(self, |v| v.make_punct2(punct))
56 }
57 #[cfg(feature = "proc-macro2")]
58 fn make_group2(self, g: proc_macro2::Group) -> proc_macro2::Group {
59 either!(self, |v| v.make_group2(g))
60 }
61 #[cfg(feature = "proc-macro2")]
62 fn make_literal2(self, literal: proc_macro2::Literal) -> proc_macro2::Literal {
63 either!(self, |v| v.make_literal2(literal))
64 }
65
66 type Span = Either<A::Span, B::Span>;
67 fn try_into_span(self) -> Option<Self::Span> {
68 match self {
69 Either::A(this) => this.try_into_span().map(Either::A),
70 Either::B(this) => this.try_into_span().map(Either::B),
71 }
72 }
73
74 type WithDefaultSpan<S: Span> = Either<A::WithDefaultSpan<S>, B::WithDefaultSpan<S>>;
75 fn with_default_span<S: Span>(self, span: S) -> Self::WithDefaultSpan<S> {
76 either_map!(self, |v| v.with_default_span(span))
77 }
78
79 type WithReplacedSpan<S: Span> = Either<A::WithReplacedSpan<S>, B::WithReplacedSpan<S>>;
80 fn with_replaced_span<S: Span>(self, span: S) -> Self::WithReplacedSpan<S> {
81 either_map!(self, |v| v.with_replaced_span(span))
82 }
83}
84
85#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
86const _: () = {
87 use crate::replace_span_of::ReplaceSpanOf;
88
89 impl<A: ReplaceSpanOf<T>, B: ReplaceSpanOf<T>, T: IntoTokens + WithSpan> ReplaceSpanOf<T>
90 for Either<A, B>
91 {
92 type ReplaceSpanOf = Either<A::ReplaceSpanOf, B::ReplaceSpanOf>;
93
94 fn replace_span_of(self, t: T) -> Self::ReplaceSpanOf {
95 either_map!(self, |v| v.replace_span_of(t))
96 }
97 }
98};
99
100impl<A: Span, B: Span> sealed::Span for Either<A, B> {}
101impl<A: Span, B: Span> Span for Either<A, B> {}
102
103impl<A: IntoTokenTree, B: IntoTokenTree> sealed::IntoTokenTree for Either<A, B> {}
104impl<A: IntoTokenTree, B: IntoTokenTree> IntoTokenTree for Either<A, B> {
105 crate::impl_into_token_tree!(|self| either!(self, IntoST::into_st));
106}
107
108impl<A: ToTokenTree, B: ToTokenTree> sealed::ToTokenTree for Either<A, B> {}
109impl<A: ToTokenTree, B: ToTokenTree> ToTokenTree for Either<A, B> {
110 crate::impl_to_token_tree!(|self| either!(self, IntoST::into_st));
111}
112
113impl<A: IntoTokens, B: IntoTokens> sealed::IntoTokens for Either<A, B> {}
114impl<A: IntoTokens, B: IntoTokens> IntoTokens for Either<A, B> {
115 crate::impl_into_tokens!(
116 |self, ts| either!(self, |v| () = (v, ts).into_st()),
117 either!(self, IntoST::into_st),
118 );
119}
120
121impl<A: ToTokens, B: ToTokens> sealed::ToTokens for Either<A, B> {}
122impl<A: ToTokens, B: ToTokens> ToTokens for Either<A, B> {
123 crate::impl_to_tokens!(
124 |self, ts| either!(self, |v| () = (v, ts).into_st()),
125 either!(self, IntoST::into_st),
126 );
127}
128
129impl<A: WithSpan, B: WithSpan> sealed::WithSpan for Either<A, B> {}
130impl<A: WithSpan, B: WithSpan> WithSpan for Either<A, B> {
131 type WithDefaultSpan<S: Span> = Either<A::WithDefaultSpan<S>, B::WithDefaultSpan<S>>;
132
133 fn with_default_span<S: Span>(self, span: S) -> Self::WithDefaultSpan<S> {
134 either_map!(self, |v| v.with_default_span(span))
135 }
136
137 type WithReplacedSpan<S: Span> = Either<A::WithReplacedSpan<S>, B::WithReplacedSpan<S>>;
138
139 fn with_replaced_span<S: Span>(self, span: S) -> Self::WithReplacedSpan<S> {
140 either_map!(self, |v| v.with_replaced_span(span))
141 }
142}
143
144impl<A: RefWithSpan, B: RefWithSpan> sealed::RefWithSpan for Either<A, B> {}
145impl<A: RefWithSpan, B: RefWithSpan> RefWithSpan for Either<A, B> {
146 type RefWithDefaultSpan<'a, S: Span>
147 = Either<A::RefWithDefaultSpan<'a, S>, B::RefWithDefaultSpan<'a, S>>
148 where
149 Self: 'a;
150
151 fn ref_with_default_span<S: Span>(&self, span: S) -> Self::RefWithDefaultSpan<'_, S> {
152 either_map!(self, |v| v.ref_with_default_span(span))
153 }
154
155 type RefWithReplacedSpan<'a, S: Span>
156 = Either<A::RefWithReplacedSpan<'a, S>, B::RefWithReplacedSpan<'a, S>>
157 where
158 Self: 'a;
159
160 fn ref_with_replaced_span<S: Span>(&self, span: S) -> Self::RefWithReplacedSpan<'_, S> {
161 either_map!(self, |v| v.ref_with_replaced_span(span))
162 }
163}