1use crate::{attrs_builder, macros::AttrsPropsBuilder, IntoExpr, IntoIdent, IntoPath, IntoType};
2use proc_macro2::TokenStream;
3use syn::{
4 BoundLifetimes, ConstParam, GenericParam, Generics, Lifetime, LifetimeParam, PredicateLifetime,
5 PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
6 WherePredicate,
7};
8
9pub fn generics<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Generics {
10 Generics {
11 lt_token: Some(Default::default()),
12 params: FromIterator::from_iter(
13 params.into_iter().map(IntoGenericParam::into_generic_param),
14 ),
15 gt_token: Some(Default::default()),
16 ..Default::default()
17 }
18}
19
20pub trait GenericsBuilder {
21 fn new<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Self;
22 fn where_clause(self, where_clause: impl Into<WhereClause>) -> Self;
23}
24
25impl GenericsBuilder for Generics {
26 fn new<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Self {
27 generics(params)
28 }
29 fn where_clause(self, where_clause: impl Into<WhereClause>) -> Self {
30 Self {
31 where_clause: Some(where_clause.into()),
32 ..self
33 }
34 }
35}
36
37pub trait IntoGenericParam {
38 fn into_generic_param(self) -> GenericParam;
39}
40
41impl IntoGenericParam for GenericParam {
42 fn into_generic_param(self) -> GenericParam {
43 self
44 }
45}
46
47pub fn lifetime_param(lifetime: impl Into<Lifetime>) -> LifetimeParam {
48 LifetimeParam {
49 attrs: Default::default(),
50 lifetime: lifetime.into(),
51 colon_token: None,
52 bounds: Default::default(),
53 }
54}
55
56attrs_builder!(LifetimeParam);
57
58impl IntoGenericParam for LifetimeParam {
59 fn into_generic_param(self) -> GenericParam {
60 GenericParam::Lifetime(self)
61 }
62}
63
64pub trait LifetimeParamBuilder: AttrsPropsBuilder {
65 fn new(lifetime: impl Into<Lifetime>) -> Self;
66 fn bounds<B: Into<Lifetime>>(self, bounds: impl IntoIterator<Item = B>) -> Self;
67}
68
69impl LifetimeParamBuilder for LifetimeParam {
70 fn new(lifetime: impl Into<Lifetime>) -> Self {
71 lifetime_param(lifetime)
72 }
73
74 fn bounds<B: Into<Lifetime>>(self, bounds: impl IntoIterator<Item = B>) -> Self {
75 Self {
76 colon_token: Some(Default::default()),
77 bounds: bounds.into_iter().map(Into::into).collect(),
78 ..self
79 }
80 }
81}
82
83pub fn type_param(ident: impl IntoIdent) -> TypeParam {
84 TypeParam {
85 attrs: Default::default(),
86 ident: ident.into_ident(),
87 colon_token: None,
88 bounds: Default::default(),
89 eq_token: None,
90 default: None,
91 }
92}
93
94attrs_builder!(TypeParam);
95
96impl IntoGenericParam for TypeParam {
97 fn into_generic_param(self) -> GenericParam {
98 GenericParam::Type(self)
99 }
100}
101
102pub trait TypeParamBuilder: AttrsPropsBuilder {
103 fn new(ident: impl IntoIdent) -> Self;
104 fn bounds<B: IntoTypeParamBound>(self, bounds: impl IntoIterator<Item = B>) -> Self;
105 fn default(self, default: impl IntoType) -> Self;
106}
107
108impl TypeParamBuilder for TypeParam {
109 fn new(ident: impl IntoIdent) -> Self {
110 type_param(ident)
111 }
112
113 fn bounds<B: IntoTypeParamBound>(self, bounds: impl IntoIterator<Item = B>) -> Self {
114 Self {
115 colon_token: Some(Default::default()),
116 bounds: FromIterator::from_iter(
117 bounds
118 .into_iter()
119 .map(IntoTypeParamBound::into_type_param_bound),
120 ),
121 ..self
122 }
123 }
124
125 fn default(self, default: impl IntoType) -> Self {
126 Self {
127 eq_token: Some(Default::default()),
128 default: Some(default.into_type()),
129 ..self
130 }
131 }
132}
133
134pub fn const_param(ident: impl IntoIdent, ty: impl IntoType) -> ConstParam {
135 ConstParam {
136 attrs: Default::default(),
137 const_token: Default::default(),
138 ident: ident.into_ident(),
139 colon_token: Default::default(),
140 ty: ty.into_type(),
141 eq_token: None,
142 default: None,
143 }
144}
145
146attrs_builder!(ConstParam);
147
148impl IntoGenericParam for ConstParam {
149 fn into_generic_param(self) -> GenericParam {
150 GenericParam::Const(self)
151 }
152}
153
154pub trait ConstParamBuilder: AttrsPropsBuilder {
155 fn new(ident: impl IntoIdent, ty: impl IntoType) -> Self;
156 fn default(self, default: impl IntoExpr) -> Self;
157}
158
159impl ConstParamBuilder for ConstParam {
160 fn new(ident: impl IntoIdent, ty: impl IntoType) -> Self {
161 const_param(ident, ty)
162 }
163
164 fn default(self, default: impl IntoExpr) -> Self {
165 Self {
166 eq_token: Some(Default::default()),
167 default: Some(default.into_expr()),
168 ..self
169 }
170 }
171}
172
173pub fn bound_lifetimes<L: IntoGenericParam>(
174 lifetimes: impl IntoIterator<Item = L>,
175) -> BoundLifetimes {
176 BoundLifetimes {
177 lifetimes: FromIterator::from_iter(
178 lifetimes
179 .into_iter()
180 .map(IntoGenericParam::into_generic_param),
181 ),
182 ..Default::default()
183 }
184}
185
186pub trait BoundLifetimesBuilder {
187 fn new<L: IntoGenericParam>(lifetimes: impl IntoIterator<Item = L>) -> Self;
188}
189
190impl BoundLifetimesBuilder for BoundLifetimes {
191 fn new<L: IntoGenericParam>(lifetimes: impl IntoIterator<Item = L>) -> Self {
192 bound_lifetimes(lifetimes)
193 }
194}
195
196pub trait IntoTypeParamBound {
197 fn into_type_param_bound(self) -> TypeParamBound;
198}
199
200impl IntoTypeParamBound for TypeParamBound {
201 fn into_type_param_bound(self) -> TypeParamBound {
202 self
203 }
204}
205
206impl IntoTypeParamBound for Lifetime {
207 fn into_type_param_bound(self) -> TypeParamBound {
208 TypeParamBound::Lifetime(self)
209 }
210}
211
212impl IntoTypeParamBound for TokenStream {
213 fn into_type_param_bound(self) -> TypeParamBound {
214 TypeParamBound::Verbatim(self)
215 }
216}
217
218pub fn trait_bound(path: impl IntoPath) -> TraitBound {
219 TraitBound {
220 paren_token: None,
221 modifier: TraitBoundModifier::None,
222 lifetimes: None,
223 path: path.into_path(),
224 }
225}
226
227impl IntoTypeParamBound for TraitBound {
228 fn into_type_param_bound(self) -> TypeParamBound {
229 TypeParamBound::Trait(self)
230 }
231}
232
233pub trait TraitBoundBuilder {
234 fn new(path: impl IntoPath) -> Self;
235 fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self;
236 fn modifier(self, maybe: bool) -> Self;
237}
238
239impl TraitBoundBuilder for TraitBound {
240 fn new(path: impl IntoPath) -> Self {
241 trait_bound(path)
242 }
243
244 fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self {
245 Self {
246 lifetimes: Some(lifetimes.into()),
247 ..self
248 }
249 }
250
251 fn modifier(self, maybe: bool) -> Self {
252 Self {
253 modifier: if maybe {
254 TraitBoundModifier::Maybe(Default::default())
255 } else {
256 TraitBoundModifier::None
257 },
258 ..self
259 }
260 }
261}
262
263pub fn where_clause<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> WhereClause {
264 WhereClause {
265 where_token: Default::default(),
266 predicates: FromIterator::from_iter(
267 predicates
268 .into_iter()
269 .map(IntoWherePredicate::into_where_predicate),
270 ),
271 }
272}
273
274pub trait IntoWherePredicate {
275 fn into_where_predicate(self) -> WherePredicate;
276}
277
278impl IntoWherePredicate for WherePredicate {
279 fn into_where_predicate(self) -> WherePredicate {
280 self
281 }
282}
283
284pub trait WhereClauseBuilder {
285 fn new<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> Self;
286}
287
288impl WhereClauseBuilder for WhereClause {
289 fn new<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> Self {
290 where_clause(predicates)
291 }
292}
293
294pub fn predicate_lifetime<B: Into<Lifetime>>(
295 lifetime: impl Into<Lifetime>,
296 bounds: impl IntoIterator<Item = B>,
297) -> PredicateLifetime {
298 PredicateLifetime {
299 lifetime: lifetime.into(),
300 colon_token: Default::default(),
301 bounds: FromIterator::from_iter(bounds.into_iter().map(Into::into)),
302 }
303}
304
305impl IntoWherePredicate for PredicateLifetime {
306 fn into_where_predicate(self) -> WherePredicate {
307 WherePredicate::Lifetime(self)
308 }
309}
310
311pub trait PredicateLifetimeBuilder {
312 fn new<B: Into<Lifetime>>(
313 lifetime: impl Into<Lifetime>,
314 bounds: impl IntoIterator<Item = B>,
315 ) -> Self;
316}
317
318impl PredicateLifetimeBuilder for PredicateLifetime {
319 fn new<B: Into<Lifetime>>(
320 lifetime: impl Into<Lifetime>,
321 bounds: impl IntoIterator<Item = B>,
322 ) -> Self {
323 predicate_lifetime(lifetime, bounds)
324 }
325}
326
327pub fn predicate_type<B: IntoTypeParamBound>(
328 bounded_ty: impl IntoType,
329 bounds: impl IntoIterator<Item = B>,
330) -> PredicateType {
331 PredicateType {
332 lifetimes: None,
333 bounded_ty: bounded_ty.into_type(),
334 colon_token: Default::default(),
335 bounds: FromIterator::from_iter(
336 bounds
337 .into_iter()
338 .map(IntoTypeParamBound::into_type_param_bound),
339 ),
340 }
341}
342
343impl IntoWherePredicate for PredicateType {
344 fn into_where_predicate(self) -> WherePredicate {
345 WherePredicate::Type(self)
346 }
347}
348
349pub trait PredicateTypeBuilder {
350 fn new<B: IntoTypeParamBound>(
351 bounded_ty: impl IntoType,
352 bounds: impl IntoIterator<Item = B>,
353 ) -> Self;
354 fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self;
355}
356
357impl PredicateTypeBuilder for PredicateType {
358 fn new<B: IntoTypeParamBound>(
359 bounded_ty: impl IntoType,
360 bounds: impl IntoIterator<Item = B>,
361 ) -> Self {
362 predicate_type(bounded_ty, bounds)
363 }
364
365 fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self {
366 Self {
367 lifetimes: Some(lifetimes.into()),
368 ..self
369 }
370 }
371}