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}