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}