1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use proc_macro2::TokenStream;
6 use syn;
7 use syn::parse::{Parse, ParseStream, Parser, Result as ParseResult};
8
9 // $(#[$outer:meta])*
10 // ($($vis:tt)*) $BitFlags:ident: $T:ty {
11 // $(
12 // $(#[$inner:ident $($args:tt)*])*
13 // const $Flag:ident = $value:expr;
14 // )+
15 // }
16 #[derive(Debug)]
17 pub struct Bitflags {
18 attrs: Vec<syn::Attribute>,
19 vis: syn::Visibility,
20 struct_token: Token![struct],
21 name: syn::Ident,
22 colon_token: Token![:],
23 repr: syn::Type,
24 flags: Flags,
25 }
26
27 impl Bitflags {
expand(&self) -> (syn::ItemStruct, syn::ItemImpl)28 pub fn expand(&self) -> (syn::ItemStruct, syn::ItemImpl) {
29 let Bitflags {
30 ref attrs,
31 ref vis,
32 ref name,
33 ref repr,
34 ref flags,
35 ..
36 } = *self;
37
38 let struct_ = parse_quote! {
39 /// cbindgen:internal-derive-bitflags=true
40 #(#attrs)*
41 #vis struct #name {
42 bits: #repr,
43 }
44 };
45
46 let consts = flags.expand(name);
47 let impl_ = parse_quote! {
48 impl #name {
49 #consts
50 }
51 };
52
53 (struct_, impl_)
54 }
55 }
56
57 impl Parse for Bitflags {
parse(input: ParseStream) -> ParseResult<Self>58 fn parse(input: ParseStream) -> ParseResult<Self> {
59 Ok(Self {
60 attrs: input.call(syn::Attribute::parse_outer)?,
61 vis: input.parse()?,
62 struct_token: input.parse()?,
63 name: input.parse()?,
64 colon_token: input.parse()?,
65 repr: input.parse()?,
66 flags: input.parse()?,
67 })
68 }
69 }
70
71 // $(#[$inner:ident $($args:tt)*])*
72 // const $Flag:ident = $value:expr;
73 #[derive(Debug)]
74 struct Flag {
75 attrs: Vec<syn::Attribute>,
76 const_token: Token![const],
77 name: syn::Ident,
78 equals_token: Token![=],
79 value: syn::Expr,
80 semicolon_token: Token![;],
81 }
82
83 impl Flag {
expand(&self, struct_name: &syn::Ident) -> TokenStream84 fn expand(&self, struct_name: &syn::Ident) -> TokenStream {
85 let Flag {
86 ref attrs,
87 ref name,
88 ref value,
89 ..
90 } = *self;
91 quote! {
92 #(#attrs)*
93 pub const #name : #struct_name = #struct_name { bits: #value };
94 }
95 }
96 }
97
98 impl Parse for Flag {
parse(input: ParseStream) -> ParseResult<Self>99 fn parse(input: ParseStream) -> ParseResult<Self> {
100 Ok(Self {
101 attrs: input.call(syn::Attribute::parse_outer)?,
102 const_token: input.parse()?,
103 name: input.parse()?,
104 equals_token: input.parse()?,
105 value: input.parse()?,
106 semicolon_token: input.parse()?,
107 })
108 }
109 }
110
111 #[derive(Debug)]
112 struct Flags(Vec<Flag>);
113
114 impl Parse for Flags {
parse(input: ParseStream) -> ParseResult<Self>115 fn parse(input: ParseStream) -> ParseResult<Self> {
116 let content;
117 let _ = braced!(content in input);
118 let mut flags = vec![];
119 while !content.is_empty() {
120 flags.push(content.parse()?);
121 }
122 Ok(Flags(flags))
123 }
124 }
125
126 impl Flags {
expand(&self, struct_name: &syn::Ident) -> TokenStream127 fn expand(&self, struct_name: &syn::Ident) -> TokenStream {
128 let mut ts = quote! {};
129 for flag in &self.0 {
130 ts.extend(flag.expand(struct_name));
131 }
132 ts
133 }
134 }
135
parse(tokens: TokenStream) -> ParseResult<Bitflags>136 pub fn parse(tokens: TokenStream) -> ParseResult<Bitflags> {
137 let parser = Bitflags::parse;
138 parser.parse2(tokens)
139 }
140