1#![warn(
4 clippy::all,
5 clippy::pedantic,
6 clippy::perf,
7 clippy::style,
8 clippy::disallowed_types,
9 clippy::indexing_slicing,
10 clippy::clone_on_ref_ptr,
11 clippy::create_dir,
12 clippy::default_numeric_fallback,
13 clippy::empty_drop,
14 clippy::empty_structs_with_brackets,
15 clippy::unwrap_used,
16 clippy::expect_used,
17 clippy::float_equality_without_abs,
18 clippy::float_cmp,
19 clippy::float_cmp_const,
20 clippy::format_push_string,
21 clippy::get_unwrap,
22 clippy::if_then_some_else_none,
23 clippy::impl_trait_in_params,
24 clippy::mixed_read_write_in_expression,
25 clippy::mod_module_files,
26 clippy::multiple_unsafe_ops_per_block,
27 clippy::undocumented_unsafe_blocks,
28 clippy::partial_pub_fields,
29 clippy::panic,
30 clippy::semicolon_if_nothing_returned,
31 clippy::semicolon_inside_block,
32 clippy::str_to_string,
33 clippy::todo,
34 clippy::try_err,
35 clippy::unneeded_field_pattern,
36 clippy::unseparated_literal_suffix,
37 clippy::fallible_impl_from,
38 clippy::future_not_send,
39 clippy::option_if_let_else,
40 clippy::or_fun_call,
41 clippy::path_buf_push_overwrite,
42 clippy::redundant_pub_crate,
43 clippy::redundant_allocation,
44 clippy::significant_drop_tightening,
45 clippy::useless_let_if_seq,
46 rustdoc::all,
47 missing_copy_implementations,
48 missing_debug_implementations,
49 missing_docs
50)]
51
52use std::fmt;
53
54use proc_macro2::{Ident, TokenStream};
55use quote::{format_ident, quote, quote_spanned};
56use syn::{spanned::Spanned, FnArg, ItemFn, Type, TypeReference};
57
58mod condition;
59mod from_byte_reader;
60mod size_query;
61mod vec_len_query;
62
63#[must_use]
65pub fn derive_from_byte_reader(item: TokenStream) -> TokenStream {
66 let ast = parse_as!(item as syn::DeriveInput);
67 from_byte_reader::impl_trait(&ast).unwrap_or_else(syn::Error::into_compile_error)
68}
69
70#[must_use]
72pub fn byte_size_query(attr: TokenStream, item: TokenStream) -> TokenStream {
73 let name = parse_as!(attr as Ident);
74 let body = parse_as!(item as ItemFn);
75
76 let gen_trait = simplify_result(size_query::generate_impl(&name, &body));
77
78 quote! {
79 #body
80 #gen_trait
81 }
82}
83
84#[must_use]
86pub fn condition(attr: TokenStream, item: TokenStream) -> TokenStream {
87 let name = parse_as!(attr as Ident);
88 let body = parse_as!(item as ItemFn);
89
90 let gen_trait = simplify_result(condition::generate_impl(&name, &body));
91
92 quote! {
93 #body
94 #gen_trait
95 }
96}
97
98#[must_use]
100pub fn vec_len_query(attr: TokenStream, item: TokenStream) -> TokenStream {
101 let name = parse_as!(attr as Ident);
102 let body = parse_as!(item as ItemFn);
103
104 let gen_trait = simplify_result(vec_len_query::generate_impl(&name, &body));
105
106 quote! {
107 #body
108 #gen_trait
109 }
110}
111
112fn simplify_result<T>(res: Result<T, T>) -> T {
113 match res {
114 Ok(t) | Err(t) => t,
115 }
116}
117
118fn dyn_mangle(ident: &Ident) -> Ident {
119 format_ident!("__dyn_barse_derive_i{ident}")
120}
121
122fn dyn_mangle_display<D>(disp: D) -> Ident
123where
124 D: fmt::Display,
125{
126 format_ident!("__dyn_disp_barse_derive_i{disp}")
127}
128
129fn static_mangle(ident: &str) -> Ident {
130 format_ident!("__static_barse_derive_i{ident}")
131}
132
133fn fn_name_and_type(body: &ItemFn) -> Result<(&Ident, &Type), proc_macro2::TokenStream> {
134 let fn_name = &body.sig.ident;
135
136 if !body.sig.generics.params.is_empty() {
137 let span = body.sig.generics.span();
138 return Err(quote_spanned! {
139 span=> compile_error!("annotated function can not have generic params or lifetimes")
140 });
141 }
142
143 if body.sig.inputs.len() != 1 {
144 let span = body.sig.inputs.span();
145 return Err(quote_spanned! {
146 span=> compile_error!("annotated function should have one and only have one parameter")
147 });
148 }
149
150 let Some(FnArg::Typed(flag_param)) = &body.sig.inputs.first() else {
151 let span = body.sig.inputs.span();
152 return Err(quote_spanned!{
153 span=> compile_error!("annotated function should have a non-self parameter")
154 });
155 };
156
157 let Type::Reference(TypeReference {
158 lifetime: None,
159 mutability: None,
160 elem: ty,
161 ..
162 }) = &*flag_param.ty else {
163 let span = flag_param.span();
164 return Err(quote_spanned!{
165 span=> compile_error!("annotaded function should have it's param be a immutable reference with no specified lifetime")
166 });
167 };
168
169 Ok((fn_name, ty))
170}
171
172macro_rules! parse_as {
173 ($e:path as $ty:ty) => {
174 match syn::parse2::<$ty>($e) {
175 Err(err) => return err.into_compile_error(),
176 Ok(val) => val,
177 }
178 };
179}
180use parse_as;