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