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::QName`.
 13pub(crate) fn qname_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("QName", span),
 35                    arguments: PathArguments::None,
 36                },
 37            ]
 38            .into_iter()
 39            .collect(),
 40        },
 41    })
 42}
 43
 44/// Construct a [`syn::Expr`] referring to
 45/// `<#ty as ::xso::FromXmlText>::from_xml_text`.
 46pub(crate) fn from_xml_text_fn(ty: Type) -> Expr {
 47    let span = ty.span();
 48    Expr::Path(ExprPath {
 49        attrs: Vec::new(),
 50        qself: Some(QSelf {
 51            lt_token: syn::token::Lt { spans: [span] },
 52            ty: Box::new(ty),
 53            position: 2,
 54            as_token: Some(syn::token::As { span }),
 55            gt_token: syn::token::Gt { spans: [span] },
 56        }),
 57        path: Path {
 58            leading_colon: Some(syn::token::PathSep {
 59                spans: [span, span],
 60            }),
 61            segments: [
 62                PathSegment {
 63                    ident: Ident::new("xso", span),
 64                    arguments: PathArguments::None,
 65                },
 66                PathSegment {
 67                    ident: Ident::new("FromXmlText", span),
 68                    arguments: PathArguments::None,
 69                },
 70                PathSegment {
 71                    ident: Ident::new("from_xml_text", span),
 72                    arguments: PathArguments::None,
 73                },
 74            ]
 75            .into_iter()
 76            .collect(),
 77        },
 78    })
 79}
 80
 81/// Construct a [`syn::Expr`] referring to
 82/// `<#ty as ::xso::IntoOptionalXmlText>::into_optional_xml_text`.
 83pub(crate) fn into_optional_xml_text_fn(ty: Type) -> Expr {
 84    let span = ty.span();
 85    Expr::Path(ExprPath {
 86        attrs: Vec::new(),
 87        qself: Some(QSelf {
 88            lt_token: syn::token::Lt { spans: [span] },
 89            ty: Box::new(ty),
 90            position: 2,
 91            as_token: Some(syn::token::As { span }),
 92            gt_token: syn::token::Gt { spans: [span] },
 93        }),
 94        path: Path {
 95            leading_colon: Some(syn::token::PathSep {
 96                spans: [span, span],
 97            }),
 98            segments: [
 99                PathSegment {
100                    ident: Ident::new("xso", span),
101                    arguments: PathArguments::None,
102                },
103                PathSegment {
104                    ident: Ident::new("IntoOptionalXmlText", span),
105                    arguments: PathArguments::None,
106                },
107                PathSegment {
108                    ident: Ident::new("into_optional_xml_text", span),
109                    arguments: PathArguments::None,
110                },
111            ]
112            .into_iter()
113            .collect(),
114        },
115    })
116}
117
118/// Construct a [`syn::Expr`] referring to
119/// `<#of_ty as ::std::default::Default>::default`.
120pub(crate) fn default_fn(of_ty: Type) -> Expr {
121    let span = of_ty.span();
122    Expr::Path(ExprPath {
123        attrs: Vec::new(),
124        qself: Some(QSelf {
125            lt_token: syn::token::Lt { spans: [span] },
126            ty: Box::new(of_ty),
127            position: 3,
128            as_token: Some(syn::token::As { span }),
129            gt_token: syn::token::Gt { spans: [span] },
130        }),
131        path: Path {
132            leading_colon: Some(syn::token::PathSep {
133                spans: [span, span],
134            }),
135            segments: [
136                PathSegment {
137                    ident: Ident::new("std", span),
138                    arguments: PathArguments::None,
139                },
140                PathSegment {
141                    ident: Ident::new("default", span),
142                    arguments: PathArguments::None,
143                },
144                PathSegment {
145                    ident: Ident::new("Default", span),
146                    arguments: PathArguments::None,
147                },
148                PathSegment {
149                    ident: Ident::new("default", span),
150                    arguments: PathArguments::None,
151                },
152            ]
153            .into_iter()
154            .collect(),
155        },
156    })
157}
158
159/// Construct a [`syn::Type`] referring to `::std::string::String`.
160pub(crate) fn string_ty(span: Span) -> Type {
161    Type::Path(TypePath {
162        qself: None,
163        path: Path {
164            leading_colon: Some(syn::token::PathSep {
165                spans: [span, span],
166            }),
167            segments: [
168                PathSegment {
169                    ident: Ident::new("std", span),
170                    arguments: PathArguments::None,
171                },
172                PathSegment {
173                    ident: Ident::new("string", span),
174                    arguments: PathArguments::None,
175                },
176                PathSegment {
177                    ident: Ident::new("String", span),
178                    arguments: PathArguments::None,
179                },
180            ]
181            .into_iter()
182            .collect(),
183        },
184    })
185}
186
187/// Construct a [`syn::Expr`] referring to
188/// `<#ty as ::xso::IntoXmlText>::into_xml_text`.
189pub(crate) fn into_xml_text_fn(ty: Type) -> Expr {
190    let span = ty.span();
191    Expr::Path(ExprPath {
192        attrs: Vec::new(),
193        qself: Some(QSelf {
194            lt_token: syn::token::Lt { spans: [span] },
195            ty: Box::new(ty),
196            position: 2,
197            as_token: Some(syn::token::As { span }),
198            gt_token: syn::token::Gt { spans: [span] },
199        }),
200        path: Path {
201            leading_colon: Some(syn::token::PathSep {
202                spans: [span, span],
203            }),
204            segments: [
205                PathSegment {
206                    ident: Ident::new("xso", span),
207                    arguments: PathArguments::None,
208                },
209                PathSegment {
210                    ident: Ident::new("IntoXmlText", span),
211                    arguments: PathArguments::None,
212                },
213                PathSegment {
214                    ident: Ident::new("into_xml_text", span),
215                    arguments: PathArguments::None,
216                },
217            ]
218            .into_iter()
219            .collect(),
220        },
221    })
222}
223
224/// Construct a [`syn::TypePath`] referring to
225/// `<#codec_ty as ::xso::TextCodec::<#for_ty>>` and return the
226/// [`syn::Span`] of the `codec_ty` alongside it.
227fn text_codec_of(codec_ty: Type, for_ty: Type) -> (Span, TypePath) {
228    let span = codec_ty.span();
229    (
230        span,
231        TypePath {
232            qself: Some(QSelf {
233                lt_token: syn::token::Lt { spans: [span] },
234                ty: Box::new(codec_ty),
235                position: 2,
236                as_token: Some(syn::token::As { span }),
237                gt_token: syn::token::Gt { spans: [span] },
238            }),
239            path: Path {
240                leading_colon: Some(syn::token::PathSep {
241                    spans: [span, span],
242                }),
243                segments: [
244                    PathSegment {
245                        ident: Ident::new("xso", span),
246                        arguments: PathArguments::None,
247                    },
248                    PathSegment {
249                        ident: Ident::new("TextCodec", span),
250                        arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
251                            colon2_token: Some(syn::token::PathSep {
252                                spans: [span, span],
253                            }),
254                            lt_token: syn::token::Lt { spans: [span] },
255                            args: [GenericArgument::Type(for_ty)].into_iter().collect(),
256                            gt_token: syn::token::Gt { spans: [span] },
257                        }),
258                    },
259                ]
260                .into_iter()
261                .collect(),
262            },
263        },
264    )
265}
266
267/// Construct a [`syn::Expr`] referring to
268/// `<#codec_ty as ::xso::TextCodec::<#for_ty>>::encode`.
269pub(crate) fn text_codec_encode_fn(codec_ty: Type, for_ty: Type) -> Expr {
270    let (span, mut ty) = text_codec_of(codec_ty, for_ty);
271    ty.path.segments.push(PathSegment {
272        ident: Ident::new("encode", span),
273        arguments: PathArguments::None,
274    });
275    Expr::Path(ExprPath {
276        attrs: Vec::new(),
277        qself: ty.qself,
278        path: ty.path,
279    })
280}
281
282/// Construct a [`syn::Expr`] referring to
283/// `<#codec_ty as ::xso::TextCodec::<#for_ty>>::decode`.
284pub(crate) fn text_codec_decode_fn(codec_ty: Type, for_ty: Type) -> Expr {
285    let (span, mut ty) = text_codec_of(codec_ty, for_ty);
286    ty.path.segments.push(PathSegment {
287        ident: Ident::new("decode", span),
288        arguments: PathArguments::None,
289    });
290    Expr::Path(ExprPath {
291        attrs: Vec::new(),
292        qself: ty.qself,
293        path: ty.path,
294    })
295}