proc_bitfield/
example.rs

1pub mod support;
2
3use crate::*;
4use support::*;
5
6bitfield! {
7    /// A bitfield showcasing how to specify bit ranges.
8    #[derive(Clone, Copy, PartialEq, Eq)]
9    pub struct BitRanges(pub u32): Debug, FromStorage, IntoStorage, DerefStorage {
10        // A single field spanning the entire bitfield, using an unbounded range:
11        pub whole_bitfield: u32 @ ..,                 // Bits 0 to 31
12
13        // Multi-bit field, specified using an inclusive range:
14        pub inclusive_range: u8 @ 0..=3,              // Bits 0 to 3
15
16        // Multi-bit field, specified using an exclusive range:
17        pub exclusive_range: u8 @ 4..7,               // Bits 4 to 6
18
19        // Multi-bit field specified using its start bit and length:
20        pub start_and_length: u8 @ 7; 5,              // Bits 7 to 11
21
22        // Single-bit field, specified using an inclusive range:
23        pub single_bit_inclusive_range: u8 @ 12..=12, // Bit 12
24
25        // Single-bit field, specified using an exclusive range:
26        pub single_bit_exclusive_range: u8 @ 13..14,  // Bit 13
27
28        // Single-bit field, specified using its start bit and a length of 1:
29        pub single_bit_start_and_length: u8 @ 14; 1,  // Bit 14
30
31        // Single-bit boolean flag, specified using a single bit position.
32        // This is equivalent to the single-bit exclusive range, but uses the `Bit` traits instead
33        // of `Bits<T>`, and is specific to `bool` (which is conversely not allowed using bit
34        // ranges).
35        pub flag: bool @ 15,                          // Bit 15
36
37        // Multi-bit field placed immediately above the previous one
38        pub pack_above: u8 @ above; 4,                // Bits 16 to 19
39
40        // Single-bit field placed immediately above the previous one
41        pub single_bit_pack_above: bool @ above,      // Bit 20
42
43        pub flag2: bool @ 28,                         // Bit 28
44
45        // Multi-bit field placed immediately below the previous one
46        pub pack_below: u8 @ below; 4,                // Bits 24 to 27
47
48        // Single-bit field placed immediately below the previous one
49        pub single_bit_pack_below: bool @ below,      // Bit 23
50    }
51}
52
53bitfield! {
54    /// A bitfield showcasing how to specify access restrictions.
55    pub struct AccessRestrictions(pub u8): Debug, FromStorage, IntoStorage, DerefStorage {
56        // By specifying `read_only` (or `ro`), only `AccessRestrictions::read_only_flag` will be
57        // generated (no setters):
58        pub read_only_flag: bool [read_only] @ 0,
59        // Equivalent:
60        // pub read_only_flag: bool [ro] @ 0,
61
62        // By specifying `write_only` (or `wo`), only `AccessRestrictions::set_write_only_flag` and
63        // `AccessRestrictions::with_write_only_flag` will be generated (no getters):
64        pub write_only_flag: bool [write_only] @ 1,
65        // Equivalent:
66        // pub read_only_flag: bool [wo] @ 0,
67
68        // Both getters and setters will be generated without any explicit access restrictions:
69        // `AccessRestrictions::read_write_flag`, `AccessRestrictions::set_read_write_flag` and
70        // `AccessRestrictions::with_read_write_flag` will all be generated.
71        pub read_write_flag: bool @ 2,
72    }
73}
74
75bitfield! {
76    /// A bitfield showcasing how to use nested bitfields.
77    pub struct NestedBitfields(pub u16): Debug, FromStorage, IntoStorage, DerefStorage {
78        // By specifying `read_only` (or `ro`), only `NestedBitfields::read_only_nested` will be
79        // generated (no setters and no mutable reference access):
80        pub read_only_nested: nested AccessRestrictions [read_only] @ 0; 3,
81        // Equivalent:
82        // pub read_only_nested: nested AccessRestrictions [ro] @ 0; 3,
83
84        // By specifying `write_only` (or `wo`), only `NestedBitfields::with_write_only_nested` and
85        // `NestedBitfields::set_write_only_nested` will be generated (no getter and no mutable
86        // reference access):
87        pub write_only_nested: nested AccessRestrictions [write_only] @ 4; 3,
88        // Equivalent:
89        // pub write_only_nested: nested AccessRestrictions [wo] @ 4; 3,
90
91        // All accessors will be generated without any explicit access restrictions:
92        // - `NestedBitfields::read_write_nested`
93        // - `NestedBitfields::read_write_nested_mut`
94        // - `NestedBitfields::with_read_write_nested`
95        // - `NestedBitfields::set_read_write_nested`
96        pub read_write_nested: nested AccessRestrictions @ 8; 3,
97    }
98}
99
100bitfield! {
101    /// A bitfield showcasing various kinds of field type conversions.
102    pub struct FieldTypeConversions(pub u16): Debug, FromStorage, IntoStorage, DerefStorage {
103        // Infallible conversions
104
105        // Will:
106        // - Return a `U8WithParity` on reads, calling `<U8WithParity as From<u8>>::from`
107        // - Take a `u8` for writes
108        pub read_as_u8_with_parity: u8 [get U8WithParity] @ 0..=3,
109
110        // Will:
111        // - Return a `u8` on reads
112        // - Take a `U8WithParity` for writes, calling `<U8WithParity as Into<u8>>::into`
113        pub write_as_u8_with_parity: u8 [set U8WithParity] @ 4..=7,
114
115        // Will:
116        // - Return a `U8WithParity` on reads, calling `<U8WithParity as From<u8>>::from`
117        // - Take a `U8WithParity` for writes, calling `<U8WithParity as Into<u8>>::into`
118        pub as_u8_with_parity: u8 [U8WithParity] @ 8..=11,
119        // Equivalent to:
120        // pub u8_with_parity: u8 [get U8WithParity, set U8WithParity] @ 8..=11,
121
122
123        // Infallible conversion functions
124
125        // Will:
126        // - Return a `U8WithParity` on reads, calling `<U8WithParity as From<u8>>::from`
127        // - Take a `u8` for writes
128        pub read_as_u8_with_parity_fn: u8 [get_fn U8WithParity::from -> U8WithParity] @ 0..=3,
129
130        // Will:
131        // - Return a `u8` on reads
132        // - Take a `U8WithParity` for writes, calling `<U8WithParity as Into<u8>>::into`
133        pub write_as_u8_with_parity_fn: u8 [set_fn U8WithParity::into(U8WithParity)] @ 4..=7,
134
135
136        // Unsafe/unchecked conversions
137
138        // Will:
139        // - Return a `NonZeroU8` on reads, marking them as `unsafe` and calling
140        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
141        // - Take a `u8` for writes
142        pub unsafe_read_as_non_zero_u8: u8 [unsafe_get NonZeroU8] @ 0..=3,
143
144        // Will:
145        // - Return a `u8` on reads
146        // - Take a `U16` for writes, marking them as `unsafe` and calling
147        //   `<U16 as UnsafeInto<u8>>::unsafe_into`
148        pub unsafe_write_as_u16: u8 [unsafe_set U16] @ 4..=7,
149
150        // Will:
151        // - Return a `SpuriouslyFailingU8` on reads, marking them as `unsafe` and calling
152        //   `<SpuriouslyFailingU8 as UnsafeFrom<u8>>::unsafe_from`
153        // - Take a `SpuriouslyFailingU8` for writes, marking them as `unsafe` and calling
154        //   `<SpuriouslyFailingU8 as UnsafeInto<u8>>::unsafe_into`
155        pub unsafe_as_spuriously_failing: u8 [unsafe_both SpuriouslyFailingU8] @ 8..=11,
156        // Equivalent to:
157        // pub unsafe_as_spuriously_failing: u8
158        //  [unsafe_get SpuriouslyFailingU8, unsafe_set SpuriouslyFailingU8] @ 8..=11,
159
160        // Will:
161        // - Return a `NonZeroU8` on reads, marking them as `unsafe` and calling
162        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
163        // - Take a `NonZeroU8` for writes, calling `<NonZeroU8 as Into<u8>>::into`
164        pub unsafe_as_non_zero_u8: u8 [unsafe NonZeroU8] @ 12..=15,
165        // Equivalent to:
166        // pub unsafe_as_non_zero_u8: u8 [unsafe_get NonZeroU8, set NonZeroU8] @ 12..=15,
167
168
169        // Unsafe/unchecked conversion functions
170
171        // Will:
172        // - Return a `NonZeroU8` on reads, marking them as `unsafe` and calling
173        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
174        // - Take a `u8` for writes
175        pub unsafe_read_as_non_zero_u8_fn: u8 [
176            unsafe_get_fn NonZeroU8::unsafe_from -> NonZeroU8
177        ] @ 0..=3,
178
179        // Will:
180        // - Return a `u8` on reads
181        // - Take a `U16` for writes, marking them as `unsafe` and calling
182        //   `<U16 as UnsafeInto<u8>>::unsafe_into`
183        pub unsafe_write_as_u16_fn: u8 [unsafe_set_fn U16::unsafe_into(U16)] @ 4..=7,
184
185
186        // Unsafe/unchecked conversions with safe accessors
187
188        // Will:
189        // - Return a `NonZeroU8` on reads, unsafely calling
190        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
191        // - Take a `u8` for writes
192        pub unsafe_read_as_non_zero_u8_safe_acc: u8 [unsafe_get! NonZeroU8] @ 0..=3,
193
194        // Will:
195        // - Return a `u8` on reads
196        // - Take a `U16` for writes, unsafely calling
197        //   `<U16 as UnsafeInto<u8>>::unsafe_into`
198        pub unsafe_write_as_u16_safe_acc: u8 [unsafe_set! U16] @ 4..=7,
199
200        // Will:
201        // - Return a `SpuriouslyFailingU8` on reads, unsafely calling
202        //   `<SpuriouslyFailingU8 as UnsafeFrom<u8>>::unsafe_from`
203        // - Take a `SpuriouslyFailingU8` for writes, unsafely calling
204        //   `<SpuriouslyFailingU8 as UnsafeInto<u8>>::unsafe_into`
205        pub unsafe_as_spuriously_failing_safe_acc: u8 [unsafe_both! SpuriouslyFailingU8] @ 8..=11,
206        // Equivalent to:
207        // pub unsafe_as_spuriously_failing_safe_acc: u8
208        //  [unsafe_get! SpuriouslyFailingU8, unsafe_set! SpuriouslyFailingU8] @ 8..=11,
209
210        // Will:
211        // - Return a `NonZeroU8` on reads, unsafely calling
212        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
213        // - Take a `NonZeroU8` for writes, calling `<NonZeroU8 as Into<u8>>::into`
214        pub unsafe_as_non_zero_u8_safe_acc: u8 [unsafe! NonZeroU8] @ 12..=15,
215        // Equivalent to:
216        // pub unsafe_as_non_zero_u8_safe_acc: u8 [unsafe_get! NonZeroU8, set NonZeroU8] @ 12..=15,
217
218
219        // Unsafe/unchecked conversion functions with safe accessors
220
221        // Will:
222        // - Return a `NonZeroU8` on reads, unsafely calling
223        //   `<NonZeroU8 as UnsafeFrom<u8>>::unsafe_from`
224        // - Take a `u8` for writes
225        pub unsafe_read_as_non_zero_u8_fn_safe_acc: u8 [
226            unsafe_get_fn! NonZeroU8::unsafe_from -> NonZeroU8
227        ] @ 0..=3,
228
229        // Will:
230        // - Return a `u8` on reads
231        // - Take a `U16` for writes, unsafely calling `<U16 as UnsafeInto<u8>>::unsafe_into`
232        pub unsafe_write_as_u16_fn_safe_acc: u8 [unsafe_set_fn! U16::unsafe_into(U16)] @ 4..=7,
233
234
235        // Fallible conversions
236
237        // Will:
238        // - Return a `Result<NonZeroU8, TryFromIntError>` on reads, calling
239        //   `<NonZeroU8 as TryFrom<u8>>::try_from`
240        // - Take a `u8` for writes
241        pub try_read_as_non_zero_u8: u8 [try_get NonZeroU8] @ 0..=3,
242
243        // Will:
244        // - Return a `u8` on reads
245        // - Take a `U16` for writes, returning `Result<(), TryFromIntError>` and calling
246        //   `<U16 as TryInto<u8>>::try_into`
247        pub try_write_as_u16: u8 [try_set U16] @ 4..=7,
248
249        // Will:
250        // - Return a `Result<SpuriouslyFailingU8, ()>` on reads, calling
251        //   `<SpuriouslyFailingU8 as TryFrom<u8>>::try_from`
252        // - Take a `SpuriouslyFailingU8` for writes, returning `Result<(), ()>` and calling
253        //   `<SpuriouslyFailingU8 as TryInto<u8>>::try_into`
254        pub try_both_as_spuriously_failing: u8 [try_both SpuriouslyFailingU8] @ 8..=11,
255        // Equivalent to:
256        // pub try_both_as_spuriously_failing: u8
257        //  [try_get SpuriouslyFailingU8, try_set SpuriouslyFailingU8] @ 8..=11,
258
259        // Will:
260        // - Return a `Result<NonZeroU8, TryFromIntError>` on reads, calling
261        //   `<NonZeroU8 as TryFrom<u8>>::try_from`
262        // - Take a `NonZeroU8` for writes, calling `<NonZeroU8 as Into<u8>>::into`
263        pub try_as_non_zero_u8: u8 [try NonZeroU8] @ 12..=15,
264        // Equivalent to:
265        // pub try_as_non_zero_u8: u8 [try_get NonZeroU8, set NonZeroU8] @ 12..=15,
266
267
268        // Fallible conversion functions
269
270        // Will:
271        // - Return a `Result<NonZeroU8, TryFromIntError>` on reads, calling
272        //   `<NonZeroU8 as TryFrom<u8>>::try_from`
273        // - Take a `u8` for writes
274        pub try_read_as_non_zero_u8_fn: u8 [
275            try_get_fn NonZeroU8::try_from -> Result<NonZeroU8, TryFromIntError>
276        ] @ 0..=3,
277
278        // Will:
279        // - Return a `u8` on reads
280        // - Take a `U16` for writes, returning `Result<(), TryFromIntError>` and calling
281        //   `<U16 as TryInto<u8>>::try_into`
282        pub try_write_as_u16_fn: u8 [
283            try_set_fn U16::try_into(U16) -> Result<u8, TryFromIntError>
284        ] @ 4..=7,
285
286
287        // Unwrapping conversions
288
289        // Will:
290        // - Return a `NonZeroU8` on reads, calling `<NonZeroU8 as TryFrom<u8>>::try_from` and
291        //   unwrapping the result
292        // - Take a `u8` for writes
293        pub unwrap_read_as_non_zero_u8: u8 [unwrap_get NonZeroU8] @ 0..=3,
294
295        // Will:
296        // - Return a `u8` on reads
297        // - Take a `U16` for writes, returning `()`, calling `<U16 as TryInto<u8>>::try_into` and
298        //   unwrapping the result
299        pub unwrap_write_as_u16: u8 [unwrap_set U16] @ 4..=7,
300
301        // Will:
302        // - Return a `SpuriouslyFailingU8` on reads, calling
303        //   `<SpuriouslyFailingU8 as TryFrom<u8>>::try_from` and unwrapping the result
304        // - Take a `SpuriouslyFailingU8` for writes, returning `()`, calling
305        //   `<SpuriouslyFailingU8 as TryInto<u8>>::try_into` and unwrapping the result
306        pub unwrap_both_as_spuriously_failing: u8 [unwrap_both SpuriouslyFailingU8] @ 8..=11,
307        // Equivalent to:
308        // pub try_both_as_spuriously_failing: u8
309        //  [try_get SpuriouslyFailingU8, try_set SpuriouslyFailingU8] @ 8..=11,
310
311        // Will:
312        // - Return a `NonZeroU8` on reads, calling `<NonZeroU8 as TryFrom<u8>>::try_from` and
313        //   unwrapping the result
314        // - Take a `NonZeroU8` for writes, calling `<NonZeroU8 as Into<u8>>::into`
315        pub unwrap_as_non_zero_u8: u8 [unwrap NonZeroU8] @ 12..=15,
316        // Equivalent to:
317        // pub unwrap_as_non_zero_u8: u8 [unwrap_get NonZeroU8, set NonZeroU8] @ 12..=15,
318
319
320        // Unwrapping conversion functions
321
322        // Will:
323        // - Return a `NonZeroU8` on reads, calling `<NonZeroU8 as TryFrom<u8>>::try_from` and
324        //   unwrapping the result
325        // - Take a `u8` for writes
326        pub unwrap_read_as_non_zero_u8_fn: u8 [unwrap_get_fn NonZeroU8::try_from -> NonZeroU8] @ 0..=3,
327
328        // Will:
329        // - Return a `u8` on reads
330        // - Take a `U16` for writes, returning `()`, calling `<U16 as TryInto<u8>>::try_into` and
331        //   unwrapping the result
332        pub unwrap_write_as_u16_fn: u8 [unwrap_set_fn U16::try_into(U16)] @ 4..=7,
333    }
334}
335
336/// An enum showcasing the `ConvRaw` derive for converting from/into integers.
337#[derive(ConvRaw)]
338pub enum ConvRawIntExample {
339    A,
340    B = 2,
341    C,
342    D = -1,
343    E = 1,
344    F = -128,
345    G = 128,
346}
347
348/// An enum showcasing the `ConvRaw` derive for converting from/into booleans.
349#[derive(ConvRaw)]
350pub enum ConvRawBoolExample {
351    False, // Implicitly, this value is treated as 0 (false).
352    True,
353}
354
355#[cfg(feature = "nightly")]
356#[cfg_attr(all(doc, feature = "nightly"), doc(cfg(feature = "nightly")))]
357/// A type showcasing the `UnwrapBits` derive.
358#[derive(UnwrapBits)]
359pub struct UnwrapBitsExample(NonZeroU8);