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}