1use std::collections::BTreeSet;
2
3use darling::ast::NestedMeta;
4#[allow(unused_imports)]
5use darling::{util::Override, Error as DarlingError, FromField, FromMeta, FromVariant};
6use proc_macro2::{Spacing, TokenTree};
7#[allow(unused_imports)]
8use proc_macro2::{Span, TokenStream};
9use quote::ToTokens;
10use syn::{parse::ParseStream, spanned::Spanned, DeriveInput, Lifetime, LitStr, Token, Type};
11
12#[derive(Debug, Clone, Copy, FromMeta)]
13pub struct DeriveArgs {
14 #[darling(default)]
15 pub(crate) vec: bool,
16 #[darling(rename = "map", default)]
17 pub(crate) hashmap: bool,
18 #[darling(default)]
19 pub(crate) ser: bool,
20 #[darling(default)]
21 pub(crate) de: bool,
22 #[darling(default)]
24 pub(crate) iterable: bool,
25}
26
27#[derive(FromField, Debug, Clone)]
28#[darling(attributes(columnar))]
29pub struct FieldArgs {
30 pub ident: Option<syn::Ident>,
32 pub ty: Type,
35 pub index: Option<usize>,
38 #[darling(default)]
40 pub optional: bool,
41 pub strategy: Option<String>,
43 pub class: Option<String>,
45 pub borrow: Option<Override<LitStr>>,
47 #[darling(default)]
49 pub skip: bool,
50 pub iter: Option<Type>,
51}
52
53#[derive(Debug, Clone, Copy)]
54pub enum Strategy {
55 Rle,
56 DeltaRle,
57 BoolRle,
58 DeltaOfDelta,
59 None,
60}
61
62impl Strategy {
63 fn from_str(s: Option<String>) -> Self {
64 if let Some(s) = s {
65 match s.as_str() {
66 "Rle" => Self::Rle,
67 "DeltaRle" => Self::DeltaRle,
68 "BoolRle" => Self::BoolRle,
69 "DeltaOfDelta" => Self::DeltaOfDelta,
70 _ => unreachable!("strategy should be Rle, BoolRle or DeltaRle"),
71 }
72 } else {
73 Self::None
74 }
75 }
76}
77
78pub enum AsType {
79 Vec,
80 Map,
81 Other,
82}
83
84pub trait Args {
85 fn ty(&self) -> Option<syn::Type>;
87 fn strategy(&self) -> Strategy;
90 fn can_copy(&self) -> bool {
91 match self.strategy() {
92 Strategy::BoolRle | Strategy::DeltaRle | Strategy::DeltaOfDelta => true,
93 Strategy::Rle | Strategy::None => false,
94 }
95 }
96 fn class(&self) -> Option<AsType>;
97 fn has_borrow_lifetime(&self) -> bool;
98 fn borrow_lifetimes(&self) -> syn::Result<Option<BTreeSet<Lifetime>>>;
99 fn self_lifetime(&self) -> syn::Result<BTreeSet<Lifetime>>;
100 fn lifetime(&self) -> syn::Result<BTreeSet<Lifetime>>;
101 fn get_strategy_column(&self, ty: TokenStream) -> syn::Result<proc_macro2::TokenStream> {
102 match self.strategy() {
103 Strategy::Rle => Ok(quote::quote!(::serde_columnar::RleColumn::<#ty>)),
104 Strategy::BoolRle => Ok(quote::quote!(::serde_columnar::BoolRleColumn)),
105 Strategy::DeltaRle => Ok(quote::quote!(::serde_columnar::DeltaRleColumn::<#ty>)),
106 Strategy::DeltaOfDelta => {
107 Ok(quote::quote!(::serde_columnar::DeltaOfDeltaColumn::<#ty>))
108 }
109 Strategy::None => {
110 if self.class().is_some() {
111 let self_ty = &self.ty();
112
113 let ans = match self.class().unwrap() {
114 AsType::Map => {
115 quote::quote!(::serde_columnar::GenericColumn::<::serde_columnar::ColumnarMap::<_, _, #self_ty>>)
116 }
117 AsType::Vec => {
118 quote::quote!(::serde_columnar::GenericColumn::<::serde_columnar::ColumnarVec::<_, #self_ty>>)
119 }
120 _ => unreachable!(),
121 };
122
123 Ok(ans)
124 } else {
125 Ok(quote::quote!(::serde_columnar::GenericColumn::<#ty>))
126 }
127 }
128 }
129 }
130}
131
132impl Args for FieldArgs {
133 fn ty(&self) -> Option<syn::Type> {
134 Some(self.ty.clone())
135 }
136
137 fn strategy(&self) -> Strategy {
138 Strategy::from_str(self.strategy.clone())
139 }
140
141 fn class(&self) -> Option<AsType> {
142 match self.class.as_deref() {
143 Some("vec") => Some(AsType::Vec),
144 Some("map") => Some(AsType::Map),
145 Some(_) => Some(AsType::Other),
146 None => None,
147 }
148 }
149
150 fn lifetime(&self) -> syn::Result<BTreeSet<Lifetime>> {
151 if self.has_borrow_lifetime() {
152 Ok(self.borrow_lifetimes()?.unwrap())
153 } else {
154 self.self_lifetime()
155 }
156 }
157
158 fn self_lifetime(&self) -> syn::Result<BTreeSet<Lifetime>> {
159 let mut lifetimes = BTreeSet::new();
160 collect_lifetimes(&self.ty, &mut lifetimes);
161
162 Ok(lifetimes)
163 }
164
165 fn borrow_lifetimes(&self) -> syn::Result<Option<BTreeSet<Lifetime>>> {
166 if self.borrow.is_none() {
167 return Ok(None);
168 }
169
170 match self.borrow.as_ref().unwrap() {
171 Override::Inherit => {
172 let mut lifetimes = BTreeSet::new();
173 collect_lifetimes(&self.ty, &mut lifetimes);
174
175 if lifetimes.is_empty() {
176 Err(syn::Error::new_spanned(
177 self.ty.clone().into_token_stream(),
178 "at least one lifetime must be borrowed",
179 ))
180 } else {
181 Ok(Some(lifetimes))
182 }
183 }
184 Override::Explicit(string) => {
185 if let Ok(lifetimes) = string.parse_with(|input: ParseStream| {
186 let mut set = BTreeSet::new();
187 while !input.is_empty() {
188 let lifetime: Lifetime = input.parse()?;
189 if !set.insert(lifetime.clone()) {
190 return Err(syn::Error::new_spanned(
191 string.clone().into_token_stream(),
192 format!("duplicate borrowed lifetime `{}`", lifetime),
193 ));
194 }
195 if input.is_empty() {
196 break;
197 }
198 input.parse::<Token![+]>()?;
199 }
200 Ok(set)
201 }) {
202 if lifetimes.is_empty() {
203 return Err(syn::Error::new_spanned(
204 string.clone().into_token_stream(),
205 "at least one lifetime must be borrowed",
206 ));
207 }
208
209 if let Ok(field_lifetimes) = self.self_lifetime() {
210 for l in &lifetimes {
211 if !field_lifetimes.contains(l) {
212 return Err(syn::Error::new(
213 self.ident.span(),
214 format!(
215 "field `{}` does not have lifetime {}",
216 self.ident.as_ref().unwrap(),
217 l,
218 ),
219 ));
220 }
221 }
222 }
223
224 Ok(Some(lifetimes))
225 } else {
226 Err(syn::Error::new_spanned(
227 string.clone().into_token_stream(),
228 format!("failed to parse borrowed lifetimes: {:?}", string.value()),
229 ))
230 }
231 }
232 }
233 }
234
235 fn has_borrow_lifetime(&self) -> bool {
236 self.borrow.is_some()
237 }
238}
239
240pub fn get_derive_args(args: &[NestedMeta]) -> syn::Result<DeriveArgs> {
241 match DeriveArgs::from_list(args) {
242 Ok(v) => Ok(v),
243 Err(e) => {
244 eprintln!("get_derive_args error: {}", e);
245 Err(DarlingError::unsupported_format(
246 "columnar only supports attributes with `vec`, `map` and `ser`, `de`",
247 )
248 .into())
249 }
250 }
251}
252
253pub fn parse_field_args(st: &mut DeriveInput) -> syn::Result<Option<Vec<FieldArgs>>> {
254 match &mut st.data {
255 syn::Data::Struct(syn::DataStruct {
256 fields: syn::Fields::Named(syn::FieldsNamed { named, .. }),
257 ..
258 }) => {
259 let mut args = Vec::with_capacity(named.len());
260 for field in named.iter() {
261 let field_args = FieldArgs::from_field(field)?;
262 args.push(field_args);
263 }
264 check_args_validate(&args)?;
265 Ok(Some(args))
266 }
267 syn::Data::Enum(syn::DataEnum { variants: _, .. }) => Err(syn::Error::new_spanned(
268 st,
269 "only supported named struct type",
270 )),
271 _ => Err(syn::Error::new_spanned(
272 st,
273 "only supported named struct type",
274 )),
275 }
276}
277
278pub fn check_args_validate(field_args: &[FieldArgs]) -> syn::Result<()> {
279 let mut start_optional = false;
281 let mut indexes = std::collections::HashSet::new();
282 for args in field_args {
283 let field_name = &args.ident;
284 let optional = args.optional;
285 let index = args.index;
286 if start_optional && !optional {
287 return Err(syn::Error::new_spanned(
288 field_name,
289 "optional field must be placed after non-optional field",
290 ));
291 }
292 if optional {
293 start_optional = true;
294 if index.is_none() {
295 return Err(syn::Error::new_spanned(
296 field_name,
297 "optional field must have index",
298 ));
299 }
300 if indexes.contains(&index.unwrap()) {
301 return Err(syn::Error::new_spanned(
302 field_name,
303 "index cannot have duplicate values",
304 ));
305 }
306 indexes.insert(index.unwrap());
307 };
308
309 let strategy = &args.strategy;
310 let class = &args.class;
311 if strategy.is_some() && class.is_some() {
312 return Err(syn::Error::new_spanned(
313 field_name,
314 "strategy and class cannot be set at the same time",
315 ));
316 }
317 }
318 Ok(())
319}
320
321fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
322 match ty {
323 syn::Type::Slice(ty) => {
324 collect_lifetimes(&ty.elem, out);
325 }
326 syn::Type::Array(ty) => {
327 collect_lifetimes(&ty.elem, out);
328 }
329 syn::Type::Ptr(ty) => {
330 collect_lifetimes(&ty.elem, out);
331 }
332 syn::Type::Reference(ty) => {
333 out.extend(ty.lifetime.iter().cloned());
334 collect_lifetimes(&ty.elem, out);
335 }
336 syn::Type::Tuple(ty) => {
337 for elem in &ty.elems {
338 collect_lifetimes(elem, out);
339 }
340 }
341 syn::Type::Path(ty) => {
342 if let Some(qself) = &ty.qself {
343 collect_lifetimes(&qself.ty, out);
344 }
345 for seg in &ty.path.segments {
346 if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments {
347 for arg in &bracketed.args {
348 match arg {
349 syn::GenericArgument::Lifetime(lifetime) => {
350 out.insert(lifetime.clone());
351 }
352 syn::GenericArgument::Type(ty) => {
353 collect_lifetimes(ty, out);
354 }
355 syn::GenericArgument::AssocType(binding) => {
356 collect_lifetimes(&binding.ty, out);
357 }
358 _ => {}
359 }
360 }
361 }
362 }
363 }
364 syn::Type::Paren(ty) => {
365 collect_lifetimes(&ty.elem, out);
366 }
367 syn::Type::Group(ty) => {
368 collect_lifetimes(&ty.elem, out);
369 }
370 syn::Type::Macro(ty) => {
371 collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out);
372 }
373 syn::Type::BareFn(_)
374 | syn::Type::Never(_)
375 | syn::Type::TraitObject(_)
376 | syn::Type::ImplTrait(_)
377 | syn::Type::Infer(_)
378 | syn::Type::Verbatim(_) => {}
379 _ => {}
380 }
381}
382fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Lifetime>) {
383 let mut iter = tokens.into_iter();
384 while let Some(tt) = iter.next() {
385 match &tt {
386 TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
387 if let Some(TokenTree::Ident(ident)) = iter.next() {
388 out.insert(syn::Lifetime {
389 apostrophe: op.span(),
390 ident,
391 });
392 }
393 }
394 TokenTree::Group(group) => {
395 let tokens = group.stream();
396 collect_lifetimes_from_tokens(tokens, out);
397 }
398 _ => {}
399 }
400 }
401}