Skip to content

Commit 3d05978

Browse files
authored
Update syn to 2.0 (#119)
1 parent 92d62c0 commit 3d05978

File tree

3 files changed

+105
-87
lines changed

3 files changed

+105
-87
lines changed

influxdb_derive/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ repository = "https://github.com/influxdb-rs/influxdb-rust"
1616
proc-macro = true
1717

1818
[dependencies]
19-
proc-macro2 = "1.0.9"
20-
quote = "1.0.3"
21-
syn = { version = "1.0.16", features = ["extra-traits", "full"] }
19+
proc-macro2 = "1.0"
20+
quote = "1.0"
21+
syn = { version = "2.0", features = ["extra-traits", "full"] }

influxdb_derive/src/lib.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
use proc_macro::TokenStream;
2-
use proc_macro2::TokenStream as TokenStream2;
3-
use quote::quote;
42

53
mod writeable;
4+
use syn::parse_macro_input;
65
use writeable::expand_writeable;
76

8-
fn krate() -> TokenStream2 {
9-
quote!(::influxdb)
10-
}
11-
127
#[proc_macro_derive(InfluxDbWriteable, attributes(influxdb))]
13-
pub fn derive_writeable(tokens: TokenStream) -> TokenStream {
14-
expand_writeable(tokens)
8+
pub fn derive_writeable(input: TokenStream) -> TokenStream {
9+
expand_writeable(parse_macro_input!(input))
10+
.unwrap_or_else(syn::Error::into_compile_error)
11+
.into()
1512
}

influxdb_derive/src/writeable.rs

Lines changed: 97 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
use proc_macro::TokenStream;
2-
use proc_macro2::{TokenStream as TokenStream2, TokenTree};
1+
use proc_macro2::TokenStream;
32
use quote::{format_ident, quote};
4-
use syn::{parse_macro_input, Field, Fields, Ident, ItemStruct};
3+
use std::convert::TryFrom;
4+
use syn::{
5+
parse::{Parse, ParseStream},
6+
punctuated::Punctuated,
7+
Data, DeriveInput, Field, Fields, Ident, Meta, Token,
8+
};
59

610
#[derive(Debug)]
711
struct WriteableField {
@@ -10,108 +14,125 @@ struct WriteableField {
1014
is_ignore: bool,
1115
}
1216

13-
impl From<Field> for WriteableField {
14-
fn from(field: Field) -> WriteableField {
15-
let ident = field.ident.expect("fields without ident are not supported");
17+
mod kw {
18+
use syn::custom_keyword;
1619

17-
let check_influx_aware = |attr: &syn::Attribute| -> bool {
18-
attr.path
19-
.segments
20-
.iter()
21-
.last()
22-
.map(|seg| seg.ident.to_string())
23-
.unwrap_or_default()
24-
== "influxdb"
25-
};
20+
custom_keyword!(tag);
21+
custom_keyword!(ignore);
22+
}
2623

27-
let check_for_attr = |token_tree, ident_cmp: &str| -> bool {
28-
match token_tree {
29-
TokenTree::Group(group) => group
30-
.stream()
31-
.into_iter()
32-
.next()
33-
.map(|token_tree| match token_tree {
34-
TokenTree::Ident(ident) => ident == ident_cmp,
35-
_ => false,
36-
})
37-
.unwrap(),
38-
_ => false,
39-
}
40-
};
24+
enum FieldAttr {
25+
Tag(kw::tag),
26+
Ignore(kw::ignore),
27+
}
4128

42-
let is_ignore = field.attrs.iter().any(|attr| {
43-
if !check_influx_aware(attr) {
44-
return false;
45-
}
29+
impl Parse for FieldAttr {
30+
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
31+
let lookahead = input.lookahead1();
32+
if lookahead.peek(kw::tag) {
33+
Ok(Self::Tag(input.parse()?))
34+
} else if lookahead.peek(kw::ignore) {
35+
Ok(Self::Ignore(input.parse()?))
36+
} else {
37+
Err(lookahead.error())
38+
}
39+
}
40+
}
41+
42+
struct FieldAttrs(Punctuated<FieldAttr, Token![,]>);
43+
44+
impl Parse for FieldAttrs {
45+
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
46+
Ok(Self(Punctuated::parse_terminated(input)?))
47+
}
48+
}
4649

47-
attr.tokens
48-
.clone()
49-
.into_iter()
50-
.next()
51-
.map(|token_tree| check_for_attr(token_tree, "ignore"))
52-
.unwrap()
53-
});
50+
impl TryFrom<Field> for WriteableField {
51+
type Error = syn::Error;
5452

55-
let is_tag = field.attrs.iter().any(|attr| {
56-
if !check_influx_aware(attr) {
57-
return false;
53+
fn try_from(field: Field) -> syn::Result<WriteableField> {
54+
let ident = field.ident.expect("fields without ident are not supported");
55+
let mut is_tag = false;
56+
let mut is_ignore = false;
57+
58+
for attr in field.attrs {
59+
match attr.meta {
60+
Meta::List(list) if list.path.is_ident("influxdb") => {
61+
for attr in syn::parse2::<FieldAttrs>(list.tokens)?.0 {
62+
match attr {
63+
FieldAttr::Tag(_) => is_tag = true,
64+
FieldAttr::Ignore(_) => is_ignore = true,
65+
}
66+
}
67+
}
68+
_ => {}
5869
}
59-
attr.tokens
60-
.clone()
61-
.into_iter()
62-
.next()
63-
.map(|token_tree| check_for_attr(token_tree, "tag"))
64-
.unwrap()
65-
});
70+
}
6671

67-
WriteableField {
72+
Ok(WriteableField {
6873
ident,
6974
is_tag,
7075
is_ignore,
71-
}
76+
})
7277
}
7378
}
7479

75-
pub fn expand_writeable(tokens: TokenStream) -> TokenStream {
76-
let krate = super::krate();
77-
let input = parse_macro_input!(tokens as ItemStruct);
80+
pub fn expand_writeable(input: DeriveInput) -> syn::Result<TokenStream> {
7881
let ident = input.ident;
79-
let generics = input.generics;
82+
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
83+
84+
let fields = match input.data {
85+
Data::Struct(strukt) => strukt.fields,
86+
Data::Enum(inum) => {
87+
return Err(syn::Error::new(
88+
inum.enum_token.span,
89+
"#[derive(InfluxDbWriteable)] can only be used on structs",
90+
))
91+
}
92+
Data::Union(cdu) => {
93+
return Err(syn::Error::new(
94+
cdu.union_token.span,
95+
"#[derive(InfluxDbWriteable)] can only be used on structs",
96+
))
97+
}
98+
};
8099

81100
let time_field = format_ident!("time");
101+
let time_field_str = time_field.to_string();
82102
#[allow(clippy::cmp_owned)] // that's not how idents work clippy
83-
let fields: Vec<TokenStream2> = match input.fields {
103+
let fields = match fields {
84104
Fields::Named(fields) => fields
85105
.named
86106
.into_iter()
87-
.map(WriteableField::from)
88-
.filter(|field| !field.is_ignore)
89-
.filter(|field| field.ident.to_string() != time_field.to_string())
90-
.map(|field| {
91-
let ident = field.ident;
92-
#[allow(clippy::match_bool)]
93-
match field.is_tag {
94-
true => quote!(query.add_tag(stringify!(#ident), self.#ident)),
95-
false => quote!(query.add_field(stringify!(#ident), self.#ident)),
96-
}
107+
.filter_map(|f| {
108+
WriteableField::try_from(f)
109+
.map(|wf| {
110+
if !wf.is_ignore && wf.ident.to_string() != time_field_str {
111+
let ident = wf.ident;
112+
Some(match wf.is_tag {
113+
true => quote!(query.add_tag(stringify!(#ident), self.#ident)),
114+
false => quote!(query.add_field(stringify!(#ident), self.#ident)),
115+
})
116+
} else {
117+
None
118+
}
119+
})
120+
.transpose()
97121
})
98-
.collect(),
122+
.collect::<syn::Result<Vec<_>>>()?,
99123
_ => panic!("a struct without named fields is not supported"),
100124
};
101125

102-
let output = quote! {
103-
impl #generics #krate::InfluxDbWriteable for #ident #generics
104-
{
105-
fn into_query<I: Into<String>>(self, name : I) -> #krate::WriteQuery
106-
{
107-
let timestamp : #krate::Timestamp = self.#time_field.into();
126+
Ok(quote! {
127+
impl #impl_generics ::influxdb::InfluxDbWriteable for #ident #ty_generics #where_clause {
128+
fn into_query<I: Into<String>>(self, name: I) -> ::influxdb::WriteQuery {
129+
let timestamp: ::influxdb::Timestamp = self.#time_field.into();
108130
let mut query = timestamp.into_query(name);
109131
#(
110132
query = #fields;
111133
)*
112134
query
113135
}
114136
}
115-
};
116-
output.into()
137+
})
117138
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy