1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use super::config::ConfigValue;
use crate::errors::CombineError;
use proc_macro2::Span;
#[derive(Default, Clone)]
pub struct FieldConfig {
/// Attributes that are re-expanded and going to be ignored by the rest of the `#[bitfield]` invocation.
pub retained_attrs: Vec<syn::Attribute>,
/// An encountered `#[bits = N]` attribute on a field.
pub bits: Option<ConfigValue<usize>>,
/// An encountered `#[skip]` attribute on a field.
pub skip: Option<ConfigValue<SkipWhich>>,
}
/// Controls which parts of the code generation to skip.
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
pub enum SkipWhich {
/// Skip code generation of getters and setters.
All,
/// Skip code generation of only getters.
///
/// For field `f` these include:
///
/// - `f`
/// - `f_or_err`
Getters,
/// Skip code generation of only setters.
///
/// For field `f` these include:
///
/// - `set_f`
/// - `set_f_checked`
/// - `with_f`
/// - `with_f_checked`
Setters,
}
impl SkipWhich {
/// Returns `true` if code generation of getters should be skipped.
pub fn skip_getters(self) -> bool {
matches!(self, Self::All | Self::Getters)
}
/// Returns `true` if code generation of setters should be skipped.
pub fn skip_setters(self) -> bool {
matches!(self, Self::All | Self::Setters)
}
}
impl FieldConfig {
/// Registers the given attribute to be re-expanded and further ignored.
pub fn retain_attr(&mut self, attr: syn::Attribute) {
self.retained_attrs.push(attr);
}
/// Sets the `#[bits = N]` if found for a `#[bitfield]` annotated field.
///
/// # Errors
///
/// If previously already registered a `#[bits = M]`.
pub fn bits(&mut self, amount: usize, span: Span) -> Result<(), syn::Error> {
match self.bits {
Some(ref previous) => {
return Err(format_err!(
span,
"encountered duplicate `#[bits = N]` attribute for field"
)
.into_combine(format_err!(previous.span, "duplicate `#[bits = M]` here")))
}
None => {
self.bits = Some(ConfigValue {
value: amount,
span,
})
}
}
Ok(())
}
/// Sets the `#[skip(which)]` if found for a `#[bitfield]` annotated field.
///
/// # Syntax
///
/// - `#[skip]` defaults to `SkipWhich::All`.
/// - `#[skip(getters)]` is `SkipWhich::Getters`.
/// - `#[skip(setters)]` is `SkipWhich::Setters`.
/// - `#[skip(getters, setters)]` is the same as `#[skip]`.
/// - `#[skip(getters)] #[skip(setters)]` is the same as `#[skip]`.
///
/// # Errors
///
/// If previously already registered a `#[skip]` that overlaps with the previous.
/// E.g. when skipping getters or setters twice. Note that skipping getters followed
/// by skipping setters is fine.
pub fn skip(&mut self, which: SkipWhich, span: Span) -> Result<(), syn::Error> {
fn raise_skip_error(
skip_params: &str,
span: Span,
previous: &ConfigValue<SkipWhich>,
) -> syn::Error {
format_err!(
span,
"encountered duplicate `#[skip{}]` attribute for field",
skip_params
)
.into_combine(format_err!(
previous.span,
"duplicate `#[skip{}]` here",
skip_params
))
}
match self.skip {
Some(ref previous) => {
match which {
SkipWhich::All => return Err(raise_skip_error("", span, previous)),
SkipWhich::Getters => {
if previous.value == SkipWhich::Getters
|| previous.value == SkipWhich::All
{
return Err(raise_skip_error("(getters)", span, previous))
}
}
SkipWhich::Setters => {
if previous.value == SkipWhich::Setters
|| previous.value == SkipWhich::All
{
return Err(raise_skip_error("(setters)", span, previous))
}
}
}
self.skip = Some(ConfigValue {
value: SkipWhich::All,
span: span.join(previous.span).unwrap_or(span),
});
}
None => self.skip = Some(ConfigValue { value: which, span }),
}
Ok(())
}
/// Returns `true` if the config demands that code generation for setters should be skipped.
pub fn skip_setters(&self) -> bool {
self.skip
.as_ref()
.map(|config| config.value)
.map(SkipWhich::skip_setters)
.unwrap_or(false)
}
/// Returns `true` if the config demands that code generation for getters should be skipped.
pub fn skip_getters(&self) -> bool {
self.skip
.as_ref()
.map(|config| config.value)
.map(SkipWhich::skip_getters)
.unwrap_or(false)
}
}