musli_macros/internals/
mode.rs
1use proc_macro2::Span;
4use syn::punctuated::Punctuated;
5use syn::spanned::Spanned;
6use syn::Token;
7
8use super::attr::{FieldEncoding, ModeKind};
9use super::tokens::Tokens;
10use super::Only;
11
12#[derive(Clone, Copy)]
13pub(crate) enum ModePath<'a> {
14 Ident(&'a syn::Ident),
15 Musli(&'a syn::Path, &'a syn::Ident),
16}
17
18impl ModePath<'_> {
19 pub(crate) fn as_path(self) -> syn::Path {
20 match self {
21 ModePath::Ident(ident) => syn::Path::from(ident.clone()),
22 ModePath::Musli(base, ident) => {
23 let mut path = base.clone();
24 path.segments.push(syn::PathSegment::from(syn::Ident::new(
25 "mode",
26 Span::call_site(),
27 )));
28 path.segments.push(syn::PathSegment::from(ident.clone()));
29 path
30 }
31 }
32 }
33}
34
35#[derive(Clone, Copy)]
36pub(crate) struct Mode<'a> {
37 pub(crate) kind: Option<&'a ModeKind>,
38 pub(crate) mode_path: ModePath<'a>,
39 pub(crate) tokens: &'a Tokens,
40 pub(crate) only: Only,
41}
42
43impl<'a> Mode<'a> {
44 pub(crate) fn encode_t_encode(&self, encoding: FieldEncoding) -> syn::Path {
46 let (mut encode_t, name) = match encoding {
47 FieldEncoding::Packed => (self.tokens.encode_packed_t.clone(), "encode_packed"),
48 FieldEncoding::Bytes => (self.tokens.encode_bytes_t.clone(), "encode_bytes"),
49 FieldEncoding::Trace => (self.tokens.trace_encode_t.clone(), "trace_encode"),
50 FieldEncoding::Default => (self.tokens.encode_t.clone(), "encode"),
51 };
52
53 if let Some(segment) = encode_t.segments.last_mut() {
54 add_mode_argument(&self.mode_path, segment);
55 }
56
57 encode_t
58 .segments
59 .push(syn::PathSegment::from(syn::Ident::new(
60 name,
61 encode_t.span(),
62 )));
63
64 encode_t
65 }
66
67 pub(crate) fn decode_t_decode(&self, encoding: FieldEncoding) -> syn::Path {
69 let (mut decode_t, name) = match encoding {
70 FieldEncoding::Packed => (self.tokens.decode_packed_t.clone(), "decode_packed"),
71 FieldEncoding::Bytes => (self.tokens.decode_bytes_t.clone(), "decode_bytes"),
72 FieldEncoding::Trace => (self.tokens.trace_decode_t.clone(), "trace_decode"),
73 FieldEncoding::Default => (self.tokens.decode_t.clone(), "decode"),
74 };
75
76 if let Some(segment) = decode_t.segments.last_mut() {
77 add_mode_argument(&self.mode_path, segment);
78 }
79
80 decode_t
81 .segments
82 .push(syn::PathSegment::from(syn::Ident::new(
83 name,
84 decode_t.span(),
85 )));
86
87 decode_t
88 }
89}
90
91fn add_mode_argument(moded_ident: &ModePath<'_>, last: &mut syn::PathSegment) {
92 let mut arguments = syn::AngleBracketedGenericArguments {
93 colon2_token: Some(<Token![::]>::default()),
94 lt_token: <Token![<]>::default(),
95 args: Punctuated::default(),
96 gt_token: <Token![>]>::default(),
97 };
98
99 arguments
100 .args
101 .push(syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
102 qself: None,
103 path: moded_ident.as_path(),
104 })));
105
106 last.arguments = syn::PathArguments::AngleBracketed(arguments);
107}