xso_proc/
types.rs

1// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7//! Module with specific [`syn::Type`] constructors.
8
9use proc_macro2::Span;
10use syn::{spanned::Spanned, *};
11
12/// Construct a [`syn::Type`] referring to `::xso::exports::rxml::Namespace`.
13pub(crate) fn namespace_ty(span: Span) -> Type {
14    Type::Path(TypePath {
15        qself: None,
16        path: Path {
17            leading_colon: Some(syn::token::PathSep {
18                spans: [span, span],
19            }),
20            segments: [
21                PathSegment {
22                    ident: Ident::new("xso", span),
23                    arguments: PathArguments::None,
24                },
25                PathSegment {
26                    ident: Ident::new("exports", span),
27                    arguments: PathArguments::None,
28                },
29                PathSegment {
30                    ident: Ident::new("rxml", span),
31                    arguments: PathArguments::None,
32                },
33                PathSegment {
34                    ident: Ident::new("Namespace", span),
35                    arguments: PathArguments::None,
36                },
37            ]
38            .into_iter()
39            .collect(),
40        },
41    })
42}
43
44/// Construct a [`syn::Type`] referring to `::xso::exports::rxml::NcNameStr`.
45pub(crate) fn ncnamestr_ty(span: Span) -> Type {
46    Type::Path(TypePath {
47        qself: None,
48        path: Path {
49            leading_colon: Some(syn::token::PathSep {
50                spans: [span, span],
51            }),
52            segments: [
53                PathSegment {
54                    ident: Ident::new("xso", span),
55                    arguments: PathArguments::None,
56                },
57                PathSegment {
58                    ident: Ident::new("exports", span),
59                    arguments: PathArguments::None,
60                },
61                PathSegment {
62                    ident: Ident::new("rxml", span),
63                    arguments: PathArguments::None,
64                },
65                PathSegment {
66                    ident: Ident::new("NcNameStr", span),
67                    arguments: PathArguments::None,
68                },
69            ]
70            .into_iter()
71            .collect(),
72        },
73    })
74}
75
76/// Construct a [`syn::Type`] referring to `Cow<#lifetime, #ty>`.
77pub(crate) fn cow_ty(ty: Type, lifetime: Lifetime) -> Type {
78    let span = ty.span();
79    Type::Path(TypePath {
80        qself: None,
81        path: Path {
82            leading_colon: Some(syn::token::PathSep {
83                spans: [span, span],
84            }),
85            segments: [
86                PathSegment {
87                    ident: Ident::new("xso", span),
88                    arguments: PathArguments::None,
89                },
90                PathSegment {
91                    ident: Ident::new("exports", span),
92                    arguments: PathArguments::None,
93                },
94                PathSegment {
95                    ident: Ident::new("alloc", span),
96                    arguments: PathArguments::None,
97                },
98                PathSegment {
99                    ident: Ident::new("borrow", span),
100                    arguments: PathArguments::None,
101                },
102                PathSegment {
103                    ident: Ident::new("Cow", span),
104                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
105                        colon2_token: None,
106                        lt_token: token::Lt { spans: [span] },
107                        args: [
108                            GenericArgument::Lifetime(lifetime),
109                            GenericArgument::Type(ty),
110                        ]
111                        .into_iter()
112                        .collect(),
113                        gt_token: token::Gt { spans: [span] },
114                    }),
115                },
116            ]
117            .into_iter()
118            .collect(),
119        },
120    })
121}
122
123/// Construct a [`syn::Type`] referring to
124/// `Cow<#lifetime, ::rxml::NcNameStr>`.
125pub(crate) fn ncnamestr_cow_ty(ty_span: Span, lifetime: Lifetime) -> Type {
126    cow_ty(ncnamestr_ty(ty_span), lifetime)
127}
128
129/// Construct a [`syn::Expr`] referring to
130/// `<#ty as ::xso::FromXmlText>::from_xml_text`.
131pub(crate) fn from_xml_text_fn(ty: Type) -> Expr {
132    let span = ty.span();
133    Expr::Path(ExprPath {
134        attrs: Vec::new(),
135        qself: Some(QSelf {
136            lt_token: syn::token::Lt { spans: [span] },
137            ty: Box::new(ty),
138            position: 2,
139            as_token: Some(syn::token::As { span }),
140            gt_token: syn::token::Gt { spans: [span] },
141        }),
142        path: Path {
143            leading_colon: Some(syn::token::PathSep {
144                spans: [span, span],
145            }),
146            segments: [
147                PathSegment {
148                    ident: Ident::new("xso", span),
149                    arguments: PathArguments::None,
150                },
151                PathSegment {
152                    ident: Ident::new("FromXmlText", span),
153                    arguments: PathArguments::None,
154                },
155                PathSegment {
156                    ident: Ident::new("from_xml_text", span),
157                    arguments: PathArguments::None,
158                },
159            ]
160            .into_iter()
161            .collect(),
162        },
163    })
164}
165
166/// Construct a [`syn::Expr`] referring to
167/// `<#ty as ::xso::AsOptionalXmlText>::as_optional_xml_text`.
168pub(crate) fn as_optional_xml_text_fn(ty: Type) -> Expr {
169    let span = ty.span();
170    Expr::Path(ExprPath {
171        attrs: Vec::new(),
172        qself: Some(QSelf {
173            lt_token: syn::token::Lt { spans: [span] },
174            ty: Box::new(ty),
175            position: 2,
176            as_token: Some(syn::token::As { span }),
177            gt_token: syn::token::Gt { spans: [span] },
178        }),
179        path: Path {
180            leading_colon: Some(syn::token::PathSep {
181                spans: [span, span],
182            }),
183            segments: [
184                PathSegment {
185                    ident: Ident::new("xso", span),
186                    arguments: PathArguments::None,
187                },
188                PathSegment {
189                    ident: Ident::new("AsOptionalXmlText", span),
190                    arguments: PathArguments::None,
191                },
192                PathSegment {
193                    ident: Ident::new("as_optional_xml_text", span),
194                    arguments: PathArguments::None,
195                },
196            ]
197            .into_iter()
198            .collect(),
199        },
200    })
201}
202
203/// Construct a [`syn::Expr`] referring to
204/// `<#of_ty as ::core::default::Default>::default`.
205pub(crate) fn default_fn(of_ty: Type) -> Expr {
206    let span = of_ty.span();
207    Expr::Path(ExprPath {
208        attrs: Vec::new(),
209        qself: Some(QSelf {
210            lt_token: syn::token::Lt { spans: [span] },
211            ty: Box::new(of_ty),
212            position: 3,
213            as_token: Some(syn::token::As { span }),
214            gt_token: syn::token::Gt { spans: [span] },
215        }),
216        path: Path {
217            leading_colon: Some(syn::token::PathSep {
218                spans: [span, span],
219            }),
220            segments: [
221                PathSegment {
222                    ident: Ident::new("core", span),
223                    arguments: PathArguments::None,
224                },
225                PathSegment {
226                    ident: Ident::new("default", span),
227                    arguments: PathArguments::None,
228                },
229                PathSegment {
230                    ident: Ident::new("Default", span),
231                    arguments: PathArguments::None,
232                },
233                PathSegment {
234                    ident: Ident::new("default", span),
235                    arguments: PathArguments::None,
236                },
237            ]
238            .into_iter()
239            .collect(),
240        },
241    })
242}
243
244/// Construct a [`syn::Type`] referring to `::alloc::string::String`.
245pub(crate) fn string_ty(span: Span) -> Type {
246    Type::Path(TypePath {
247        qself: None,
248        path: Path {
249            leading_colon: Some(syn::token::PathSep {
250                spans: [span, span],
251            }),
252            segments: [
253                PathSegment {
254                    ident: Ident::new("xso", span),
255                    arguments: PathArguments::None,
256                },
257                PathSegment {
258                    ident: Ident::new("exports", span),
259                    arguments: PathArguments::None,
260                },
261                PathSegment {
262                    ident: Ident::new("alloc", span),
263                    arguments: PathArguments::None,
264                },
265                PathSegment {
266                    ident: Ident::new("string", span),
267                    arguments: PathArguments::None,
268                },
269                PathSegment {
270                    ident: Ident::new("String", span),
271                    arguments: PathArguments::None,
272                },
273            ]
274            .into_iter()
275            .collect(),
276        },
277    })
278}
279
280/// Construct a [`syn::Expr`] referring to
281/// `<#ty as ::xso::AsXmlText>::as_xml_text`.
282pub(crate) fn as_xml_text_fn(ty: Type) -> Expr {
283    let span = ty.span();
284    Expr::Path(ExprPath {
285        attrs: Vec::new(),
286        qself: Some(QSelf {
287            lt_token: syn::token::Lt { spans: [span] },
288            ty: Box::new(ty),
289            position: 2,
290            as_token: Some(syn::token::As { span }),
291            gt_token: syn::token::Gt { spans: [span] },
292        }),
293        path: Path {
294            leading_colon: Some(syn::token::PathSep {
295                spans: [span, span],
296            }),
297            segments: [
298                PathSegment {
299                    ident: Ident::new("xso", span),
300                    arguments: PathArguments::None,
301                },
302                PathSegment {
303                    ident: Ident::new("AsXmlText", span),
304                    arguments: PathArguments::None,
305                },
306                PathSegment {
307                    ident: Ident::new("as_xml_text", span),
308                    arguments: PathArguments::None,
309                },
310            ]
311            .into_iter()
312            .collect(),
313        },
314    })
315}
316
317/// Construct a [`syn::Path`] referring to `::xso::TextCodec::<#for_ty>`,
318/// returning the span of `for_ty` alongside it.
319///
320/// The span used is `codec_span`, in order to ensure that error messages
321/// about a missing implementation point at the codec, not at the type.
322fn text_codec_of(for_ty: Type, codec_span: Span) -> Path {
323    let span = codec_span;
324    Path {
325        leading_colon: Some(syn::token::PathSep {
326            spans: [span, span],
327        }),
328        segments: [
329            PathSegment {
330                ident: Ident::new("xso", span),
331                arguments: PathArguments::None,
332            },
333            PathSegment {
334                ident: Ident::new("TextCodec", span),
335                arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
336                    colon2_token: Some(syn::token::PathSep {
337                        spans: [span, span],
338                    }),
339                    lt_token: syn::token::Lt { spans: [span] },
340                    args: [GenericArgument::Type(for_ty)].into_iter().collect(),
341                    gt_token: syn::token::Gt { spans: [span] },
342                }),
343            },
344        ]
345        .into_iter()
346        .collect(),
347    }
348}
349
350/// Construct a [`syn::Expr`] referring to
351/// `::xso::TextCodec::<#for_ty>::encode`.
352///
353/// The span used is `codec_span`, in order to ensure that error messages
354/// about a missing implementation point at the codec, not at the type.
355pub(crate) fn text_codec_encode_fn(for_ty: Type, codec_span: Span) -> Expr {
356    let mut path = text_codec_of(for_ty, codec_span);
357    path.segments.push(PathSegment {
358        ident: Ident::new("encode", codec_span),
359        arguments: PathArguments::None,
360    });
361    Expr::Path(ExprPath {
362        attrs: Vec::new(),
363        qself: None,
364        path,
365    })
366}
367
368/// Construct a [`syn::Expr`] referring to
369/// `::xso::TextCodec::<#for_ty>::decode`.
370///
371/// The span used is `codec_span`, in order to ensure that error messages
372/// about a missing implementation point at the codec, not at the type.
373pub(crate) fn text_codec_decode_fn(for_ty: Type, codec_span: Span) -> Expr {
374    let mut path = text_codec_of(for_ty, codec_span);
375    path.segments.push(PathSegment {
376        ident: Ident::new("decode", codec_span),
377        arguments: PathArguments::None,
378    });
379    Expr::Path(ExprPath {
380        attrs: Vec::new(),
381        qself: None,
382        path,
383    })
384}
385
386/// Construct a [`syn::Type`] for `&#lifetime #ty`.
387pub(crate) fn ref_ty(ty: Type, lifetime: Lifetime) -> Type {
388    let span = ty.span();
389    Type::Reference(TypeReference {
390        and_token: token::And { spans: [span] },
391        lifetime: Some(lifetime),
392        mutability: None,
393        elem: Box::new(ty),
394    })
395}
396
397/// Construct a [`syn::Type`] referring to
398/// `::core::marker::PhantomData<&#lifetime ()>`.
399pub(crate) fn phantom_lifetime_ty(lifetime: Lifetime) -> Type {
400    let span = lifetime.span();
401    let dummy = Type::Tuple(TypeTuple {
402        paren_token: token::Paren::default(),
403        elems: punctuated::Punctuated::default(),
404    });
405    Type::Path(TypePath {
406        qself: None,
407        path: Path {
408            leading_colon: Some(syn::token::PathSep {
409                spans: [span, span],
410            }),
411            segments: [
412                PathSegment {
413                    ident: Ident::new("core", span),
414                    arguments: PathArguments::None,
415                },
416                PathSegment {
417                    ident: Ident::new("marker", span),
418                    arguments: PathArguments::None,
419                },
420                PathSegment {
421                    ident: Ident::new("PhantomData", span),
422                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
423                        colon2_token: None,
424                        lt_token: token::Lt { spans: [span] },
425                        args: [GenericArgument::Type(ref_ty(dummy, lifetime))]
426                            .into_iter()
427                            .collect(),
428                        gt_token: token::Gt { spans: [span] },
429                    }),
430                },
431            ]
432            .into_iter()
433            .collect(),
434        },
435    })
436}
437
438/// Construct a [`syn::TypePath`] referring to
439/// `<#of_ty as ::xso::FromXml>`.
440fn from_xml_of(of_ty: Type) -> (Span, TypePath) {
441    let span = of_ty.span();
442    (
443        span,
444        TypePath {
445            qself: Some(QSelf {
446                lt_token: syn::token::Lt { spans: [span] },
447                ty: Box::new(of_ty),
448                position: 2,
449                as_token: Some(syn::token::As { span }),
450                gt_token: syn::token::Gt { spans: [span] },
451            }),
452            path: Path {
453                leading_colon: Some(syn::token::PathSep {
454                    spans: [span, span],
455                }),
456                segments: [
457                    PathSegment {
458                        ident: Ident::new("xso", span),
459                        arguments: PathArguments::None,
460                    },
461                    PathSegment {
462                        ident: Ident::new("FromXml", span),
463                        arguments: PathArguments::None,
464                    },
465                ]
466                .into_iter()
467                .collect(),
468            },
469        },
470    )
471}
472
473/// Construct a [`syn::Type`] referring to
474/// `<#of_ty as ::xso::FromXml>::Builder`.
475pub(crate) fn from_xml_builder_ty(of_ty: Type) -> Type {
476    let (span, mut ty) = from_xml_of(of_ty);
477    ty.path.segments.push(PathSegment {
478        ident: Ident::new("Builder", span),
479        arguments: PathArguments::None,
480    });
481    Type::Path(ty)
482}
483
484/// Construct a [`syn::Expr`] referring to
485/// `<#of_ty as ::xso::FromXml>::from_events`.
486pub(crate) fn from_events_fn(of_ty: Type) -> Expr {
487    let (span, mut ty) = from_xml_of(of_ty);
488    ty.path.segments.push(PathSegment {
489        ident: Ident::new("from_events", span),
490        arguments: PathArguments::None,
491    });
492    Expr::Path(ExprPath {
493        attrs: Vec::new(),
494        qself: ty.qself,
495        path: ty.path,
496    })
497}
498
499/// Construct a [`syn::Type`] which wraps the given `ty` in
500/// `::core::option::Option<_>`.
501pub(crate) fn option_ty(ty: Type) -> Type {
502    let span = ty.span();
503    Type::Path(TypePath {
504        qself: None,
505        path: Path {
506            leading_colon: Some(syn::token::PathSep {
507                spans: [span, span],
508            }),
509            segments: [
510                PathSegment {
511                    ident: Ident::new("core", span),
512                    arguments: PathArguments::None,
513                },
514                PathSegment {
515                    ident: Ident::new("option", span),
516                    arguments: PathArguments::None,
517                },
518                PathSegment {
519                    ident: Ident::new("Option", span),
520                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
521                        colon2_token: None,
522                        lt_token: syn::token::Lt { spans: [span] },
523                        args: [GenericArgument::Type(ty)].into_iter().collect(),
524                        gt_token: syn::token::Gt { spans: [span] },
525                    }),
526                },
527            ]
528            .into_iter()
529            .collect(),
530        },
531    })
532}
533
534/// Construct a [`syn::TypePath`] referring to
535/// `<#of_ty as ::xso::FromEventsBuilder>`.
536fn from_events_builder_of(of_ty: Type) -> (Span, TypePath) {
537    let span = of_ty.span();
538    (
539        span,
540        TypePath {
541            qself: Some(QSelf {
542                lt_token: syn::token::Lt { spans: [span] },
543                ty: Box::new(of_ty),
544                position: 2,
545                as_token: Some(syn::token::As { span }),
546                gt_token: syn::token::Gt { spans: [span] },
547            }),
548            path: Path {
549                leading_colon: Some(syn::token::PathSep {
550                    spans: [span, span],
551                }),
552                segments: [
553                    PathSegment {
554                        ident: Ident::new("xso", span),
555                        arguments: PathArguments::None,
556                    },
557                    PathSegment {
558                        ident: Ident::new("FromEventsBuilder", span),
559                        arguments: PathArguments::None,
560                    },
561                ]
562                .into_iter()
563                .collect(),
564            },
565        },
566    )
567}
568
569/// Construct a [`syn::Expr`] referring to
570/// `<#of_ty as ::xso::FromEventsBuilder>::feed`.
571pub(crate) fn feed_fn(of_ty: Type) -> Expr {
572    let (span, mut ty) = from_events_builder_of(of_ty);
573    ty.path.segments.push(PathSegment {
574        ident: Ident::new("feed", span),
575        arguments: PathArguments::None,
576    });
577    Expr::Path(ExprPath {
578        attrs: Vec::new(),
579        qself: ty.qself,
580        path: ty.path,
581    })
582}
583
584fn as_xml_of(of_ty: Type) -> (Span, TypePath) {
585    let span = of_ty.span();
586    (
587        span,
588        TypePath {
589            qself: Some(QSelf {
590                lt_token: syn::token::Lt { spans: [span] },
591                ty: Box::new(of_ty),
592                position: 2,
593                as_token: Some(syn::token::As { span }),
594                gt_token: syn::token::Gt { spans: [span] },
595            }),
596            path: Path {
597                leading_colon: Some(syn::token::PathSep {
598                    spans: [span, span],
599                }),
600                segments: [
601                    PathSegment {
602                        ident: Ident::new("xso", span),
603                        arguments: PathArguments::None,
604                    },
605                    PathSegment {
606                        ident: Ident::new("AsXml", span),
607                        arguments: PathArguments::None,
608                    },
609                ]
610                .into_iter()
611                .collect(),
612            },
613        },
614    )
615}
616
617/// Construct a [`syn::Expr`] referring to
618/// `<#of_ty as ::xso::AsXml>::as_xml_iter`.
619pub(crate) fn as_xml_iter_fn(of_ty: Type) -> Expr {
620    let (span, mut ty) = as_xml_of(of_ty);
621    ty.path.segments.push(PathSegment {
622        ident: Ident::new("as_xml_iter", span),
623        arguments: PathArguments::None,
624    });
625    Expr::Path(ExprPath {
626        attrs: Vec::new(),
627        qself: ty.qself,
628        path: ty.path,
629    })
630}
631
632/// Construct a [`syn::Type`] referring to
633/// `<#of_ty as ::xso::AsXml>::ItemIter`.
634pub(crate) fn item_iter_ty(of_ty: Type, lifetime: Lifetime) -> Type {
635    let (span, mut ty) = as_xml_of(of_ty);
636    ty.path.segments.push(PathSegment {
637        ident: Ident::new("ItemIter", span),
638        arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
639            colon2_token: None,
640            lt_token: token::Lt { spans: [span] },
641            args: [GenericArgument::Lifetime(lifetime)].into_iter().collect(),
642            gt_token: token::Gt { spans: [span] },
643        }),
644    });
645    Type::Path(ty)
646}
647
648/// Construct a [`syn::TypePath`] referring to `<#of_ty as IntoIterator>`.
649fn into_iterator_of(of_ty: Type) -> (Span, TypePath) {
650    let span = of_ty.span();
651    (
652        span,
653        TypePath {
654            qself: Some(QSelf {
655                lt_token: syn::token::Lt { spans: [span] },
656                ty: Box::new(of_ty),
657                position: 3,
658                as_token: Some(syn::token::As { span }),
659                gt_token: syn::token::Gt { spans: [span] },
660            }),
661            path: Path {
662                leading_colon: Some(syn::token::PathSep {
663                    spans: [span, span],
664                }),
665                segments: [
666                    PathSegment {
667                        ident: Ident::new("core", span),
668                        arguments: PathArguments::None,
669                    },
670                    PathSegment {
671                        ident: Ident::new("iter", span),
672                        arguments: PathArguments::None,
673                    },
674                    PathSegment {
675                        ident: Ident::new("IntoIterator", span),
676                        arguments: PathArguments::None,
677                    },
678                ]
679                .into_iter()
680                .collect(),
681            },
682        },
683    )
684}
685
686/// Construct a [`syn::Type`] referring to
687/// `<#of_ty as IntoIterator>::IntoIter`.
688pub(crate) fn into_iterator_iter_ty(of_ty: Type) -> Type {
689    let (span, mut ty) = into_iterator_of(of_ty);
690    ty.path.segments.push(PathSegment {
691        ident: Ident::new("IntoIter", span),
692        arguments: PathArguments::None,
693    });
694    Type::Path(ty)
695}
696
697/// Construct a [`syn::Type`] referring to
698/// `<#of_ty as IntoIterator>::Item`.
699pub(crate) fn into_iterator_item_ty(of_ty: Type) -> Type {
700    let (span, mut ty) = into_iterator_of(of_ty);
701    ty.path.segments.push(PathSegment {
702        ident: Ident::new("Item", span),
703        arguments: PathArguments::None,
704    });
705    Type::Path(ty)
706}
707
708/// Construct a [`syn::Expr`] referring to
709/// `<#of_ty as IntoIterator>::into_iter`.
710pub(crate) fn into_iterator_into_iter_fn(of_ty: Type) -> Expr {
711    let (span, mut ty) = into_iterator_of(of_ty);
712    ty.path.segments.push(PathSegment {
713        ident: Ident::new("into_iter", span),
714        arguments: PathArguments::None,
715    });
716    Expr::Path(ExprPath {
717        attrs: Vec::new(),
718        qself: ty.qself,
719        path: ty.path,
720    })
721}
722
723/// Construct a [`syn::Expr`] referring to
724/// `<#of_ty as ::core::iter::Extend>::extend`.
725pub(crate) fn extend_fn(of_ty: Type, item_ty: Type) -> Expr {
726    let span = of_ty.span();
727    Expr::Path(ExprPath {
728        attrs: Vec::new(),
729        qself: Some(QSelf {
730            lt_token: syn::token::Lt { spans: [span] },
731            ty: Box::new(of_ty),
732            position: 3,
733            as_token: Some(syn::token::As { span }),
734            gt_token: syn::token::Gt { spans: [span] },
735        }),
736        path: Path {
737            leading_colon: Some(syn::token::PathSep {
738                spans: [span, span],
739            }),
740            segments: [
741                PathSegment {
742                    ident: Ident::new("core", span),
743                    arguments: PathArguments::None,
744                },
745                PathSegment {
746                    ident: Ident::new("iter", span),
747                    arguments: PathArguments::None,
748                },
749                PathSegment {
750                    ident: Ident::new("Extend", span),
751                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
752                        colon2_token: Some(syn::token::PathSep {
753                            spans: [span, span],
754                        }),
755                        lt_token: syn::token::Lt { spans: [span] },
756                        args: [GenericArgument::Type(item_ty)].into_iter().collect(),
757                        gt_token: syn::token::Gt { spans: [span] },
758                    }),
759                },
760                PathSegment {
761                    ident: Ident::new("extend", span),
762                    arguments: PathArguments::None,
763                },
764            ]
765            .into_iter()
766            .collect(),
767        },
768    })
769}
770
771/// Construct a [`syn::TypePath`] which references the given type name.
772pub(crate) fn ty_from_ident(ident: Ident) -> TypePath {
773    TypePath {
774        qself: None,
775        path: ident.into(),
776    }
777}
778
779/// Construct a [`syn::Type`] referring to `xso::OptionAsXml<#inner_ty>`.
780pub(crate) fn option_as_xml_ty(inner_ty: Type) -> Type {
781    let span = inner_ty.span();
782    Type::Path(TypePath {
783        qself: None,
784        path: Path {
785            leading_colon: Some(syn::token::PathSep {
786                spans: [span, span],
787            }),
788            segments: [
789                PathSegment {
790                    ident: Ident::new("xso", span),
791                    arguments: PathArguments::None,
792                },
793                PathSegment {
794                    ident: Ident::new("asxml", span),
795                    arguments: PathArguments::None,
796                },
797                PathSegment {
798                    ident: Ident::new("OptionAsXml", span),
799                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
800                        colon2_token: None,
801                        lt_token: token::Lt { spans: [span] },
802                        args: [GenericArgument::Type(inner_ty)].into_iter().collect(),
803                        gt_token: token::Gt { spans: [span] },
804                    }),
805                },
806            ]
807            .into_iter()
808            .collect(),
809        },
810    })
811}
812
813/// Construct a [`syn::Type`] referring to `::xso::exports::minidom::Element`.
814#[cfg(feature = "minidom")]
815pub(crate) fn element_ty(span: Span) -> Type {
816    Type::Path(TypePath {
817        qself: None,
818        path: Path {
819            leading_colon: Some(syn::token::PathSep {
820                spans: [span, span],
821            }),
822            segments: [
823                PathSegment {
824                    ident: Ident::new("xso", span),
825                    arguments: PathArguments::None,
826                },
827                PathSegment {
828                    ident: Ident::new("exports", span),
829                    arguments: PathArguments::None,
830                },
831                PathSegment {
832                    ident: Ident::new("minidom", span),
833                    arguments: PathArguments::None,
834                },
835                PathSegment {
836                    ident: Ident::new("Element", span),
837                    arguments: PathArguments::None,
838                },
839            ]
840            .into_iter()
841            .collect(),
842        },
843    })
844}
845
846/// Construct a [`syn::Path`] referring to `::xso::UnknownAttributePolicy`.
847pub(crate) fn unknown_attribute_policy_path(span: Span) -> Path {
848    Path {
849        leading_colon: Some(syn::token::PathSep {
850            spans: [span, span],
851        }),
852        segments: [
853            PathSegment {
854                ident: Ident::new("xso", span),
855                arguments: PathArguments::None,
856            },
857            PathSegment {
858                ident: Ident::new("UnknownAttributePolicy", span),
859                arguments: PathArguments::None,
860            },
861        ]
862        .into_iter()
863        .collect(),
864    }
865}
866
867/// Construct a [`syn::Path`] referring to `::xso::UnknownChildPolicy`.
868pub(crate) fn unknown_child_policy_path(span: Span) -> Path {
869    Path {
870        leading_colon: Some(syn::token::PathSep {
871            spans: [span, span],
872        }),
873        segments: [
874            PathSegment {
875                ident: Ident::new("xso", span),
876                arguments: PathArguments::None,
877            },
878            PathSegment {
879                ident: Ident::new("UnknownChildPolicy", span),
880                arguments: PathArguments::None,
881            },
882        ]
883        .into_iter()
884        .collect(),
885    }
886}
887
888/// Construct a [`syn::Type`] referring to `::xso::fromxml::Discard`.
889pub(crate) fn discard_builder_ty(span: Span) -> Type {
890    Type::Path(TypePath {
891        qself: None,
892        path: Path {
893            leading_colon: Some(syn::token::PathSep {
894                spans: [span, span],
895            }),
896            segments: [
897                PathSegment {
898                    ident: Ident::new("xso", span),
899                    arguments: PathArguments::None,
900                },
901                PathSegment {
902                    ident: Ident::new("fromxml", span),
903                    arguments: PathArguments::None,
904                },
905                PathSegment {
906                    ident: Ident::new("Discard", span),
907                    arguments: PathArguments::None,
908                },
909            ]
910            .into_iter()
911            .collect(),
912        },
913    })
914}
915
916/// Construct a [`syn::Type`] referring to the built-in `bool` type.
917///
918/// Note that we go through `xso::exports::CoreBool` for that, because there seems
919/// to be no way to access built-in types once they have been shadowed in a
920/// scope.
921pub(crate) fn bool_ty(span: Span) -> Type {
922    Type::Path(TypePath {
923        qself: None,
924        path: Path {
925            leading_colon: Some(syn::token::PathSep {
926                spans: [span, span],
927            }),
928            segments: [
929                PathSegment {
930                    ident: Ident::new("xso", span),
931                    arguments: PathArguments::None,
932                },
933                PathSegment {
934                    ident: Ident::new("exports", span),
935                    arguments: PathArguments::None,
936                },
937                PathSegment {
938                    ident: Ident::new("CoreBool", span),
939                    arguments: PathArguments::None,
940                },
941            ]
942            .into_iter()
943            .collect(),
944        },
945    })
946}
947
948/// Construct a [`syn::Type`] referring to the built-in `u8` type.
949///
950/// Note that we go through `xso::exports::CoreU8` for that, because there seems
951/// to be no way to access built-in types once they have been shadowed in a
952/// scope.
953pub(crate) fn u8_ty(span: Span) -> Type {
954    Type::Path(TypePath {
955        qself: None,
956        path: Path {
957            leading_colon: Some(syn::token::PathSep {
958                spans: [span, span],
959            }),
960            segments: [
961                PathSegment {
962                    ident: Ident::new("xso", span),
963                    arguments: PathArguments::None,
964                },
965                PathSegment {
966                    ident: Ident::new("exports", span),
967                    arguments: PathArguments::None,
968                },
969                PathSegment {
970                    ident: Ident::new("CoreU8", span),
971                    arguments: PathArguments::None,
972                },
973            ]
974            .into_iter()
975            .collect(),
976        },
977    })
978}
979
980/// Construct a [`syn::Type`] referring to `::xso::fromxml::EmptyBuilder`.
981pub(crate) fn empty_builder_ty(span: Span) -> Type {
982    Type::Path(TypePath {
983        qself: None,
984        path: Path {
985            leading_colon: Some(syn::token::PathSep {
986                spans: [span, span],
987            }),
988            segments: [
989                PathSegment {
990                    ident: Ident::new("xso", span),
991                    arguments: PathArguments::None,
992                },
993                PathSegment {
994                    ident: Ident::new("fromxml", span),
995                    arguments: PathArguments::None,
996                },
997                PathSegment {
998                    ident: Ident::new("EmptyBuilder", span),
999                    arguments: PathArguments::None,
1000                },
1001            ]
1002            .into_iter()
1003            .collect(),
1004        },
1005    })
1006}