blob: a0fb314384ec4f08293e09ab13643fba5d23d014 [file] [log] [blame]
David Tolnaydaaf7742016-10-03 11:11:43 -07001use {AngleBracketedParameterData, Generics, Ident, Lifetime, ParenthesizedParameterData, Path,
2 PathParameters, PathSegment, Ty, TypeBinding};
David Tolnay55337722016-09-11 12:58:56 -07003use aster::ident::ToIdent;
4use aster::invoke::{Invoke, Identity};
5use aster::lifetime::IntoLifetime;
6use aster::ty::TyBuilder;
7
David Tolnaydaaf7742016-10-03 11:11:43 -07008// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -07009
10pub trait IntoPath {
11 fn into_path(self) -> Path;
12}
13
14impl IntoPath for Path {
15 fn into_path(self) -> Path {
16 self
17 }
18}
19
20impl IntoPath for Ident {
21 fn into_path(self) -> Path {
22 PathBuilder::new().id(self).build()
23 }
24}
25
26impl<'a> IntoPath for &'a str {
27 fn into_path(self) -> Path {
28 PathBuilder::new().id(self).build()
29 }
30}
31
32impl IntoPath for String {
33 fn into_path(self) -> Path {
34 (&*self).into_path()
35 }
36}
37
David Tolnaydaaf7742016-10-03 11:11:43 -070038impl<'a, T> IntoPath for &'a [T]
39 where T: ToIdent
40{
David Tolnay55337722016-09-11 12:58:56 -070041 fn into_path(self) -> Path {
42 PathBuilder::new().ids(self).build()
43 }
44}
45
David Tolnaydaaf7742016-10-03 11:11:43 -070046// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -070047
David Tolnaydaaf7742016-10-03 11:11:43 -070048pub struct PathBuilder<F = Identity> {
David Tolnay55337722016-09-11 12:58:56 -070049 callback: F,
50 global: bool,
51}
52
53impl PathBuilder {
54 pub fn new() -> Self {
55 PathBuilder::with_callback(Identity)
56 }
57}
58
59impl<F> PathBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -070060 where F: Invoke<Path>
David Tolnay55337722016-09-11 12:58:56 -070061{
62 pub fn with_callback(callback: F) -> Self {
63 PathBuilder {
64 callback: callback,
65 global: false,
66 }
67 }
68
69 pub fn build(self, path: Path) -> F::Result {
70 self.callback.invoke(path)
71 }
72
73 pub fn global(mut self) -> Self {
74 self.global = true;
75 self
76 }
77
78 pub fn ids<I, T>(self, ids: I) -> PathSegmentsBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -070079 where I: IntoIterator<Item = T>,
80 T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -070081 {
82 let mut ids = ids.into_iter();
83 let id = ids.next().expect("passed path with no id");
84
85 self.id(id).ids(ids)
86 }
87
88 pub fn id<I>(self, id: I) -> PathSegmentsBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -070089 where I: ToIdent
David Tolnay55337722016-09-11 12:58:56 -070090 {
91 self.segment(id).build()
92 }
93
David Tolnaydaaf7742016-10-03 11:11:43 -070094 pub fn segment<I>(self, id: I) -> PathSegmentBuilder<PathSegmentsBuilder<F>>
95 where I: ToIdent
David Tolnay55337722016-09-11 12:58:56 -070096 {
David Tolnaydaaf7742016-10-03 11:11:43 -070097 PathSegmentBuilder::with_callback(id,
98 PathSegmentsBuilder {
99 callback: self.callback,
100 global: self.global,
101 segments: Vec::new(),
102 })
David Tolnay55337722016-09-11 12:58:56 -0700103 }
104}
105
David Tolnaydaaf7742016-10-03 11:11:43 -0700106// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700107
David Tolnaydaaf7742016-10-03 11:11:43 -0700108pub struct PathSegmentsBuilder<F = Identity> {
David Tolnay55337722016-09-11 12:58:56 -0700109 callback: F,
110 global: bool,
111 segments: Vec<PathSegment>,
112}
113
114impl<F> PathSegmentsBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -0700115 where F: Invoke<Path>
David Tolnay55337722016-09-11 12:58:56 -0700116{
117 pub fn ids<I, T>(mut self, ids: I) -> PathSegmentsBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -0700118 where I: IntoIterator<Item = T>,
119 T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700120 {
121 for id in ids {
122 self = self.id(id);
123 }
124
125 self
126 }
127
128 pub fn id<T>(self, id: T) -> PathSegmentsBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -0700129 where T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700130 {
131 self.segment(id).build()
132 }
133
134 pub fn segment<T>(self, id: T) -> PathSegmentBuilder<Self>
David Tolnaydaaf7742016-10-03 11:11:43 -0700135 where T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700136 {
137 PathSegmentBuilder::with_callback(id, self)
138 }
139
140 pub fn build(self) -> F::Result {
141 self.callback.invoke(Path {
142 global: self.global,
143 segments: self.segments,
144 })
145 }
146}
147
148impl<F> Invoke<PathSegment> for PathSegmentsBuilder<F> {
149 type Result = Self;
150
151 fn invoke(mut self, segment: PathSegment) -> Self {
152 self.segments.push(segment);
153 self
154 }
155}
156
David Tolnaydaaf7742016-10-03 11:11:43 -0700157// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700158
David Tolnaydaaf7742016-10-03 11:11:43 -0700159pub struct PathSegmentBuilder<F = Identity> {
David Tolnay55337722016-09-11 12:58:56 -0700160 callback: F,
161 id: Ident,
162 lifetimes: Vec<Lifetime>,
163 tys: Vec<Ty>,
164 bindings: Vec<TypeBinding>,
165}
166
167impl<F> PathSegmentBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -0700168 where F: Invoke<PathSegment>
David Tolnay55337722016-09-11 12:58:56 -0700169{
170 pub fn with_callback<I>(id: I, callback: F) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700171 where I: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700172 {
173 PathSegmentBuilder {
174 callback: callback,
175 id: id.to_ident(),
176 lifetimes: Vec::new(),
177 tys: Vec::new(),
178 bindings: Vec::new(),
179 }
180 }
181
182 pub fn with_generics(self, generics: Generics) -> Self {
183 // Strip off the bounds.
David Tolnaydaaf7742016-10-03 11:11:43 -0700184 let lifetimes = generics.lifetimes
185 .iter()
David Tolnay55337722016-09-11 12:58:56 -0700186 .map(|lifetime_def| lifetime_def.lifetime.clone());
187
David Tolnaydaaf7742016-10-03 11:11:43 -0700188 let tys = generics.ty_params
189 .iter()
David Tolnay55337722016-09-11 12:58:56 -0700190 .map(|ty_param| TyBuilder::new().id(ty_param.ident.clone()));
191
192 self.with_lifetimes(lifetimes)
193 .with_tys(tys)
194 }
195
196 pub fn with_lifetimes<I, L>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700197 where I: IntoIterator<Item = L>,
198 L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700199 {
200 let iter = iter.into_iter().map(|lifetime| lifetime.into_lifetime());
201 self.lifetimes.extend(iter);
202 self
203 }
204
205 pub fn with_lifetime<L>(mut self, lifetime: L) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700206 where L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700207 {
208 self.lifetimes.push(lifetime.into_lifetime());
209 self
210 }
211
212 pub fn lifetime<N>(self, name: N) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700213 where N: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700214 {
David Tolnaydaaf7742016-10-03 11:11:43 -0700215 let lifetime = Lifetime { ident: name.to_ident() };
David Tolnay55337722016-09-11 12:58:56 -0700216 self.with_lifetime(lifetime)
217 }
218
219 pub fn with_tys<I>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700220 where I: IntoIterator<Item = Ty>
David Tolnay55337722016-09-11 12:58:56 -0700221 {
222 self.tys.extend(iter);
223 self
224 }
225
226 pub fn with_ty(mut self, ty: Ty) -> Self {
227 self.tys.push(ty);
228 self
229 }
230
231 pub fn ty(self) -> TyBuilder<Self> {
232 TyBuilder::with_callback(self)
233 }
234
235 pub fn with_binding(mut self, binding: TypeBinding) -> Self {
236 self.bindings.push(binding);
237 self
238 }
239
240 pub fn binding<T>(self, id: T) -> TyBuilder<TypeBindingBuilder<F>>
David Tolnaydaaf7742016-10-03 11:11:43 -0700241 where T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700242 {
243 TyBuilder::with_callback(TypeBindingBuilder {
244 id: id.to_ident(),
245 builder: self,
246 })
247 }
248
249 pub fn no_return(self) -> F::Result {
250 self.build_return(None)
251 }
252
253 pub fn return_(self) -> TyBuilder<PathSegmentReturnBuilder<F>> {
254 TyBuilder::with_callback(PathSegmentReturnBuilder(self))
255 }
256
257 pub fn build_return(self, output: Option<Ty>) -> F::Result {
258 let data = ParenthesizedParameterData {
259 inputs: self.tys,
260 output: output,
261 };
262
263 let parameters = PathParameters::Parenthesized(data);
264
265 self.callback.invoke(PathSegment {
266 ident: self.id,
267 parameters: parameters,
268 })
269 }
270
271 pub fn build(self) -> F::Result {
272 let data = AngleBracketedParameterData {
273 lifetimes: self.lifetimes,
274 types: self.tys,
275 bindings: self.bindings,
276 };
277
278 let parameters = PathParameters::AngleBracketed(data);
279
280 self.callback.invoke(PathSegment {
281 ident: self.id,
282 parameters: parameters,
283 })
284 }
285}
286
287impl<F> Invoke<Ty> for PathSegmentBuilder<F>
288 where F: Invoke<PathSegment>
289{
290 type Result = Self;
291
292 fn invoke(self, ty: Ty) -> Self {
293 self.with_ty(ty)
294 }
295}
296
David Tolnaydaaf7742016-10-03 11:11:43 -0700297// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700298
299pub struct TypeBindingBuilder<F> {
300 id: Ident,
301 builder: PathSegmentBuilder<F>,
302}
303
304impl<F> Invoke<Ty> for TypeBindingBuilder<F>
305 where F: Invoke<PathSegment>
306{
307 type Result = PathSegmentBuilder<F>;
308
309 fn invoke(self, ty: Ty) -> Self::Result {
310 let id = self.id;
311
312 self.builder.with_binding(TypeBinding {
313 ident: id,
314 ty: ty,
315 })
316 }
317}
318
David Tolnaydaaf7742016-10-03 11:11:43 -0700319// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700320
321pub struct PathSegmentReturnBuilder<F>(PathSegmentBuilder<F>);
322
323impl<F> Invoke<Ty> for PathSegmentReturnBuilder<F>
324 where F: Invoke<PathSegment>
325{
326 type Result = F::Result;
327
328 fn invoke(self, ty: Ty) -> Self::Result {
329 self.0.build_return(Some(ty))
330 }
331}