1use std::borrow::Cow;
2use std::collections::BTreeMap;
3
4use proc_macro2::{Span, TokenStream};
5use syn::parse::{Parse, ParseStream};
6use syn::spanned::Spanned;
7
8use crate::internals::attr::{self, ModeIdent, ModeKind, TypeAttr};
9use crate::internals::{Build, Ctxt, Expansion, Mode, NameAll, Only, Parameters, Result, Tokens};
10
11#[derive(Clone, Copy)]
12pub(crate) enum UnsizedMethod {
13 Default,
14 Bytes,
15}
16
17impl UnsizedMethod {
18 pub(crate) fn as_method_name(&self) -> syn::Ident {
20 match self {
21 Self::Default => syn::Ident::new("decode_unsized", Span::call_site()),
22 Self::Bytes => syn::Ident::new("decode_unsized_bytes", Span::call_site()),
23 }
24 }
25}
26
27pub(crate) struct Name<'a, T> {
28 pub(crate) span: Option<Span>,
29 pub(crate) value: &'a T,
30 pub(crate) ty: syn::Type,
31 pub(crate) method: NameMethod,
32 pub(crate) format_with: Option<&'a (Span, syn::Path)>,
33}
34
35impl<T> Name<'_, T> {
36 pub(crate) fn expr(&self, ident: syn::Ident) -> syn::Expr {
37 match self.method {
38 NameMethod::Unsized(..) => syn::parse_quote!(#ident),
39 NameMethod::Sized => syn::parse_quote!(&#ident),
40 }
41 }
42
43 pub(crate) fn ty(&self) -> Cow<'_, syn::Type> {
44 match self.method {
45 NameMethod::Unsized(..) => {
46 let ty = &self.ty;
47 Cow::Owned(syn::parse_quote!(&#ty))
48 }
49 NameMethod::Sized => Cow::Borrowed(&self.ty),
50 }
51 }
52
53 pub(crate) fn name_format(&self, value: &syn::Ident) -> syn::Expr {
54 match self.format_with {
55 Some((_, path)) => syn::parse_quote!(#path(&#value)),
56 None => syn::parse_quote!(&#value),
57 }
58 }
59}
60
61#[derive(Default, Clone, Copy)]
62pub(crate) enum NameMethod {
63 #[default]
65 Sized,
66 Unsized(UnsizedMethod),
68}
69
70impl NameMethod {
71 pub(crate) fn name_all(&self) -> Option<NameAll> {
72 match self {
73 Self::Sized => None,
74 Self::Unsized(_) => Some(NameAll::Name),
75 }
76 }
77}
78
79impl Parse for NameMethod {
80 fn parse(input: ParseStream<'_>) -> Result<Self, syn::Error> {
81 let string: syn::LitStr = input.parse()?;
82 let s = string.value();
83
84 match s.as_str() {
85 "sized" => Ok(Self::Sized),
86 "unsized" => Ok(Self::Unsized(UnsizedMethod::Default)),
87 "unsized_bytes" => Ok(Self::Unsized(UnsizedMethod::Bytes)),
88 _ => Err(syn::Error::new_spanned(
89 string,
90 "#[musli(name(method = ..))]: Bad value, expected one of \"value\", \"unsized\", \"unsized_bytes\"",
91 )),
92 }
93 }
94}
95
96pub(crate) struct FieldData<'a> {
97 pub(crate) span: Span,
98 pub(crate) index: usize,
99 pub(crate) attr: attr::Field,
100 pub(crate) ident: Option<&'a syn::Ident>,
101 pub(crate) ty: &'a syn::Type,
102}
103
104pub(crate) struct StructData<'a> {
105 pub(crate) name: syn::LitStr,
106 pub(crate) fields: Vec<FieldData<'a>>,
107 pub(crate) kind: StructKind,
108}
109
110pub(crate) struct VariantData<'a> {
111 pub(crate) span: Span,
112 pub(crate) name: syn::LitStr,
113 pub(crate) index: usize,
114 pub(crate) attr: attr::VariantAttr,
115 pub(crate) ident: &'a syn::Ident,
116 pub(crate) fields: Vec<FieldData<'a>>,
117 pub(crate) kind: StructKind,
118}
119
120#[derive(Debug, Clone, Copy)]
121pub(crate) enum StructKind {
122 Indexed(usize),
123 Named,
124 Empty,
125}
126
127pub(crate) struct EnumData<'a> {
128 pub(crate) name: syn::LitStr,
129 pub(crate) variants: Vec<VariantData<'a>>,
130}
131
132pub(crate) enum Data<'a> {
133 Struct(StructData<'a>),
134 Enum(EnumData<'a>),
135 Union,
136}
137
138pub(crate) struct Expander<'a> {
139 pub(crate) input: &'a syn::DeriveInput,
140 pub(crate) cx: Ctxt,
141 pub(crate) type_attr: TypeAttr,
142 pub(crate) data: Data<'a>,
143 pub(crate) prefix: syn::Path,
144 pub(crate) default: Vec<ModeIdent>,
145}
146
147impl<'a> Expander<'a> {
148 pub(crate) fn new(input: &'a syn::DeriveInput, default_crate: &str) -> Self {
149 fn fields<'a>(cx: &Ctxt, fields: &'a syn::Fields) -> Vec<FieldData<'a>> {
150 fields
151 .iter()
152 .enumerate()
153 .map(|(index, field)| FieldData {
154 span: field.span(),
155 index,
156 attr: attr::field_attrs(cx, &field.attrs),
157 ident: field.ident.as_ref(),
158 ty: &field.ty,
159 })
160 .collect()
161 }
162
163 let cx = Ctxt::new();
164 let type_attr = attr::type_attrs(&cx, &input.attrs);
165
166 let data = match &input.data {
167 syn::Data::Struct(st) => Data::Struct(StructData {
168 name: syn::LitStr::new(&input.ident.to_string(), input.ident.span()),
169 fields: fields(&cx, &st.fields),
170 kind: match &st.fields {
171 syn::Fields::Unit => StructKind::Empty,
172 syn::Fields::Unnamed(f) => StructKind::Indexed(f.unnamed.len()),
173 syn::Fields::Named(..) => StructKind::Named,
174 },
175 }),
176 syn::Data::Enum(en) => {
177 let variants = en
178 .variants
179 .iter()
180 .enumerate()
181 .map(|(index, variant)| VariantData {
182 span: variant.span(),
183 index,
184 name: syn::LitStr::new(&variant.ident.to_string(), variant.ident.span()),
185 attr: attr::variant_attrs(&cx, &variant.attrs),
186 ident: &variant.ident,
187 fields: fields(&cx, &variant.fields),
188 kind: match &variant.fields {
189 syn::Fields::Unit => StructKind::Empty,
190 syn::Fields::Unnamed(f) => StructKind::Indexed(f.unnamed.len()),
191 syn::Fields::Named(..) => StructKind::Named,
192 },
193 });
194
195 Data::Enum(EnumData {
196 name: syn::LitStr::new(&input.ident.to_string(), input.ident.span()),
197 variants: variants.collect(),
198 })
199 }
200 syn::Data::Union(..) => Data::Union,
201 };
202
203 let prefix = type_attr.crate_or_default(default_crate);
204
205 let default = vec![
206 ModeIdent {
207 kind: ModeKind::Binary,
208 path: syn::Path::from(syn::PathSegment::from(syn::Ident::new(
209 "Binary",
210 Span::call_site(),
211 ))),
212 },
213 ModeIdent {
214 kind: ModeKind::Text,
215 path: syn::Path::from(syn::PathSegment::from(syn::Ident::new(
216 "Text",
217 Span::call_site(),
218 ))),
219 },
220 ];
221
222 Self {
223 input,
224 cx,
225 type_attr,
226 data,
227 prefix,
228 default,
229 }
230 }
231
232 pub(crate) fn tokens(&self) -> Tokens<'_> {
233 Tokens::new(&self.prefix)
234 }
235
236 pub(crate) fn into_errors(self) -> Vec<syn::Error> {
238 self.cx.into_errors()
239 }
240
241 fn setup_builds<'b>(
242 &'b self,
243 modes: &'b [ModeIdent],
244 tokens: &'b Tokens<'b>,
245 only: Only,
246 ) -> Result<Vec<Build<'b>>> {
247 let mut builds = Vec::new();
248
249 let mut missing = BTreeMap::new();
250
251 for default in &self.default {
252 missing.insert(&default.kind, default);
253 }
254
255 let (lt, lt_exists) = 'out: {
256 if let Some(lt) = self.input.generics.lifetimes().next() {
257 break 'out (lt.lifetime.clone(), true);
258 }
259
260 (syn::Lifetime::new("'__de", Span::call_site()), false)
261 };
262
263 let (allocator_ident, allocator_exists) = 'out: {
264 for p in self.input.generics.type_params() {
265 if p.ident == "A" {
266 break 'out (p.ident.clone(), true);
267 }
268 }
269
270 (
271 self.cx.type_with_span_permanent("__A", Span::call_site()),
272 false,
273 )
274 };
275
276 let p = Parameters {
277 lt,
278 lt_exists,
279 allocator_ident,
280 allocator_exists,
281 };
282
283 for mode_ident in modes {
284 missing.remove(&mode_ident.kind);
285
286 let expansion = Expansion { mode_ident };
287
288 let mode = expansion.as_mode(tokens, only);
289 let p = self.decorate(&p, &mode);
290
291 builds.push(crate::internals::build::setup(
292 self, expansion, mode, tokens, p,
293 )?);
294 }
295
296 for (_, mode_ident) in missing {
297 let expansion = Expansion { mode_ident };
298
299 let mode = expansion.as_mode(tokens, only);
300 let p = self.decorate(&p, &mode);
301
302 builds.push(crate::internals::build::setup(
303 self, expansion, mode, tokens, p,
304 )?);
305 }
306
307 Ok(builds)
308 }
309
310 fn decorate(&self, p: &Parameters, mode: &Mode<'_>) -> Parameters {
311 let (lt, lt_exists) = 'out: {
312 let list = self.type_attr.decode_bounds_lifetimes(mode);
313
314 if let [_, rest @ ..] = list {
315 for &(span, _) in rest {
316 self.cx
317 .error_span(span, "More than one decoder lifetime bound is specified");
318 }
319 }
320
321 if let Some((_, ty)) = list.first() {
322 break 'out (ty, false);
323 }
324
325 (&p.lt, p.lt_exists)
326 };
327
328 let (allocator_ident, allocator_exists) = 'out: {
329 let list = self.type_attr.decode_bounds_types(mode);
330
331 if let [_, rest @ ..] = list {
332 for &(span, _) in rest {
333 self.cx
334 .error_span(span, "More than one decoder allocator bound is specified");
335 }
336 }
337
338 if let Some((_, ty)) = list.first() {
339 break 'out (ty, false);
340 }
341
342 (&p.allocator_ident, p.allocator_exists)
343 };
344
345 Parameters {
346 lt: lt.clone(),
347 lt_exists,
348 allocator_ident: allocator_ident.clone(),
349 allocator_exists,
350 }
351 }
352
353 pub(crate) fn expand_encode(&self) -> Result<TokenStream> {
355 let modes = self.cx.modes();
356 let tokens = self.tokens();
357 let builds = self.setup_builds(&modes, &tokens, Only::Encode)?;
358
359 let mut out = TokenStream::new();
360
361 for build in builds {
362 out.extend(crate::en::expand_encode_entry(&build)?);
363 }
364
365 Ok(out)
366 }
367
368 pub(crate) fn expand_decode(&self) -> Result<TokenStream> {
370 let modes = self.cx.modes();
371 let tokens = self.tokens();
372 let builds = self.setup_builds(&modes, &tokens, Only::Decode)?;
373
374 let mut out = TokenStream::new();
375
376 for build in builds {
377 out.extend(crate::de::expand_decode_entry(&build)?);
378 }
379
380 Ok(out)
381 }
382}
383
384pub(crate) trait Taggable {
386 fn span(&self) -> Span;
388 fn name(&self, mode: &Mode<'_>) -> Option<&(Span, syn::Expr)>;
390 fn index(&self) -> usize;
392}
393
394pub(crate) fn expand_name(
396 taggable: &dyn Taggable,
397 mode: &Mode<'_>,
398 name_all: NameAll,
399 ident: Option<&syn::Ident>,
400) -> (syn::Expr, Option<Span>) {
401 let lit = 'out: {
402 if let Some(&(span, ref rename)) = taggable.name(mode) {
403 return (rename.clone(), Some(span));
404 }
405
406 if let (Some(ident), name_all) = (ident, name_all) {
407 let ident = ident.to_string();
408 let ident = ident.trim_start_matches("r#");
409
410 if let Some(name) = name_all.apply(ident) {
411 break 'out syn::LitStr::new(&name, ident.span()).into();
412 }
413 }
414
415 usize_suffixed(taggable.index(), taggable.span()).into()
416 };
417
418 let expr = syn::Expr::Lit(syn::ExprLit {
419 attrs: Vec::new(),
420 lit,
421 });
422
423 (expr, None)
424}
425
426pub(crate) fn usize_suffixed(index: usize, span: Span) -> syn::LitInt {
429 syn::LitInt::new(&format!("{index}usize"), span)
430}
431
432impl Taggable for FieldData<'_> {
433 fn span(&self) -> Span {
434 self.span
435 }
436
437 fn name(&self, mode: &Mode<'_>) -> Option<&(Span, syn::Expr)> {
438 self.attr.name(mode)
439 }
440
441 fn index(&self) -> usize {
442 self.index
443 }
444}
445
446impl Taggable for VariantData<'_> {
447 fn span(&self) -> Span {
448 self.span
449 }
450
451 fn name(&self, mode: &Mode<'_>) -> Option<&(Span, syn::Expr)> {
452 self.attr.name_expr(mode)
453 }
454
455 fn index(&self) -> usize {
456 self.index
457 }
458}