musli_macros/
lib.rs
1#![allow(clippy::too_many_arguments)]
12#![allow(clippy::needless_late_init)]
13#![allow(missing_docs)]
14
15mod de;
16mod en;
17mod expander;
18mod internals;
19mod types;
20
21use proc_macro::TokenStream;
22
23const CRATE_DEFAULT: &str = "musli";
24
25#[proc_macro_derive(Encode, attributes(musli))]
43pub fn musli_derive_encode(input: TokenStream) -> TokenStream {
44 derive_encode(input, CRATE_DEFAULT)
45}
46
47#[proc_macro_derive(Decode, attributes(musli))]
65pub fn musli_derive_decode(input: TokenStream) -> TokenStream {
66 derive_decode(input, CRATE_DEFAULT)
67}
68
69fn derive_encode(input: TokenStream, crate_default: &str) -> TokenStream {
70 let input = syn::parse_macro_input!(input as syn::DeriveInput);
71 let expander = expander::Expander::new(&input, crate_default);
72
73 match expander.expand_encode() {
74 Ok(tokens) => tokens.into(),
75 Err(()) => to_compile_errors(expander.into_errors()).into(),
76 }
77}
78
79fn derive_decode(input: TokenStream, crate_default: &str) -> TokenStream {
80 let input = syn::parse_macro_input!(input as syn::DeriveInput);
81 let expander = expander::Expander::new(&input, crate_default);
82
83 match expander.expand_decode() {
84 Ok(tokens) => tokens.into(),
85 Err(()) => to_compile_errors(expander.into_errors()).into(),
86 }
87}
88
89#[proc_macro_attribute]
90pub fn decoder(attr: TokenStream, input: TokenStream) -> TokenStream {
91 let attr = syn::parse_macro_input!(attr as types::Attr);
92 let input = syn::parse_macro_input!(input as types::Types);
93
94 match input.expand(
95 CRATE_DEFAULT,
96 &attr,
97 "decoder",
98 types::DECODER_TYPES,
99 types::DECODER_FNS,
100 None,
101 "__UseMusliDecoderAttributeMacro",
102 types::Kind::SelfCx,
103 ) {
104 Ok(tokens) => tokens.into(),
105 Err(err) => err.to_compile_error().into(),
106 }
107}
108
109#[proc_macro_attribute]
110pub fn encoder(attr: TokenStream, input: TokenStream) -> TokenStream {
111 let attr = syn::parse_macro_input!(attr as types::Attr);
112 let input = syn::parse_macro_input!(input as types::Types);
113
114 match input.expand(
115 CRATE_DEFAULT,
116 &attr,
117 "encoder",
118 types::ENCODER_TYPES,
119 &[],
120 Some("Ok"),
121 "__UseMusliEncoderAttributeMacro",
122 types::Kind::SelfCx,
123 ) {
124 Ok(tokens) => tokens.into(),
125 Err(err) => err.to_compile_error().into(),
126 }
127}
128
129#[proc_macro_attribute]
130pub fn visitor(attr: TokenStream, input: TokenStream) -> TokenStream {
131 let attr = syn::parse_macro_input!(attr as types::Attr);
132 let input = syn::parse_macro_input!(input as types::Types);
133
134 match input.expand(
135 CRATE_DEFAULT,
136 &attr,
137 "visitor",
138 types::VISITOR_TYPES,
139 &[],
140 Some("Ok"),
141 "__UseMusliVisitorAttributeMacro",
142 types::Kind::GenericCx,
143 ) {
144 Ok(tokens) => tokens.into(),
145 Err(err) => err.to_compile_error().into(),
146 }
147}
148
149fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
150 let mut output = proc_macro2::TokenStream::new();
151
152 for e in errors {
153 output.extend(e.to_compile_error());
154 }
155
156 output
157}