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.
319fn text_codec_of(for_ty: Type) -> (Span, Path) {
320    let span = for_ty.span();
321    (
322        span,
323        Path {
324            leading_colon: Some(syn::token::PathSep {
325                spans: [span, span],
326            }),
327            segments: [
328                PathSegment {
329                    ident: Ident::new("xso", span),
330                    arguments: PathArguments::None,
331                },
332                PathSegment {
333                    ident: Ident::new("TextCodec", span),
334                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
335                        colon2_token: Some(syn::token::PathSep {
336                            spans: [span, span],
337                        }),
338                        lt_token: syn::token::Lt { spans: [span] },
339                        args: [GenericArgument::Type(for_ty)].into_iter().collect(),
340                        gt_token: syn::token::Gt { spans: [span] },
341                    }),
342                },
343            ]
344            .into_iter()
345            .collect(),
346        },
347    )
348}
349
350/// Construct a [`syn::Expr`] referring to
351/// `::xso::TextCodec::<#for_ty>::encode`.
352pub(crate) fn text_codec_encode_fn(for_ty: Type) -> Expr {
353    let (span, mut path) = text_codec_of(for_ty);
354    path.segments.push(PathSegment {
355        ident: Ident::new("encode", span),
356        arguments: PathArguments::None,
357    });
358    Expr::Path(ExprPath {
359        attrs: Vec::new(),
360        qself: None,
361        path: path,
362    })
363}
364
365/// Construct a [`syn::Expr`] referring to
366/// `::xso::TextCodec::<#for_ty>::decode`.
367pub(crate) fn text_codec_decode_fn(for_ty: Type) -> Expr {
368    let (span, mut path) = text_codec_of(for_ty);
369    path.segments.push(PathSegment {
370        ident: Ident::new("decode", span),
371        arguments: PathArguments::None,
372    });
373    Expr::Path(ExprPath {
374        attrs: Vec::new(),
375        qself: None,
376        path: path,
377    })
378}
379
380/// Construct a [`syn::Type`] for `&#lifetime #ty`.
381pub(crate) fn ref_ty(ty: Type, lifetime: Lifetime) -> Type {
382    let span = ty.span();
383    Type::Reference(TypeReference {
384        and_token: token::And { spans: [span] },
385        lifetime: Some(lifetime),
386        mutability: None,
387        elem: Box::new(ty),
388    })
389}
390
391/// Construct a [`syn::Type`] referring to
392/// `::core::marker::PhantomData<&#lifetime ()>`.
393pub(crate) fn phantom_lifetime_ty(lifetime: Lifetime) -> Type {
394    let span = lifetime.span();
395    let dummy = Type::Tuple(TypeTuple {
396        paren_token: token::Paren::default(),
397        elems: punctuated::Punctuated::default(),
398    });
399    Type::Path(TypePath {
400        qself: None,
401        path: Path {
402            leading_colon: Some(syn::token::PathSep {
403                spans: [span, span],
404            }),
405            segments: [
406                PathSegment {
407                    ident: Ident::new("core", span),
408                    arguments: PathArguments::None,
409                },
410                PathSegment {
411                    ident: Ident::new("marker", span),
412                    arguments: PathArguments::None,
413                },
414                PathSegment {
415                    ident: Ident::new("PhantomData", span),
416                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
417                        colon2_token: None,
418                        lt_token: token::Lt { spans: [span] },
419                        args: [GenericArgument::Type(ref_ty(dummy, lifetime))]
420                            .into_iter()
421                            .collect(),
422                        gt_token: token::Gt { spans: [span] },
423                    }),
424                },
425            ]
426            .into_iter()
427            .collect(),
428        },
429    })
430}
431
432/// Construct a [`syn::TypePath`] referring to
433/// `<#of_ty as ::xso::FromXml>`.
434fn from_xml_of(of_ty: Type) -> (Span, TypePath) {
435    let span = of_ty.span();
436    (
437        span,
438        TypePath {
439            qself: Some(QSelf {
440                lt_token: syn::token::Lt { spans: [span] },
441                ty: Box::new(of_ty),
442                position: 2,
443                as_token: Some(syn::token::As { span }),
444                gt_token: syn::token::Gt { spans: [span] },
445            }),
446            path: Path {
447                leading_colon: Some(syn::token::PathSep {
448                    spans: [span, span],
449                }),
450                segments: [
451                    PathSegment {
452                        ident: Ident::new("xso", span),
453                        arguments: PathArguments::None,
454                    },
455                    PathSegment {
456                        ident: Ident::new("FromXml", span),
457                        arguments: PathArguments::None,
458                    },
459                ]
460                .into_iter()
461                .collect(),
462            },
463        },
464    )
465}
466
467/// Construct a [`syn::Type`] referring to
468/// `<#of_ty as ::xso::FromXml>::Builder`.
469pub(crate) fn from_xml_builder_ty(of_ty: Type) -> Type {
470    let (span, mut ty) = from_xml_of(of_ty);
471    ty.path.segments.push(PathSegment {
472        ident: Ident::new("Builder", span),
473        arguments: PathArguments::None,
474    });
475    Type::Path(ty)
476}
477
478/// Construct a [`syn::Expr`] referring to
479/// `<#of_ty as ::xso::FromXml>::from_events`.
480pub(crate) fn from_events_fn(of_ty: Type) -> Expr {
481    let (span, mut ty) = from_xml_of(of_ty);
482    ty.path.segments.push(PathSegment {
483        ident: Ident::new("from_events", span),
484        arguments: PathArguments::None,
485    });
486    Expr::Path(ExprPath {
487        attrs: Vec::new(),
488        qself: ty.qself,
489        path: ty.path,
490    })
491}
492
493/// Construct a [`syn::Type`] which wraps the given `ty` in
494/// `::core::option::Option<_>`.
495pub(crate) fn option_ty(ty: Type) -> Type {
496    let span = ty.span();
497    Type::Path(TypePath {
498        qself: None,
499        path: Path {
500            leading_colon: Some(syn::token::PathSep {
501                spans: [span, span],
502            }),
503            segments: [
504                PathSegment {
505                    ident: Ident::new("core", span),
506                    arguments: PathArguments::None,
507                },
508                PathSegment {
509                    ident: Ident::new("option", span),
510                    arguments: PathArguments::None,
511                },
512                PathSegment {
513                    ident: Ident::new("Option", span),
514                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
515                        colon2_token: None,
516                        lt_token: syn::token::Lt { spans: [span] },
517                        args: [GenericArgument::Type(ty)].into_iter().collect(),
518                        gt_token: syn::token::Gt { spans: [span] },
519                    }),
520                },
521            ]
522            .into_iter()
523            .collect(),
524        },
525    })
526}
527
528/// Construct a [`syn::TypePath`] referring to
529/// `<#of_ty as ::xso::FromEventsBuilder>`.
530fn from_events_builder_of(of_ty: Type) -> (Span, TypePath) {
531    let span = of_ty.span();
532    (
533        span,
534        TypePath {
535            qself: Some(QSelf {
536                lt_token: syn::token::Lt { spans: [span] },
537                ty: Box::new(of_ty),
538                position: 2,
539                as_token: Some(syn::token::As { span }),
540                gt_token: syn::token::Gt { spans: [span] },
541            }),
542            path: Path {
543                leading_colon: Some(syn::token::PathSep {
544                    spans: [span, span],
545                }),
546                segments: [
547                    PathSegment {
548                        ident: Ident::new("xso", span),
549                        arguments: PathArguments::None,
550                    },
551                    PathSegment {
552                        ident: Ident::new("FromEventsBuilder", span),
553                        arguments: PathArguments::None,
554                    },
555                ]
556                .into_iter()
557                .collect(),
558            },
559        },
560    )
561}
562
563/// Construct a [`syn::Expr`] referring to
564/// `<#of_ty as ::xso::FromEventsBuilder>::feed`.
565pub(crate) fn feed_fn(of_ty: Type) -> Expr {
566    let (span, mut ty) = from_events_builder_of(of_ty);
567    ty.path.segments.push(PathSegment {
568        ident: Ident::new("feed", span),
569        arguments: PathArguments::None,
570    });
571    Expr::Path(ExprPath {
572        attrs: Vec::new(),
573        qself: ty.qself,
574        path: ty.path,
575    })
576}
577
578fn as_xml_of(of_ty: Type) -> (Span, TypePath) {
579    let span = of_ty.span();
580    (
581        span,
582        TypePath {
583            qself: Some(QSelf {
584                lt_token: syn::token::Lt { spans: [span] },
585                ty: Box::new(of_ty),
586                position: 2,
587                as_token: Some(syn::token::As { span }),
588                gt_token: syn::token::Gt { spans: [span] },
589            }),
590            path: Path {
591                leading_colon: Some(syn::token::PathSep {
592                    spans: [span, span],
593                }),
594                segments: [
595                    PathSegment {
596                        ident: Ident::new("xso", span),
597                        arguments: PathArguments::None,
598                    },
599                    PathSegment {
600                        ident: Ident::new("AsXml", span),
601                        arguments: PathArguments::None,
602                    },
603                ]
604                .into_iter()
605                .collect(),
606            },
607        },
608    )
609}
610
611/// Construct a [`syn::Expr`] referring to
612/// `<#of_ty as ::xso::AsXml>::as_xml_iter`.
613pub(crate) fn as_xml_iter_fn(of_ty: Type) -> Expr {
614    let (span, mut ty) = as_xml_of(of_ty);
615    ty.path.segments.push(PathSegment {
616        ident: Ident::new("as_xml_iter", span),
617        arguments: PathArguments::None,
618    });
619    Expr::Path(ExprPath {
620        attrs: Vec::new(),
621        qself: ty.qself,
622        path: ty.path,
623    })
624}
625
626/// Construct a [`syn::Type`] referring to
627/// `<#of_ty as ::xso::AsXml>::ItemIter`.
628pub(crate) fn item_iter_ty(of_ty: Type, lifetime: Lifetime) -> Type {
629    let (span, mut ty) = as_xml_of(of_ty);
630    ty.path.segments.push(PathSegment {
631        ident: Ident::new("ItemIter", span),
632        arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
633            colon2_token: None,
634            lt_token: token::Lt { spans: [span] },
635            args: [GenericArgument::Lifetime(lifetime)].into_iter().collect(),
636            gt_token: token::Gt { spans: [span] },
637        }),
638    });
639    Type::Path(ty)
640}
641
642/// Construct a [`syn::TypePath`] referring to `<#of_ty as IntoIterator>`.
643fn into_iterator_of(of_ty: Type) -> (Span, TypePath) {
644    let span = of_ty.span();
645    (
646        span,
647        TypePath {
648            qself: Some(QSelf {
649                lt_token: syn::token::Lt { spans: [span] },
650                ty: Box::new(of_ty),
651                position: 3,
652                as_token: Some(syn::token::As { span }),
653                gt_token: syn::token::Gt { spans: [span] },
654            }),
655            path: Path {
656                leading_colon: Some(syn::token::PathSep {
657                    spans: [span, span],
658                }),
659                segments: [
660                    PathSegment {
661                        ident: Ident::new("core", span),
662                        arguments: PathArguments::None,
663                    },
664                    PathSegment {
665                        ident: Ident::new("iter", span),
666                        arguments: PathArguments::None,
667                    },
668                    PathSegment {
669                        ident: Ident::new("IntoIterator", span),
670                        arguments: PathArguments::None,
671                    },
672                ]
673                .into_iter()
674                .collect(),
675            },
676        },
677    )
678}
679
680/// Construct a [`syn::Type`] referring to
681/// `<#of_ty as IntoIterator>::IntoIter`.
682pub(crate) fn into_iterator_iter_ty(of_ty: Type) -> Type {
683    let (span, mut ty) = into_iterator_of(of_ty);
684    ty.path.segments.push(PathSegment {
685        ident: Ident::new("IntoIter", span),
686        arguments: PathArguments::None,
687    });
688    Type::Path(ty)
689}
690
691/// Construct a [`syn::Type`] referring to
692/// `<#of_ty as IntoIterator>::Item`.
693pub(crate) fn into_iterator_item_ty(of_ty: Type) -> Type {
694    let (span, mut ty) = into_iterator_of(of_ty);
695    ty.path.segments.push(PathSegment {
696        ident: Ident::new("Item", span),
697        arguments: PathArguments::None,
698    });
699    Type::Path(ty)
700}
701
702/// Construct a [`syn::Expr`] referring to
703/// `<#of_ty as IntoIterator>::into_iter`.
704pub(crate) fn into_iterator_into_iter_fn(of_ty: Type) -> Expr {
705    let (span, mut ty) = into_iterator_of(of_ty);
706    ty.path.segments.push(PathSegment {
707        ident: Ident::new("into_iter", span),
708        arguments: PathArguments::None,
709    });
710    Expr::Path(ExprPath {
711        attrs: Vec::new(),
712        qself: ty.qself,
713        path: ty.path,
714    })
715}
716
717/// Construct a [`syn::Expr`] referring to
718/// `<#of_ty as ::core::iter::Extend>::extend`.
719pub(crate) fn extend_fn(of_ty: Type, item_ty: Type) -> Expr {
720    let span = of_ty.span();
721    Expr::Path(ExprPath {
722        attrs: Vec::new(),
723        qself: Some(QSelf {
724            lt_token: syn::token::Lt { spans: [span] },
725            ty: Box::new(of_ty),
726            position: 3,
727            as_token: Some(syn::token::As { span }),
728            gt_token: syn::token::Gt { spans: [span] },
729        }),
730        path: Path {
731            leading_colon: Some(syn::token::PathSep {
732                spans: [span, span],
733            }),
734            segments: [
735                PathSegment {
736                    ident: Ident::new("core", span),
737                    arguments: PathArguments::None,
738                },
739                PathSegment {
740                    ident: Ident::new("iter", span),
741                    arguments: PathArguments::None,
742                },
743                PathSegment {
744                    ident: Ident::new("Extend", span),
745                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
746                        colon2_token: Some(syn::token::PathSep {
747                            spans: [span, span],
748                        }),
749                        lt_token: syn::token::Lt { spans: [span] },
750                        args: [GenericArgument::Type(item_ty)].into_iter().collect(),
751                        gt_token: syn::token::Gt { spans: [span] },
752                    }),
753                },
754                PathSegment {
755                    ident: Ident::new("extend", span),
756                    arguments: PathArguments::None,
757                },
758            ]
759            .into_iter()
760            .collect(),
761        },
762    })
763}
764
765/// Construct a [`syn::TypePath`] which references the given type name.
766pub(crate) fn ty_from_ident(ident: Ident) -> TypePath {
767    TypePath {
768        qself: None,
769        path: ident.into(),
770    }
771}
772
773/// Construct a [`syn::Type`] referring to `xso::OptionAsXml<#inner_ty>`.
774pub(crate) fn option_as_xml_ty(inner_ty: Type) -> Type {
775    let span = inner_ty.span();
776    Type::Path(TypePath {
777        qself: None,
778        path: Path {
779            leading_colon: Some(syn::token::PathSep {
780                spans: [span, span],
781            }),
782            segments: [
783                PathSegment {
784                    ident: Ident::new("xso", span),
785                    arguments: PathArguments::None,
786                },
787                PathSegment {
788                    ident: Ident::new("asxml", span),
789                    arguments: PathArguments::None,
790                },
791                PathSegment {
792                    ident: Ident::new("OptionAsXml", span),
793                    arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
794                        colon2_token: None,
795                        lt_token: token::Lt { spans: [span] },
796                        args: [GenericArgument::Type(inner_ty)].into_iter().collect(),
797                        gt_token: token::Gt { spans: [span] },
798                    }),
799                },
800            ]
801            .into_iter()
802            .collect(),
803        },
804    })
805}
806
807/// Construct a [`syn::Type`] referring to `::xso::exports::minidom::Element`.
808#[cfg(feature = "minidom")]
809pub(crate) fn element_ty(span: Span) -> Type {
810    Type::Path(TypePath {
811        qself: None,
812        path: Path {
813            leading_colon: Some(syn::token::PathSep {
814                spans: [span, span],
815            }),
816            segments: [
817                PathSegment {
818                    ident: Ident::new("xso", span),
819                    arguments: PathArguments::None,
820                },
821                PathSegment {
822                    ident: Ident::new("exports", span),
823                    arguments: PathArguments::None,
824                },
825                PathSegment {
826                    ident: Ident::new("minidom", span),
827                    arguments: PathArguments::None,
828                },
829                PathSegment {
830                    ident: Ident::new("Element", span),
831                    arguments: PathArguments::None,
832                },
833            ]
834            .into_iter()
835            .collect(),
836        },
837    })
838}
839
840/// Construct a [`syn::Path`] referring to `::xso::UnknownAttributePolicy`.
841pub(crate) fn unknown_attribute_policy_path(span: Span) -> Path {
842    Path {
843        leading_colon: Some(syn::token::PathSep {
844            spans: [span, span],
845        }),
846        segments: [
847            PathSegment {
848                ident: Ident::new("xso", span),
849                arguments: PathArguments::None,
850            },
851            PathSegment {
852                ident: Ident::new("UnknownAttributePolicy", span),
853                arguments: PathArguments::None,
854            },
855        ]
856        .into_iter()
857        .collect(),
858    }
859}
860
861/// Construct a [`syn::Path`] referring to `::xso::UnknownChildPolicy`.
862pub(crate) fn unknown_child_policy_path(span: Span) -> Path {
863    Path {
864        leading_colon: Some(syn::token::PathSep {
865            spans: [span, span],
866        }),
867        segments: [
868            PathSegment {
869                ident: Ident::new("xso", span),
870                arguments: PathArguments::None,
871            },
872            PathSegment {
873                ident: Ident::new("UnknownChildPolicy", span),
874                arguments: PathArguments::None,
875            },
876        ]
877        .into_iter()
878        .collect(),
879    }
880}
881
882/// Construct a [`syn::Type`] referring to `::xso::fromxml::Discard`.
883pub(crate) fn discard_builder_ty(span: Span) -> Type {
884    Type::Path(TypePath {
885        qself: None,
886        path: Path {
887            leading_colon: Some(syn::token::PathSep {
888                spans: [span, span],
889            }),
890            segments: [
891                PathSegment {
892                    ident: Ident::new("xso", span),
893                    arguments: PathArguments::None,
894                },
895                PathSegment {
896                    ident: Ident::new("fromxml", span),
897                    arguments: PathArguments::None,
898                },
899                PathSegment {
900                    ident: Ident::new("Discard", span),
901                    arguments: PathArguments::None,
902                },
903            ]
904            .into_iter()
905            .collect(),
906        },
907    })
908}
909
910/// Construct a [`syn::Type`] referring to the built-in `bool` type.
911///
912/// Note that we go through `xso::exports::CoreBool` for that, because there seems
913/// to be no way to access built-in types once they have been shadowed in a
914/// scope.
915pub(crate) fn bool_ty(span: Span) -> Type {
916    Type::Path(TypePath {
917        qself: None,
918        path: Path {
919            leading_colon: Some(syn::token::PathSep {
920                spans: [span, span],
921            }),
922            segments: [
923                PathSegment {
924                    ident: Ident::new("xso", span),
925                    arguments: PathArguments::None,
926                },
927                PathSegment {
928                    ident: Ident::new("exports", span),
929                    arguments: PathArguments::None,
930                },
931                PathSegment {
932                    ident: Ident::new("CoreBool", span),
933                    arguments: PathArguments::None,
934                },
935            ]
936            .into_iter()
937            .collect(),
938        },
939    })
940}
941
942/// Construct a [`syn::Type`] referring to the built-in `u8` type.
943///
944/// Note that we go through `xso::exports::CoreU8` for that, because there seems
945/// to be no way to access built-in types once they have been shadowed in a
946/// scope.
947pub(crate) fn u8_ty(span: Span) -> Type {
948    Type::Path(TypePath {
949        qself: None,
950        path: Path {
951            leading_colon: Some(syn::token::PathSep {
952                spans: [span, span],
953            }),
954            segments: [
955                PathSegment {
956                    ident: Ident::new("xso", span),
957                    arguments: PathArguments::None,
958                },
959                PathSegment {
960                    ident: Ident::new("exports", span),
961                    arguments: PathArguments::None,
962                },
963                PathSegment {
964                    ident: Ident::new("CoreU8", span),
965                    arguments: PathArguments::None,
966                },
967            ]
968            .into_iter()
969            .collect(),
970        },
971    })
972}
973
974/// Construct a [`syn::Type`] referring to `::xso::fromxml::EmptyBuilder`.
975pub(crate) fn empty_builder_ty(span: Span) -> Type {
976    Type::Path(TypePath {
977        qself: None,
978        path: Path {
979            leading_colon: Some(syn::token::PathSep {
980                spans: [span, span],
981            }),
982            segments: [
983                PathSegment {
984                    ident: Ident::new("xso", span),
985                    arguments: PathArguments::None,
986                },
987                PathSegment {
988                    ident: Ident::new("fromxml", span),
989                    arguments: PathArguments::None,
990                },
991                PathSegment {
992                    ident: Ident::new("EmptyBuilder", span),
993                    arguments: PathArguments::None,
994                },
995            ]
996            .into_iter()
997            .collect(),
998        },
999    })
1000}