blob: 23d644ebd5ed8c82ea1519f80620235f03cf8246 [file] [log] [blame]
David Tolnaydaaf7742016-10-03 11:11:43 -07001use {AngleBracketedParameterData, Generics, Ident, Lifetime, ParenthesizedParameterData, Path,
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002 PathParameters, PathSegment, Ty, TypeBinding, FunctionRetTy};
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 {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700142 global: self.global,
143 segments: self.segments.into(),
144 leading_colon: None,
145 })
David Tolnay55337722016-09-11 12:58:56 -0700146 }
147}
148
149impl<F> Invoke<PathSegment> for PathSegmentsBuilder<F> {
150 type Result = Self;
151
152 fn invoke(mut self, segment: PathSegment) -> Self {
153 self.segments.push(segment);
154 self
155 }
156}
157
David Tolnaydaaf7742016-10-03 11:11:43 -0700158// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700159
David Tolnaydaaf7742016-10-03 11:11:43 -0700160pub struct PathSegmentBuilder<F = Identity> {
David Tolnay55337722016-09-11 12:58:56 -0700161 callback: F,
162 id: Ident,
163 lifetimes: Vec<Lifetime>,
164 tys: Vec<Ty>,
165 bindings: Vec<TypeBinding>,
166}
167
168impl<F> PathSegmentBuilder<F>
David Tolnaydaaf7742016-10-03 11:11:43 -0700169 where F: Invoke<PathSegment>
David Tolnay55337722016-09-11 12:58:56 -0700170{
171 pub fn with_callback<I>(id: I, callback: F) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700172 where I: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700173 {
174 PathSegmentBuilder {
175 callback: callback,
176 id: id.to_ident(),
177 lifetimes: Vec::new(),
178 tys: Vec::new(),
179 bindings: Vec::new(),
180 }
181 }
182
183 pub fn with_generics(self, generics: Generics) -> Self {
184 // Strip off the bounds.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700185 let lifetimes = generics.lifetimes.iter().map(|lifetime_def| lifetime_def.item().lifetime.clone());
David Tolnay55337722016-09-11 12:58:56 -0700186
David Tolnay05120ef2017-03-12 18:29:26 -0700187 let tys =
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700188 generics.ty_params.iter().map(|ty_param| TyBuilder::new().id(ty_param.item().ident.clone()));
David Tolnay55337722016-09-11 12:58:56 -0700189
David Tolnay05120ef2017-03-12 18:29:26 -0700190 self.with_lifetimes(lifetimes).with_tys(tys)
David Tolnay55337722016-09-11 12:58:56 -0700191 }
192
193 pub fn with_lifetimes<I, L>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700194 where I: IntoIterator<Item = L>,
195 L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700196 {
197 let iter = iter.into_iter().map(|lifetime| lifetime.into_lifetime());
198 self.lifetimes.extend(iter);
199 self
200 }
201
202 pub fn with_lifetime<L>(mut self, lifetime: L) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700203 where L: IntoLifetime
David Tolnay55337722016-09-11 12:58:56 -0700204 {
205 self.lifetimes.push(lifetime.into_lifetime());
206 self
207 }
208
209 pub fn lifetime<N>(self, name: N) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700210 where N: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700211 {
David Tolnaydaaf7742016-10-03 11:11:43 -0700212 let lifetime = Lifetime { ident: name.to_ident() };
David Tolnay55337722016-09-11 12:58:56 -0700213 self.with_lifetime(lifetime)
214 }
215
216 pub fn with_tys<I>(mut self, iter: I) -> Self
David Tolnaydaaf7742016-10-03 11:11:43 -0700217 where I: IntoIterator<Item = Ty>
David Tolnay55337722016-09-11 12:58:56 -0700218 {
219 self.tys.extend(iter);
220 self
221 }
222
223 pub fn with_ty(mut self, ty: Ty) -> Self {
224 self.tys.push(ty);
225 self
226 }
227
228 pub fn ty(self) -> TyBuilder<Self> {
229 TyBuilder::with_callback(self)
230 }
231
232 pub fn with_binding(mut self, binding: TypeBinding) -> Self {
233 self.bindings.push(binding);
234 self
235 }
236
237 pub fn binding<T>(self, id: T) -> TyBuilder<TypeBindingBuilder<F>>
David Tolnaydaaf7742016-10-03 11:11:43 -0700238 where T: ToIdent
David Tolnay55337722016-09-11 12:58:56 -0700239 {
240 TyBuilder::with_callback(TypeBindingBuilder {
David Tolnay05120ef2017-03-12 18:29:26 -0700241 id: id.to_ident(),
242 builder: self,
243 })
David Tolnay55337722016-09-11 12:58:56 -0700244 }
245
246 pub fn no_return(self) -> F::Result {
247 self.build_return(None)
248 }
249
250 pub fn return_(self) -> TyBuilder<PathSegmentReturnBuilder<F>> {
251 TyBuilder::with_callback(PathSegmentReturnBuilder(self))
252 }
253
254 pub fn build_return(self, output: Option<Ty>) -> F::Result {
255 let data = ParenthesizedParameterData {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700256 inputs: self.tys.into(),
257 output: match output {
258 Some(ty) => FunctionRetTy::Ty(ty, Default::default()),
259 None => FunctionRetTy::Default,
260 },
261 paren_token: Default::default(),
David Tolnay55337722016-09-11 12:58:56 -0700262 };
263
264 let parameters = PathParameters::Parenthesized(data);
265
266 self.callback.invoke(PathSegment {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700267 ident: self.id,
268 parameters: parameters,
269 })
David Tolnay55337722016-09-11 12:58:56 -0700270 }
271
272 pub fn build(self) -> F::Result {
273 let data = AngleBracketedParameterData {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700274 lifetimes: self.lifetimes.into(),
275 types: self.tys.into(),
276 bindings: self.bindings.into(),
277 gt_token: Default::default(),
278 lt_token: Default::default(),
David Tolnay55337722016-09-11 12:58:56 -0700279 };
280
281 let parameters = PathParameters::AngleBracketed(data);
282
283 self.callback.invoke(PathSegment {
David Tolnay05120ef2017-03-12 18:29:26 -0700284 ident: self.id,
285 parameters: parameters,
286 })
David Tolnay55337722016-09-11 12:58:56 -0700287 }
288}
289
290impl<F> Invoke<Ty> for PathSegmentBuilder<F>
291 where F: Invoke<PathSegment>
292{
293 type Result = Self;
294
295 fn invoke(self, ty: Ty) -> Self {
296 self.with_ty(ty)
297 }
298}
299
David Tolnaydaaf7742016-10-03 11:11:43 -0700300// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700301
302pub struct TypeBindingBuilder<F> {
303 id: Ident,
304 builder: PathSegmentBuilder<F>,
305}
306
307impl<F> Invoke<Ty> for TypeBindingBuilder<F>
308 where F: Invoke<PathSegment>
309{
310 type Result = PathSegmentBuilder<F>;
311
312 fn invoke(self, ty: Ty) -> Self::Result {
313 let id = self.id;
314
315 self.builder.with_binding(TypeBinding {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700316 ident: id,
317 ty: ty,
318 eq_token: Default::default(),
319 })
David Tolnay55337722016-09-11 12:58:56 -0700320 }
321}
322
David Tolnaydaaf7742016-10-03 11:11:43 -0700323// ////////////////////////////////////////////////////////////////////////////
David Tolnay55337722016-09-11 12:58:56 -0700324
325pub struct PathSegmentReturnBuilder<F>(PathSegmentBuilder<F>);
326
327impl<F> Invoke<Ty> for PathSegmentReturnBuilder<F>
328 where F: Invoke<PathSegment>
329{
330 type Result = F::Result;
331
332 fn invoke(self, ty: Ty) -> Self::Result {
333 self.0.build_return(Some(ty))
334 }
335}