1#![allow(clippy::too_many_arguments)]
17#![allow(clippy::needless_late_init)]
18#![allow(clippy::type_complexity)]
19#![allow(missing_docs)]
20
21mod de;
22mod en;
23mod expander;
24mod internals;
25mod types;
26
27use proc_macro::TokenStream;
28
29const CRATE_DEFAULT: &str = "musli";
30
31#[proc_macro_derive(Encode, attributes(musli))]
32#[doc(hidden)]
33pub fn musli_derive_encode(input: TokenStream) -> TokenStream {
34 derive_encode(input, CRATE_DEFAULT)
35}
36
37#[proc_macro_derive(Decode, attributes(musli))]
38#[doc(hidden)]
39pub fn musli_derive_decode(input: TokenStream) -> TokenStream {
40 derive_decode(input, CRATE_DEFAULT)
41}
42
43fn derive_encode(input: TokenStream, crate_default: &str) -> TokenStream {
44 let input = syn::parse_macro_input!(input as syn::DeriveInput);
45 let expander = expander::Expander::new(&input, crate_default);
46
47 match expander.expand_encode() {
48 Ok(tokens) => tokens.into(),
49 Err(()) => to_compile_errors(expander.into_errors()).into(),
50 }
51}
52
53fn derive_decode(input: TokenStream, crate_default: &str) -> TokenStream {
54 let input = syn::parse_macro_input!(input as syn::DeriveInput);
55 let expander = expander::Expander::new(&input, crate_default);
56
57 match expander.expand_decode() {
58 Ok(tokens) => tokens.into(),
59 Err(()) => to_compile_errors(expander.into_errors()).into(),
60 }
61}
62
63#[proc_macro_attribute]
64#[doc(hidden)]
65pub fn decoder(attr: TokenStream, input: TokenStream) -> TokenStream {
66 let attr = syn::parse_macro_input!(attr as types::Attr);
67 let input = syn::parse_macro_input!(input as types::Types);
68
69 match input.expand(
70 CRATE_DEFAULT,
71 &attr,
72 "decoder",
73 types::DECODER_TYPES,
74 "__UseMusliDecoderAttributeMacro",
75 types::Kind::SelfCx,
76 ) {
77 Ok(tokens) => tokens.into(),
78 Err(err) => err.to_compile_error().into(),
79 }
80}
81
82#[proc_macro_attribute]
83#[doc(hidden)]
84pub fn encoder(attr: TokenStream, input: TokenStream) -> TokenStream {
85 let attr = syn::parse_macro_input!(attr as types::Attr);
86 let input = syn::parse_macro_input!(input as types::Types);
87
88 match input.expand(
89 CRATE_DEFAULT,
90 &attr,
91 "encoder",
92 types::ENCODER_TYPES,
93 "__UseMusliEncoderAttributeMacro",
94 types::Kind::SelfCx,
95 ) {
96 Ok(tokens) => tokens.into(),
97 Err(err) => err.to_compile_error().into(),
98 }
99}
100
101#[proc_macro_attribute]
102#[doc(hidden)]
103pub fn visitor(attr: TokenStream, input: TokenStream) -> TokenStream {
104 let attr = syn::parse_macro_input!(attr as types::Attr);
105 let input = syn::parse_macro_input!(input as types::Types);
106
107 match input.expand(
108 CRATE_DEFAULT,
109 &attr,
110 "visitor",
111 types::VISITOR_TYPES,
112 "__UseMusliVisitorAttributeMacro",
113 types::Kind::GenericCx,
114 ) {
115 Ok(tokens) => tokens.into(),
116 Err(err) => err.to_compile_error().into(),
117 }
118}
119
120#[proc_macro_attribute]
121#[doc(hidden)]
122pub fn unsized_visitor(attr: TokenStream, input: TokenStream) -> TokenStream {
123 let attr = syn::parse_macro_input!(attr as types::Attr);
124 let input = syn::parse_macro_input!(input as types::Types);
125
126 match input.expand(
127 CRATE_DEFAULT,
128 &attr,
129 "unsized visitor",
130 types::UNSIZED_VISITOR_TYPES,
131 "__UseMusliUnsizedVisitorAttributeMacro",
132 types::Kind::GenericCx,
133 ) {
134 Ok(tokens) => tokens.into(),
135 Err(err) => err.to_compile_error().into(),
136 }
137}
138
139fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
140 let mut output = proc_macro2::TokenStream::new();
141
142 for e in errors {
143 output.extend(e.to_compile_error());
144 }
145
146 output
147}