blob: e53b1421d02853ed8c1ba1160fec851b9b37fea1 [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 {
David Tolnay05120ef2017-03-12 18:29:26 -0700142 global: self.global,
143 segments: self.segments,
144 })
David Tolnay55337722016-09-11 12:58:56 -0700145 }
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 Tolnay05120ef2017-03-12 18:29:26 -0700184 let lifetimes = generics.lifetimes.iter().map(|lifetime_def| lifetime_def.lifetime.clone());
David Tolnay55337722016-09-11 12:58:56 -0700185
David Tolnay05120ef2017-03-12 18:29:26 -0700186 let tys =
187 generics.ty_params.iter().map(|ty_param| TyBuilder::new().id(ty_param.ident.clone()));
David Tolnay55337722016-09-11 12:58:56 -0700188
David Tolnay05120ef2017-03-12 18:29:26 -0700189 self.with_lifetimes(lifetimes).with_tys(tys)
David Tolnay55337722016-09-11 12:58:56 -0700190 }
191
192 pub fn with_lifetimes<I, L>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700193 where I: IntoIterator<Item = L>,
194 L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700195 {
196 let iter = iter.into_iter().map(|lifetime| lifetime.into_lifetime());
197 self.lifetimes.extend(iter);
198 self
199 }
200
201 pub fn with_lifetime<L>(mut self, lifetime: L) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700202 where L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700203 {
204 self.lifetimes.push(lifetime.into_lifetime());
205 self
206 }
207
208 pub fn lifetime<N>(self, name: N) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700209 where N: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700210 {
David Tolnaydaaf7742016-10-03 11:11:43 -0700211 let lifetime = Lifetime { ident: name.to_ident() };
David Tolnay55337722016-09-11 12:58:56 -0700212 self.with_lifetime(lifetime)
213 }
214
215 pub fn with_tys<I>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700216 where I: IntoIterator<Item = Ty>
David Tolnay55337722016-09-11 12:58:56 -0700217 {
218 self.tys.extend(iter);
219 self
220 }
221
222 pub fn with_ty(mut self, ty: Ty) -> Self {
223 self.tys.push(ty);
224 self
225 }
226
227 pub fn ty(self) -> TyBuilder<Self> {
228 TyBuilder::with_callback(self)
229 }
230
231 pub fn with_binding(mut self, binding: TypeBinding) -> Self {
232 self.bindings.push(binding);
233 self
234 }
235
236 pub fn binding<T>(self, id: T) -> TyBuilder<TypeBindingBuilder<F>>
David Tolnaydaaf7742016-10-03 11:11:43 -0700237 where T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700238 {
239 TyBuilder::with_callback(TypeBindingBuilder {
David Tolnay05120ef2017-03-12 18:29:26 -0700240 id: id.to_ident(),
241 builder: self,
242 })
David Tolnay55337722016-09-11 12:58:56 -0700243 }
244
245 pub fn no_return(self) -> F::Result {
246 self.build_return(None)
247 }
248
249 pub fn return_(self) -> TyBuilder<PathSegmentReturnBuilder<F>> {
250 TyBuilder::with_callback(PathSegmentReturnBuilder(self))
251 }
252
253 pub fn build_return(self, output: Option<Ty>) -> F::Result {
254 let data = ParenthesizedParameterData {
255 inputs: self.tys,
256 output: output,
257 };
258
259 let parameters = PathParameters::Parenthesized(data);
260
261 self.callback.invoke(PathSegment {
David Tolnay05120ef2017-03-12 18:29:26 -0700262 ident: self.id,
263 parameters: parameters,
264 })
David Tolnay55337722016-09-11 12:58:56 -0700265 }
266
267 pub fn build(self) -> F::Result {
268 let data = AngleBracketedParameterData {
269 lifetimes: self.lifetimes,
270 types: self.tys,
271 bindings: self.bindings,
272 };
273
274 let parameters = PathParameters::AngleBracketed(data);
275
276 self.callback.invoke(PathSegment {
David Tolnay05120ef2017-03-12 18:29:26 -0700277 ident: self.id,
278 parameters: parameters,
279 })
David Tolnay55337722016-09-11 12:58:56 -0700280 }
281}
282
283impl<F> Invoke<Ty> for PathSegmentBuilder<F>
284 where F: Invoke<PathSegment>
285{
286 type Result = Self;
287
288 fn invoke(self, ty: Ty) -> Self {
289 self.with_ty(ty)
290 }
291}
292
David Tolnaydaaf7742016-10-03 11:11:43 -0700293// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700294
295pub struct TypeBindingBuilder<F> {
296 id: Ident,
297 builder: PathSegmentBuilder<F>,
298}
299
300impl<F> Invoke<Ty> for TypeBindingBuilder<F>
301 where F: Invoke<PathSegment>
302{
303 type Result = PathSegmentBuilder<F>;
304
305 fn invoke(self, ty: Ty) -> Self::Result {
306 let id = self.id;
307
308 self.builder.with_binding(TypeBinding {
David Tolnay05120ef2017-03-12 18:29:26 -0700309 ident: id,
310 ty: ty,
311 })
David Tolnay55337722016-09-11 12:58:56 -0700312 }
313}
314
David Tolnaydaaf7742016-10-03 11:11:43 -0700315// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700316
317pub struct PathSegmentReturnBuilder<F>(PathSegmentBuilder<F>);
318
319impl<F> Invoke<Ty> for PathSegmentReturnBuilder<F>
320 where F: Invoke<PathSegment>
321{
322 type Result = F::Result;
323
324 fn invoke(self, ty: Ty) -> Self::Result {
325 self.0.build_return(Some(ty))
326 }
327}