1use proc_macro2::{Span, TokenStream};
18use quote::{format_ident, quote};
19use syn::{Result, Token};
20
21pub mod multilocation {
22 use super::*;
23
24 pub fn generate_conversion_functions(input: proc_macro::TokenStream) -> Result<TokenStream> {
25 if !input.is_empty() {
26 return Err(syn::Error::new(Span::call_site(), "No arguments expected"))
27 }
28
29 let from_tuples = generate_conversion_from_tuples(8);
31 let from_v3 = generate_conversion_from_v3();
32
33 Ok(quote! {
34 #from_tuples
35 #from_v3
36 })
37 }
38
39 fn generate_conversion_from_tuples(max_parents: u8) -> TokenStream {
40 let mut from_tuples = (0..8usize)
41 .map(|num_junctions| {
42 let junctions =
43 (0..=num_junctions).map(|_| format_ident!("Junction")).collect::<Vec<_>>();
44 let idents =
45 (0..=num_junctions).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>();
46 let variant = &format_ident!("X{}", num_junctions + 1);
47 let array_size = num_junctions + 1;
48
49 let mut from_tuple = quote! {
50 impl From<( #(#junctions,)* )> for MultiLocation {
51 fn from( ( #(#idents,)* ): ( #(#junctions,)* ) ) -> Self {
52 MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) }
53 }
54 }
55
56 impl From<(u8, #(#junctions),*)> for MultiLocation {
57 fn from( ( parents, #(#idents),* ): (u8, #(#junctions),* ) ) -> Self {
58 MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) }
59 }
60 }
61
62 impl From<(Ancestor, #(#junctions),*)> for MultiLocation {
63 fn from( ( Ancestor(parents), #(#idents),* ): (Ancestor, #(#junctions),* ) ) -> Self {
64 MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) }
65 }
66 }
67
68 impl From<[Junction; #array_size]> for MultiLocation {
69 fn from(j: [Junction; #array_size]) -> Self {
70 let [#(#idents),*] = j;
71 MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) }
72 }
73 }
74 };
75
76 let from_parent_tuples = (1..=max_parents).map(|cur_parents| {
77 let parents =
78 (0..cur_parents).map(|_| format_ident!("Parent")).collect::<Vec<_>>();
79 let underscores =
80 (0..cur_parents).map(|_| Token)).collect::<Vec<_>>();
81
82 quote! {
83 impl From<( #(#parents,)* #(#junctions),* )> for MultiLocation {
84 fn from( (#(#underscores,)* #(#idents),*): ( #(#parents,)* #(#junctions),* ) ) -> Self {
85 MultiLocation { parents: #cur_parents, interior: Junctions::#variant( #(#idents),* ) }
86 }
87 }
88 }
89 });
90
91 from_tuple.extend(from_parent_tuples);
92 from_tuple
93 })
94 .collect::<TokenStream>();
95
96 let from_parent_junctions_tuples = (1..=max_parents).map(|cur_parents| {
97 let parents = (0..cur_parents).map(|_| format_ident!("Parent")).collect::<Vec<_>>();
98 let underscores =
99 (0..cur_parents).map(|_| Token)).collect::<Vec<_>>();
100
101 quote! {
102 impl From<( #(#parents,)* Junctions )> for MultiLocation {
103 fn from( (#(#underscores,)* junctions): ( #(#parents,)* Junctions ) ) -> Self {
104 MultiLocation { parents: #cur_parents, interior: junctions }
105 }
106 }
107 }
108 });
109 from_tuples.extend(from_parent_junctions_tuples);
110
111 quote! {
112 impl From<Junctions> for MultiLocation {
113 fn from(junctions: Junctions) -> Self {
114 MultiLocation { parents: 0, interior: junctions }
115 }
116 }
117
118 impl From<(u8, Junctions)> for MultiLocation {
119 fn from((parents, interior): (u8, Junctions)) -> Self {
120 MultiLocation { parents, interior }
121 }
122 }
123
124 impl From<(Ancestor, Junctions)> for MultiLocation {
125 fn from((Ancestor(parents), interior): (Ancestor, Junctions)) -> Self {
126 MultiLocation { parents, interior }
127 }
128 }
129
130 impl From<()> for MultiLocation {
131 fn from(_: ()) -> Self {
132 MultiLocation { parents: 0, interior: Junctions::Here }
133 }
134 }
135
136 impl From<(u8,)> for MultiLocation {
137 fn from((parents,): (u8,)) -> Self {
138 MultiLocation { parents, interior: Junctions::Here }
139 }
140 }
141
142 impl From<Junction> for MultiLocation {
143 fn from(x: Junction) -> Self {
144 MultiLocation { parents: 0, interior: Junctions::X1(x) }
145 }
146 }
147
148 impl From<[Junction; 0]> for MultiLocation {
149 fn from(_: [Junction; 0]) -> Self {
150 MultiLocation { parents: 0, interior: Junctions::Here }
151 }
152 }
153
154 #from_tuples
155 }
156 }
157
158 fn generate_conversion_from_v3() -> TokenStream {
159 let match_variants = (0..8u8)
160 .map(|cur_num| {
161 let num_ancestors = cur_num + 1;
162 let variant = format_ident!("X{}", num_ancestors);
163 let idents = (0..=cur_num).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>();
164
165 quote! {
166 crate::v3::Junctions::#variant( #(#idents),* ) =>
167 #variant( #( core::convert::TryInto::try_into(#idents)? ),* ),
168 }
169 })
170 .collect::<TokenStream>();
171
172 quote! {
173 impl core::convert::TryFrom<crate::v3::Junctions> for Junctions {
174 type Error = ();
175 fn try_from(mut new: crate::v3::Junctions) -> core::result::Result<Self, ()> {
176 use Junctions::*;
177 Ok(match new {
178 crate::v3::Junctions::Here => Here,
179 #match_variants
180 })
181 }
182 }
183 }
184 }
185}
186
187pub mod junctions {
188 use super::*;
189
190 pub fn generate_conversion_functions(input: proc_macro::TokenStream) -> Result<TokenStream> {
191 if !input.is_empty() {
192 return Err(syn::Error::new(Span::call_site(), "No arguments expected"))
193 }
194
195 let from_slice_syntax = generate_conversion_from_slice_syntax();
196
197 Ok(quote! {
198 #from_slice_syntax
199 })
200 }
201
202 fn generate_conversion_from_slice_syntax() -> TokenStream {
203 quote! {
204 macro_rules! impl_junction {
205 ($count:expr, $variant:ident, ($($index:literal),+)) => {
206 impl From<[Junction; $count]> for Junctions {
209 fn from(junctions: [Junction; $count]) -> Self {
210 Self::$variant($(junctions[$index].clone()),*)
211 }
212 }
213 };
214 }
215
216 impl_junction!(1, X1, (0));
217 impl_junction!(2, X2, (0, 1));
218 impl_junction!(3, X3, (0, 1, 2));
219 impl_junction!(4, X4, (0, 1, 2, 3));
220 impl_junction!(5, X5, (0, 1, 2, 3, 4));
221 impl_junction!(6, X6, (0, 1, 2, 3, 4, 5));
222 impl_junction!(7, X7, (0, 1, 2, 3, 4, 5, 6));
223 impl_junction!(8, X8, (0, 1, 2, 3, 4, 5, 6, 7));
224 }
225 }
226}