blob: 14695e017ff6d8c5aa0f40f5de1d901028ed6283 [file] [log] [blame]
David Tolnay55337722016-09-11 12:58:56 -07001use {
2 AngleBracketedParameterData,
3 Generics,
4 Ident,
5 Lifetime,
6 ParenthesizedParameterData,
7 Path,
8 PathParameters,
9 PathSegment,
10 Ty,
11 TypeBinding,
12};
13use aster::ident::ToIdent;
14use aster::invoke::{Invoke, Identity};
15use aster::lifetime::IntoLifetime;
16use aster::ty::TyBuilder;
17
18//////////////////////////////////////////////////////////////////////////////
19
20pub trait IntoPath {
21 fn into_path(self) -> Path;
22}
23
24impl IntoPath for Path {
25 fn into_path(self) -> Path {
26 self
27 }
28}
29
30impl IntoPath for Ident {
31 fn into_path(self) -> Path {
32 PathBuilder::new().id(self).build()
33 }
34}
35
36impl<'a> IntoPath for &'a str {
37 fn into_path(self) -> Path {
38 PathBuilder::new().id(self).build()
39 }
40}
41
42impl IntoPath for String {
43 fn into_path(self) -> Path {
44 (&*self).into_path()
45 }
46}
47
48impl<'a, T> IntoPath for &'a [T] where T: ToIdent {
49 fn into_path(self) -> Path {
50 PathBuilder::new().ids(self).build()
51 }
52}
53
54//////////////////////////////////////////////////////////////////////////////
55
56pub struct PathBuilder<F=Identity> {
57 callback: F,
58 global: bool,
59}
60
61impl PathBuilder {
62 pub fn new() -> Self {
63 PathBuilder::with_callback(Identity)
64 }
65}
66
67impl<F> PathBuilder<F>
68 where F: Invoke<Path>,
69{
70 pub fn with_callback(callback: F) -> Self {
71 PathBuilder {
72 callback: callback,
73 global: false,
74 }
75 }
76
77 pub fn build(self, path: Path) -> F::Result {
78 self.callback.invoke(path)
79 }
80
81 pub fn global(mut self) -> Self {
82 self.global = true;
83 self
84 }
85
86 pub fn ids<I, T>(self, ids: I) -> PathSegmentsBuilder<F>
87 where I: IntoIterator<Item=T>,
88 T: ToIdent,
89 {
90 let mut ids = ids.into_iter();
91 let id = ids.next().expect("passed path with no id");
92
93 self.id(id).ids(ids)
94 }
95
96 pub fn id<I>(self, id: I) -> PathSegmentsBuilder<F>
97 where I: ToIdent,
98 {
99 self.segment(id).build()
100 }
101
102 pub fn segment<I>(self, id: I)
103 -> PathSegmentBuilder<PathSegmentsBuilder<F>>
104 where I: ToIdent,
105 {
106 PathSegmentBuilder::with_callback(id, PathSegmentsBuilder {
107 callback: self.callback,
108 global: self.global,
109 segments: Vec::new(),
110 })
111 }
112}
113
114//////////////////////////////////////////////////////////////////////////////
115
116pub struct PathSegmentsBuilder<F=Identity> {
117 callback: F,
118 global: bool,
119 segments: Vec<PathSegment>,
120}
121
122impl<F> PathSegmentsBuilder<F>
123 where F: Invoke<Path>,
124{
125 pub fn ids<I, T>(mut self, ids: I) -> PathSegmentsBuilder<F>
126 where I: IntoIterator<Item=T>,
127 T: ToIdent,
128 {
129 for id in ids {
130 self = self.id(id);
131 }
132
133 self
134 }
135
136 pub fn id<T>(self, id: T) -> PathSegmentsBuilder<F>
137 where T: ToIdent,
138 {
139 self.segment(id).build()
140 }
141
142 pub fn segment<T>(self, id: T) -> PathSegmentBuilder<Self>
143 where T: ToIdent,
144 {
145 PathSegmentBuilder::with_callback(id, self)
146 }
147
148 pub fn build(self) -> F::Result {
149 self.callback.invoke(Path {
150 global: self.global,
151 segments: self.segments,
152 })
153 }
154}
155
156impl<F> Invoke<PathSegment> for PathSegmentsBuilder<F> {
157 type Result = Self;
158
159 fn invoke(mut self, segment: PathSegment) -> Self {
160 self.segments.push(segment);
161 self
162 }
163}
164
165//////////////////////////////////////////////////////////////////////////////
166
167pub struct PathSegmentBuilder<F=Identity> {
168 callback: F,
169 id: Ident,
170 lifetimes: Vec<Lifetime>,
171 tys: Vec<Ty>,
172 bindings: Vec<TypeBinding>,
173}
174
175impl<F> PathSegmentBuilder<F>
176 where F: Invoke<PathSegment>,
177{
178 pub fn with_callback<I>(id: I, callback: F) -> Self
179 where I: ToIdent,
180 {
181 PathSegmentBuilder {
182 callback: callback,
183 id: id.to_ident(),
184 lifetimes: Vec::new(),
185 tys: Vec::new(),
186 bindings: Vec::new(),
187 }
188 }
189
190 pub fn with_generics(self, generics: Generics) -> Self {
191 // Strip off the bounds.
192 let lifetimes = generics.lifetimes.iter()
193 .map(|lifetime_def| lifetime_def.lifetime.clone());
194
195 let tys = generics.ty_params.iter()
196 .map(|ty_param| TyBuilder::new().id(ty_param.ident.clone()));
197
198 self.with_lifetimes(lifetimes)
199 .with_tys(tys)
200 }
201
202 pub fn with_lifetimes<I, L>(mut self, iter: I) -> Self
203 where I: IntoIterator<Item=L>,
204 L: IntoLifetime,
205 {
206 let iter = iter.into_iter().map(|lifetime| lifetime.into_lifetime());
207 self.lifetimes.extend(iter);
208 self
209 }
210
211 pub fn with_lifetime<L>(mut self, lifetime: L) -> Self
212 where L: IntoLifetime,
213 {
214 self.lifetimes.push(lifetime.into_lifetime());
215 self
216 }
217
218 pub fn lifetime<N>(self, name: N) -> Self
219 where N: ToIdent,
220 {
221 let lifetime = Lifetime {
222 ident: name.to_ident(),
223 };
224 self.with_lifetime(lifetime)
225 }
226
227 pub fn with_tys<I>(mut self, iter: I) -> Self
228 where I: IntoIterator<Item=Ty>,
229 {
230 self.tys.extend(iter);
231 self
232 }
233
234 pub fn with_ty(mut self, ty: Ty) -> Self {
235 self.tys.push(ty);
236 self
237 }
238
239 pub fn ty(self) -> TyBuilder<Self> {
240 TyBuilder::with_callback(self)
241 }
242
243 pub fn with_binding(mut self, binding: TypeBinding) -> Self {
244 self.bindings.push(binding);
245 self
246 }
247
248 pub fn binding<T>(self, id: T) -> TyBuilder<TypeBindingBuilder<F>>
249 where T: ToIdent,
250 {
251 TyBuilder::with_callback(TypeBindingBuilder {
252 id: id.to_ident(),
253 builder: self,
254 })
255 }
256
257 pub fn no_return(self) -> F::Result {
258 self.build_return(None)
259 }
260
261 pub fn return_(self) -> TyBuilder<PathSegmentReturnBuilder<F>> {
262 TyBuilder::with_callback(PathSegmentReturnBuilder(self))
263 }
264
265 pub fn build_return(self, output: Option<Ty>) -> F::Result {
266 let data = ParenthesizedParameterData {
267 inputs: self.tys,
268 output: output,
269 };
270
271 let parameters = PathParameters::Parenthesized(data);
272
273 self.callback.invoke(PathSegment {
274 ident: self.id,
275 parameters: parameters,
276 })
277 }
278
279 pub fn build(self) -> F::Result {
280 let data = AngleBracketedParameterData {
281 lifetimes: self.lifetimes,
282 types: self.tys,
283 bindings: self.bindings,
284 };
285
286 let parameters = PathParameters::AngleBracketed(data);
287
288 self.callback.invoke(PathSegment {
289 ident: self.id,
290 parameters: parameters,
291 })
292 }
293}
294
295impl<F> Invoke<Ty> for PathSegmentBuilder<F>
296 where F: Invoke<PathSegment>
297{
298 type Result = Self;
299
300 fn invoke(self, ty: Ty) -> Self {
301 self.with_ty(ty)
302 }
303}
304
305//////////////////////////////////////////////////////////////////////////////
306
307pub struct TypeBindingBuilder<F> {
308 id: Ident,
309 builder: PathSegmentBuilder<F>,
310}
311
312impl<F> Invoke<Ty> for TypeBindingBuilder<F>
313 where F: Invoke<PathSegment>
314{
315 type Result = PathSegmentBuilder<F>;
316
317 fn invoke(self, ty: Ty) -> Self::Result {
318 let id = self.id;
319
320 self.builder.with_binding(TypeBinding {
321 ident: id,
322 ty: ty,
323 })
324 }
325}
326
327//////////////////////////////////////////////////////////////////////////////
328
329pub struct PathSegmentReturnBuilder<F>(PathSegmentBuilder<F>);
330
331impl<F> Invoke<Ty> for PathSegmentReturnBuilder<F>
332 where F: Invoke<PathSegment>
333{
334 type Result = F::Result;
335
336 fn invoke(self, ty: Ty) -> Self::Result {
337 self.0.build_return(Some(ty))
338 }
339}