Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/bit_field/bit_field_derive/src/bit_field_derive.rs
5394 views
1
// Copyright 2018 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#![recursion_limit = "256"]
6
7
extern crate proc_macro;
8
9
use proc_macro2::Span;
10
use proc_macro2::TokenStream;
11
use quote::quote;
12
use quote::quote_spanned;
13
use syn::parse::Error;
14
use syn::parse::Result;
15
use syn::parse_macro_input;
16
use syn::Attribute;
17
use syn::Data;
18
use syn::DataEnum;
19
use syn::DeriveInput;
20
use syn::Fields;
21
use syn::FieldsNamed;
22
use syn::FieldsUnnamed;
23
use syn::Ident;
24
use syn::Lit;
25
use syn::LitInt;
26
use syn::Meta;
27
use syn::MetaNameValue;
28
use syn::Type;
29
use syn::Visibility;
30
31
/// The function that derives the actual implementation.
32
#[proc_macro_attribute]
33
pub fn bitfield(
34
_args: proc_macro::TokenStream,
35
input: proc_macro::TokenStream,
36
) -> proc_macro::TokenStream {
37
let derive_input = parse_macro_input!(input as DeriveInput);
38
39
let expanded = bitfield_impl(&derive_input).unwrap_or_else(|err| {
40
let compile_error = err.to_compile_error();
41
quote! {
42
#compile_error
43
44
// Include the original input to avoid "use of undeclared type"
45
// errors elsewhere.
46
#derive_input
47
}
48
});
49
50
expanded.into()
51
}
52
53
fn bitfield_impl(ast: &DeriveInput) -> Result<TokenStream> {
54
if !ast.generics.params.is_empty() {
55
return Err(Error::new(
56
Span::call_site(),
57
"#[bitfield] does not support generic parameters",
58
));
59
}
60
61
match &ast.data {
62
Data::Struct(data_struct) => match &data_struct.fields {
63
Fields::Named(fields_named) => bitfield_struct_impl(ast, fields_named),
64
Fields::Unnamed(fields_unnamed) => bitfield_tuple_struct_impl(ast, fields_unnamed),
65
Fields::Unit => Err(Error::new(
66
Span::call_site(),
67
"#[bitfield] does not work with unit struct",
68
)),
69
},
70
Data::Enum(data_enum) => bitfield_enum_impl(ast, data_enum),
71
Data::Union(_) => Err(Error::new(
72
Span::call_site(),
73
"#[bitfield] does not support unions",
74
)),
75
}
76
}
77
78
fn bitfield_tuple_struct_impl(ast: &DeriveInput, fields: &FieldsUnnamed) -> Result<TokenStream> {
79
let mut ast = ast.clone();
80
let width = match parse_remove_bits_attr(&mut ast)? {
81
Some(w) => w,
82
None => {
83
return Err(Error::new(
84
Span::call_site(),
85
"tuple struct field must have bits attribute",
86
));
87
}
88
};
89
90
let ident = &ast.ident;
91
92
if width > 64 {
93
return Err(Error::new(
94
Span::call_site(),
95
"max width of bitfield field is 64",
96
));
97
}
98
99
let bits = width as u8;
100
101
if fields.unnamed.len() != 1 {
102
return Err(Error::new(
103
Span::call_site(),
104
"tuple struct field must have exactly 1 field",
105
));
106
}
107
108
let field_type = match &fields.unnamed.first().unwrap().ty {
109
Type::Path(t) => t,
110
_ => {
111
return Err(Error::new(
112
Span::call_site(),
113
"tuple struct field must have primitive field",
114
));
115
}
116
};
117
let span = field_type.path.segments.first().unwrap().ident.span();
118
119
let from_u64 = quote_spanned! {
120
span => val as #field_type
121
};
122
123
let into_u64 = quote_spanned! {
124
span => val.0 as u64
125
};
126
127
let expanded = quote! {
128
#ast
129
130
impl bit_field::BitFieldSpecifier for #ident {
131
const FIELD_WIDTH: u8 = #bits;
132
type SetterType = Self;
133
type GetterType = Self;
134
135
#[inline]
136
#[allow(clippy::unnecessary_cast)]
137
fn from_u64(val: u64) -> Self::GetterType {
138
Self(#from_u64)
139
}
140
141
#[inline]
142
#[allow(clippy::unnecessary_cast)]
143
fn into_u64(val: Self::SetterType) -> u64 {
144
#into_u64
145
}
146
}
147
};
148
149
Ok(expanded)
150
}
151
152
fn bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
153
let mut ast = ast.clone();
154
let width = parse_remove_bits_attr(&mut ast)?;
155
match width {
156
None => bitfield_enum_without_width_impl(&ast, data),
157
Some(width) => bitfield_enum_with_width_impl(&ast, data, width),
158
}
159
}
160
161
fn bitfield_enum_with_width_impl(
162
ast: &DeriveInput,
163
data: &DataEnum,
164
width: u64,
165
) -> Result<TokenStream> {
166
if width > 64 {
167
return Err(Error::new(
168
Span::call_site(),
169
"max width of bitfield enum is 64",
170
));
171
}
172
let bits = width as u8;
173
let declare_discriminants = get_declare_discriminants_for_enum(bits, ast, data);
174
175
let ident = &ast.ident;
176
let type_name = ident.to_string();
177
let variants = &data.variants;
178
let match_discriminants = variants.iter().map(|variant| {
179
let variant = &variant.ident;
180
quote! {
181
discriminant::#variant => Ok(#ident::#variant),
182
}
183
});
184
185
let expanded = quote! {
186
#ast
187
188
impl bit_field::BitFieldSpecifier for #ident {
189
const FIELD_WIDTH: u8 = #bits;
190
type SetterType = Self;
191
type GetterType = std::result::Result<Self, bit_field::Error>;
192
193
#[inline]
194
fn from_u64(val: u64) -> Self::GetterType {
195
struct discriminant;
196
impl discriminant {
197
#(#declare_discriminants)*
198
}
199
match val {
200
#(#match_discriminants)*
201
v => Err(bit_field::Error::new(#type_name, v)),
202
}
203
}
204
205
#[inline]
206
fn into_u64(val: Self::SetterType) -> u64 {
207
val as u64
208
}
209
}
210
};
211
212
Ok(expanded)
213
}
214
// Expand to an impl of BitFieldSpecifier for an enum like:
215
//
216
// #[bitfield]
217
// #[derive(Debug, PartialEq)]
218
// enum TwoBits {
219
// Zero = 0b00,
220
// One = 0b01,
221
// Two = 0b10,
222
// Three = 0b11,
223
// }
224
//
225
// Such enums may be used as a field of a bitfield struct.
226
//
227
// #[bitfield]
228
// struct Struct {
229
// prefix: BitField1,
230
// two_bits: TwoBits,
231
// suffix: BitField5,
232
// }
233
//
234
fn bitfield_enum_without_width_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
235
let ident = &ast.ident;
236
let variants = &data.variants;
237
let len = variants.len();
238
if len.count_ones() != 1 {
239
return Err(Error::new(
240
Span::call_site(),
241
"#[bitfield] expected a number of variants which is a power of 2 when bits is not \
242
specified for the enum",
243
));
244
}
245
246
let bits = len.trailing_zeros() as u8;
247
let declare_discriminants = get_declare_discriminants_for_enum(bits, ast, data);
248
249
let match_discriminants = variants.iter().map(|variant| {
250
let variant = &variant.ident;
251
quote! {
252
discriminant::#variant => #ident::#variant,
253
}
254
});
255
256
let expanded = quote! {
257
#ast
258
259
impl bit_field::BitFieldSpecifier for #ident {
260
const FIELD_WIDTH: u8 = #bits;
261
type SetterType = Self;
262
type GetterType = Self;
263
264
#[inline]
265
fn from_u64(val: u64) -> Self::GetterType {
266
struct discriminant;
267
impl discriminant {
268
#(#declare_discriminants)*
269
}
270
match val {
271
#(#match_discriminants)*
272
_ => unreachable!(),
273
}
274
}
275
276
#[inline]
277
fn into_u64(val: Self::SetterType) -> u64 {
278
val as u64
279
}
280
}
281
};
282
283
Ok(expanded)
284
}
285
286
fn get_declare_discriminants_for_enum(
287
bits: u8,
288
ast: &DeriveInput,
289
data: &DataEnum,
290
) -> Vec<TokenStream> {
291
let variants = &data.variants;
292
let upper_bound = 2u64.pow(bits as u32);
293
let ident = &ast.ident;
294
295
variants
296
.iter()
297
.map(|variant| {
298
let variant = &variant.ident;
299
let span = variant.span();
300
301
let assertion = quote_spanned! {span=>
302
// If IS_IN_BOUNDS is true, this evaluates to 0.
303
//
304
// If IS_IN_BOUNDS is false, this evaluates to `0 - 1` which
305
// triggers a compile error on underflow when referenced below. The
306
// error is not beautiful but does carry the span of the problematic
307
// enum variant so at least it points to the right line.
308
//
309
// error: any use of this value will cause an error
310
// --> bit_field/test.rs:10:5
311
// |
312
// 10 | OutOfBounds = 0b111111,
313
// | ^^^^^^^^^^^ attempt to subtract with overflow
314
// |
315
//
316
// error[E0080]: erroneous constant used
317
// --> bit_field/test.rs:5:1
318
// |
319
// 5 | #[bitfield]
320
// | ^^^^^^^^^^^ referenced constant has errors
321
//
322
const ASSERT: u64 = 0 - !IS_IN_BOUNDS as u64;
323
};
324
325
quote! {
326
#[allow(non_upper_case_globals)]
327
const #variant: u64 = {
328
const IS_IN_BOUNDS: bool = (#ident::#variant as u64) < #upper_bound;
329
330
#assertion
331
332
#ident::#variant as u64 + ASSERT
333
};
334
}
335
})
336
.collect()
337
}
338
339
fn bitfield_struct_impl(ast: &DeriveInput, fields: &FieldsNamed) -> Result<TokenStream> {
340
let name = &ast.ident;
341
let vis = &ast.vis;
342
let attrs = &ast.attrs;
343
let fields = get_struct_fields(fields)?;
344
let struct_def = get_struct_def(vis, name, &fields);
345
let bits_impl = get_bits_impl(name);
346
let fields_impl = get_fields_impl(&fields);
347
let debug_fmt_impl = get_debug_fmt_impl(name, &fields);
348
349
let expanded = quote! {
350
#(#attrs)*
351
#struct_def
352
#bits_impl
353
impl #name {
354
#(#fields_impl)*
355
}
356
#debug_fmt_impl
357
};
358
359
Ok(expanded)
360
}
361
362
struct FieldSpec<'a> {
363
ident: &'a Ident,
364
ty: &'a Type,
365
expected_bits: Option<LitInt>,
366
}
367
368
// Unwrap ast to get the named fields. We only care about field names and types:
369
// "myfield : BitField3" -> ("myfield", Token(BitField3))
370
fn get_struct_fields(fields: &FieldsNamed) -> Result<Vec<FieldSpec>> {
371
let mut vec = Vec::new();
372
373
for field in &fields.named {
374
let ident = field
375
.ident
376
.as_ref()
377
.expect("Fields::Named has named fields");
378
let ty = &field.ty;
379
let expected_bits = parse_bits_attr(&field.attrs)?;
380
vec.push(FieldSpec {
381
ident,
382
ty,
383
expected_bits,
384
});
385
}
386
387
Ok(vec)
388
}
389
390
// For example: #[bits = 1]
391
fn parse_bits_attr(attrs: &[Attribute]) -> Result<Option<LitInt>> {
392
let mut expected_bits = None;
393
394
for attr in attrs {
395
if attr.path().is_ident("doc") {
396
continue;
397
}
398
if let Some(v) = try_parse_bits_attr(attr) {
399
expected_bits = Some(v);
400
continue;
401
}
402
403
return Err(Error::new_spanned(attr, "unrecognized attribute"));
404
}
405
406
Ok(expected_bits)
407
}
408
409
// This function will return None if the attribute is not #[bits = *].
410
fn try_parse_bits_attr(attr: &Attribute) -> Option<LitInt> {
411
if attr.path().is_ident("bits") {
412
if let Meta::NameValue(MetaNameValue {
413
value:
414
syn::Expr::Lit(syn::ExprLit {
415
lit: Lit::Int(int), ..
416
}),
417
..
418
}) = &attr.meta
419
{
420
return Some(int).cloned();
421
}
422
}
423
None
424
}
425
426
fn parse_remove_bits_attr(ast: &mut DeriveInput) -> Result<Option<u64>> {
427
let mut width = None;
428
let mut bits_idx = 0;
429
430
for (i, attr) in ast.attrs.iter().enumerate() {
431
if let Some(w) = try_parse_bits_attr(attr) {
432
bits_idx = i;
433
width = Some(w.base10_parse()?);
434
}
435
}
436
437
if width.is_some() {
438
ast.attrs.remove(bits_idx);
439
}
440
441
Ok(width)
442
}
443
444
fn get_struct_def(vis: &Visibility, name: &Ident, fields: &[FieldSpec]) -> TokenStream {
445
let mut field_types = Vec::new();
446
for spec in fields {
447
field_types.push(spec.ty);
448
}
449
450
// `(BitField1::FIELD_WIDTH + BitField3::FIELD_WIDTH + ...)`
451
let data_size_in_bits = quote! {
452
(
453
#(
454
<#field_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
455
)+*
456
)
457
};
458
459
quote! {
460
#[repr(C)]
461
#vis struct #name {
462
data: [u8; #data_size_in_bits / 8],
463
}
464
465
impl #name {
466
pub fn new() -> #name {
467
let _: ::bit_field::Check<[u8; #data_size_in_bits % 8]>;
468
469
#name {
470
data: [0; #data_size_in_bits / 8],
471
}
472
}
473
}
474
}
475
}
476
477
// Implement setter and getter for all fields.
478
fn get_fields_impl(fields: &[FieldSpec]) -> Vec<TokenStream> {
479
let mut impls = Vec::new();
480
// This vec keeps track of types before this field, used to generate the offset.
481
let current_types = &mut vec![quote!(::bit_field::BitField0)];
482
483
for spec in fields {
484
let ty = spec.ty;
485
let getter_ident = Ident::new(format!("get_{}", spec.ident).as_str(), Span::call_site());
486
let setter_ident = Ident::new(format!("set_{}", spec.ident).as_str(), Span::call_site());
487
488
// Optional #[bits = N] attribute to provide compile-time checked
489
// documentation of how many bits some field covers.
490
let check_expected_bits = spec.expected_bits.as_ref().map(|expected_bits| {
491
// If expected_bits does not match the actual number of bits in the
492
// bit field specifier, this will fail to compile with an error
493
// pointing into the #[bits = N] attribute.
494
let span = expected_bits.span();
495
quote_spanned! {span=>
496
#[allow(dead_code)]
497
const EXPECTED_BITS: [(); #expected_bits] =
498
[(); <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize];
499
}
500
});
501
502
impls.push(quote! {
503
pub fn #getter_ident(&self) -> <#ty as ::bit_field::BitFieldSpecifier>::GetterType {
504
#check_expected_bits
505
let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
506
let val = self.get(offset, <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
507
<#ty as ::bit_field::BitFieldSpecifier>::from_u64(val)
508
}
509
510
pub fn #setter_ident(&mut self, val: <#ty as ::bit_field::BitFieldSpecifier>::SetterType) {
511
let val = <#ty as ::bit_field::BitFieldSpecifier>::into_u64(val);
512
debug_assert!(val <= ::bit_field::max::<#ty>());
513
let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
514
self.set(offset, <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
515
}
516
});
517
518
current_types.push(quote!(#ty));
519
}
520
521
impls
522
}
523
524
// Implement setter and getter for all fields.
525
fn get_debug_fmt_impl(name: &Ident, fields: &[FieldSpec]) -> TokenStream {
526
// print fields:
527
let mut impls = Vec::new();
528
for spec in fields {
529
let field_name = spec.ident.to_string();
530
let getter_ident = Ident::new(&format!("get_{}", spec.ident), Span::call_site());
531
impls.push(quote! {
532
.field(#field_name, &self.#getter_ident())
533
});
534
}
535
536
let name_str = format!("{name}");
537
quote! {
538
impl std::fmt::Debug for #name {
539
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
540
f.debug_struct(#name_str)
541
#(#impls)*
542
.finish()
543
}
544
}
545
}
546
}
547
548
fn get_bits_impl(name: &Ident) -> TokenStream {
549
quote! {
550
impl #name {
551
#[inline]
552
fn check_access(&self, offset: usize, width: u8) {
553
debug_assert!(width <= 64);
554
debug_assert!(offset / 8 < self.data.len());
555
debug_assert!((offset + (width as usize)) <= (self.data.len() * 8));
556
}
557
558
#[inline]
559
pub fn get_bit(&self, offset: usize) -> bool {
560
self.check_access(offset, 1);
561
562
let byte_index = offset / 8;
563
let bit_offset = offset % 8;
564
565
let byte = self.data[byte_index];
566
let mask = 1 << bit_offset;
567
568
byte & mask == mask
569
}
570
571
#[inline]
572
pub fn set_bit(&mut self, offset: usize, val: bool) {
573
self.check_access(offset, 1);
574
575
let byte_index = offset / 8;
576
let bit_offset = offset % 8;
577
578
let byte = &mut self.data[byte_index];
579
let mask = 1 << bit_offset;
580
581
if val {
582
*byte |= mask;
583
} else {
584
*byte &= !mask;
585
}
586
}
587
588
#[inline]
589
pub fn get(&self, offset: usize, width: u8) -> u64 {
590
self.check_access(offset, width);
591
let mut val = 0;
592
593
for i in 0..(width as usize) {
594
if self.get_bit(i + offset) {
595
val |= 1 << i;
596
}
597
}
598
599
val
600
}
601
602
#[inline]
603
pub fn set(&mut self, offset: usize, width: u8, val: u64) {
604
self.check_access(offset, width);
605
606
for i in 0..(width as usize) {
607
let mask = 1 << i;
608
let val_bit_is_set = val & mask == mask;
609
self.set_bit(i + offset, val_bit_is_set);
610
}
611
}
612
}
613
}
614
}
615
616
// Only intended to be used from the bit_field crate. This macro emits the
617
// marker types bit_field::BitField0 through bit_field::BitField64.
618
#[proc_macro]
619
#[doc(hidden)]
620
pub fn define_bit_field_specifiers(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
621
let mut code = TokenStream::new();
622
623
for width in 0u8..=64 {
624
let span = Span::call_site();
625
let long_name = Ident::new(&format!("BitField{width}"), span);
626
let short_name = Ident::new(&format!("B{width}"), span);
627
628
let default_field_type = if width <= 8 {
629
quote!(u8)
630
} else if width <= 16 {
631
quote!(u16)
632
} else if width <= 32 {
633
quote!(u32)
634
} else {
635
quote!(u64)
636
};
637
638
code.extend(quote! {
639
pub struct #long_name;
640
pub use self::#long_name as #short_name;
641
642
impl BitFieldSpecifier for #long_name {
643
const FIELD_WIDTH: u8 = #width;
644
type SetterType = #default_field_type;
645
type GetterType = #default_field_type;
646
647
#[inline]
648
fn from_u64(val: u64) -> Self::GetterType {
649
val as Self::GetterType
650
}
651
652
#[inline]
653
fn into_u64(val: Self::SetterType) -> u64 {
654
val as u64
655
}
656
}
657
});
658
}
659
660
code.into()
661
}
662
663
#[cfg(test)]
664
mod tests {
665
use syn::parse_quote;
666
667
use super::*;
668
669
#[test]
670
fn end_to_end() {
671
let input: DeriveInput = parse_quote! {
672
#[derive(Clone)]
673
struct MyBitField {
674
a: BitField1,
675
b: BitField2,
676
c: BitField5,
677
}
678
};
679
680
let expected = quote! {
681
#[derive(Clone)]
682
#[repr(C)]
683
struct MyBitField {
684
data: [u8; (<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
685
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
686
+ <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
687
/ 8],
688
}
689
impl MyBitField {
690
pub fn new() -> MyBitField {
691
let _: ::bit_field::Check<[
692
u8;
693
(<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
694
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
695
+ <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
696
% 8
697
]>;
698
699
MyBitField {
700
data: [0; (<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
701
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
702
+ <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
703
/ 8],
704
}
705
}
706
}
707
impl MyBitField {
708
#[inline]
709
fn check_access(&self, offset: usize, width: u8) {
710
debug_assert!(width <= 64);
711
debug_assert!(offset / 8 < self.data.len());
712
debug_assert!((offset + (width as usize)) <= (self.data.len() * 8));
713
}
714
#[inline]
715
pub fn get_bit(&self, offset: usize) -> bool {
716
self.check_access(offset, 1);
717
let byte_index = offset / 8;
718
let bit_offset = offset % 8;
719
let byte = self.data[byte_index];
720
let mask = 1 << bit_offset;
721
byte & mask == mask
722
}
723
#[inline]
724
pub fn set_bit(&mut self, offset: usize, val: bool) {
725
self.check_access(offset, 1);
726
let byte_index = offset / 8;
727
let bit_offset = offset % 8;
728
let byte = &mut self.data[byte_index];
729
let mask = 1 << bit_offset;
730
if val {
731
*byte |= mask;
732
} else {
733
*byte &= !mask;
734
}
735
}
736
#[inline]
737
pub fn get(&self, offset: usize, width: u8) -> u64 {
738
self.check_access(offset, width);
739
let mut val = 0;
740
for i in 0..(width as usize) {
741
if self.get_bit(i + offset) {
742
val |= 1 << i;
743
}
744
}
745
val
746
}
747
#[inline]
748
pub fn set(&mut self, offset: usize, width: u8, val: u64) {
749
self.check_access(offset, width);
750
for i in 0..(width as usize) {
751
let mask = 1 << i;
752
let val_bit_is_set = val & mask == mask;
753
self.set_bit(i + offset, val_bit_is_set);
754
}
755
}
756
}
757
impl MyBitField {
758
pub fn get_a(&self) -> <BitField1 as ::bit_field::BitFieldSpecifier>::GetterType {
759
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
760
let val = self.get(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
761
<BitField1 as ::bit_field::BitFieldSpecifier>::from_u64(val)
762
}
763
pub fn set_a(&mut self, val: <BitField1 as ::bit_field::BitFieldSpecifier>::SetterType) {
764
let val = <BitField1 as ::bit_field::BitFieldSpecifier>::into_u64(val);
765
debug_assert!(val <= ::bit_field::max::<BitField1>());
766
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
767
self.set(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
768
}
769
pub fn get_b(&self) -> <BitField2 as ::bit_field::BitFieldSpecifier>::GetterType {
770
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
771
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
772
let val = self.get(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
773
<BitField2 as ::bit_field::BitFieldSpecifier>::from_u64(val)
774
}
775
pub fn set_b(&mut self, val: <BitField2 as ::bit_field::BitFieldSpecifier>::SetterType) {
776
let val = <BitField2 as ::bit_field::BitFieldSpecifier>::into_u64(val);
777
debug_assert!(val <= ::bit_field::max::<BitField2>());
778
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
779
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
780
self.set(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
781
}
782
pub fn get_c(&self) -> <BitField5 as ::bit_field::BitFieldSpecifier>::GetterType {
783
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
784
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
785
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
786
let val = self.get(offset, <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
787
<BitField5 as ::bit_field::BitFieldSpecifier>::from_u64(val)
788
}
789
pub fn set_c(&mut self, val: <BitField5 as ::bit_field::BitFieldSpecifier>::SetterType) {
790
let val = <BitField5 as ::bit_field::BitFieldSpecifier>::into_u64(val);
791
debug_assert!(val <= ::bit_field::max::<BitField5>());
792
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
793
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
794
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
795
self.set(offset, <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
796
}
797
}
798
impl std::fmt::Debug for MyBitField {
799
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
800
f.debug_struct("MyBitField")
801
.field("a", &self.get_a())
802
.field("b", &self.get_b())
803
.field("c", &self.get_c())
804
.finish()
805
}
806
}
807
};
808
809
assert_eq!(
810
bitfield_impl(&input).unwrap().to_string(),
811
expected.to_string()
812
);
813
}
814
}
815
816