bondrewd_derive/lib.rs
1//! Fast and easy bitfield proc macro
2//!
3//! Provides a proc macro for compressing a data structure with data which can be expressed with bit
4//! lengths that are not a power of Two.
5//!
6//! # Derive Bitfields
7//! - Implements the [`Bitfields`](https://docs.rs/bondrewd/latest/bondrewd/trait.Bitfields.html) trait
8//! which offers from\into bytes functions that are non-failable and convert the struct from/into sized
9//! u8 arrays ([u8; {total_bit_length * 8}]).
10//! - `read` and `write` functions that allow the field to be accessed or overwritten within a sized u8 array.
11//! - More information about how each field is handled (bit length, endianness, ..), as well as structure
12//! wide effects (bit position, default field endianness, ..), can be found on the
13//! [`Bitfields Derive`](Bitfields) page.
14//!
15//! For example we can define a data structure with 7 total bytes as:
16//! - A boolean field named one will be the first bit.
17//! - A floating point field named two will be the next 32 bits. floats must be full sized
18//! currently.
19//! - A signed integer field named three will be the next 14 bits.
20//! - An unsigned integer field named four will be the next 6 bits.
21//!
22//! ```
23//! // Users code
24//! use bondrewd::*;
25//! #[derive(Bitfields)]
26//! #[bondrewd(default_endianness = "be")]
27//! struct SimpleExample {
28//! // fields that are as expected do not require attributes.
29//! one: bool,
30//! two: f32,
31//! #[bondrewd(bit_length = 14)]
32//! three: i16,
33//! #[bondrewd(bit_length = 6)]
34//! four: u8,
35//! }
36//! ```
37//! Generated Code with function logic omitted. [Full Generated Code](#full-example-generated-code)
38//! ```compile_fail
39//! impl Bitfields<7usize> for SimpleExample {
40//! const BIT_SIZE: usize = 53usize;
41//! fn into_bytes(self) -> [u8; 7usize] { .. }
42//! fn from_bytes(mut input_byte_buffer: [u8; 7usize]) -> Self { .. }
43//! }
44//! impl SimpleExample {
45//! pub fn read_one(input_byte_buffer: &[u8; 7usize]) -> bool { .. }
46//! pub fn read_two(input_byte_buffer: &[u8; 7usize]) -> f32 { .. }
47//! pub fn read_three(input_byte_buffer: &[u8; 7usize]) -> i16 { .. }
48//! pub fn read_four(input_byte_buffer: &[u8; 7usize]) -> u8 { .. }
49//! pub fn write_one(output_byte_buffer: &mut [u8; 7usize], mut one: bool) { .. }
50//! pub fn write_two(output_byte_buffer: &mut [u8; 7usize], mut two: f32) { .. }
51//! pub fn write_three(output_byte_buffer: &mut [u8; 7usize], mut three: i16) { .. }
52//! pub fn write_four(output_byte_buffer: &mut [u8; 7usize], mut four: u8) { .. }
53//! }
54//! ```
55//! # Derive BitfieldEnum
56//! - Implements the [`BitfieldEnum`](https://docs.rs/bondrewd/latest/bondrewd/trait.BitfieldEnum.html)
57//! trait which offers from\into primitive functions that are non-failable and convert the enum from/into
58//! a primitive type (u8 is the only currently testing primitive).
59//! - More information about controlling the end result (define variant values, define a catch/invalid
60//! variant) can be found on the [`BitfieldEnum Derive`](BitfieldEnum) page.
61//!
62//! ```
63//! // Users code
64//! use bondrewd::BitfieldEnum;
65//! #[derive(BitfieldEnum)]
66//! enum SimpleEnum {
67//! Zero,
68//! One,
69//! Six = 6,
70//! Two,
71//! }
72//! ```
73//! Full Generated Struct Code
74//! ```
75//! # use bondrewd::BitfieldEnum;
76//! # enum SimpleEnum {
77//! # Zero,
78//! # One,
79//! # Six = 6,
80//! # Two,
81//! # }
82//! // use statement and SimpleEnum definition are hidden.
83//! impl bondrewd::BitfieldEnum for SimpleEnum {
84//! type Primitive = u8;
85//! fn into_primitive(self) -> u8 {
86//! match self {
87//! Self::Zero => 0,
88//! Self::One => 1,
89//! Self::Six => 6,
90//! Self::Two => 2,
91//! }
92//! }
93//! fn from_primitive(input: u8) -> Self {
94//! match input {
95//! 0 => Self::Zero,
96//! 1 => Self::One,
97//! 6 => Self::Six,
98//! _ => Self::Two,
99//! }
100//! }
101//! }
102//! ```
103//!
104//! # Crate Features
105//! Slice functions are convenience functions for reading/wring single or multiple fields without reading
106//! the entire structure. Bondrewd will provided 2 ways to access the field:
107//! * Single field access. These are functions that are added along side the standard read/write field
108//! functions in the impl for the input structure. read/write slice functions will check the length of
109//! the slice to insure the amount to bytes needed for the field (NOT the entire structure) are present and
110//! return BitfieldSliceError if not enough bytes are present.
111//! * `fn read_slice_{field}(&[u8]) -> Result<{field_type}, bondrewd::BondrewdSliceError> { .. }`
112//! * `fn write_slice_{field}(&mut [u8], {field_type}) -> Result<(), bondrewd::BondrewdSliceError> { .. }`
113//! * Multiple field access.
114//! * `fn check_slice(&[u8]) -> Result<{struct_name}Checked, bondrewd::BondrewdSliceError> { .. }`
115//! This function will check the size of the slice, if the slice is big enough it will return
116//! a checked structure. the structure will be the same name as the input structure with
117//! "Checked" tacked onto the end. the Checked Structure will have getters for each of the input
118//! structures fields, the naming is the same as the standard `read_{field}` functions.
119//! * `fn read_{field}(&self) -> {field_type} { .. }`
120//! * `fn check_slice_mut(&mut [u8]) -> Result<{struct_name}CheckedMut, bondrewd::BondrewdSliceError> { .. }`
121//! This function will check the size of the slice, if the slice is big enough it will return
122//! a checked structure. the structure will be the same name as the input structure with
123//! "CheckedMut" tacked onto the end. the Checked Structure will have getters and setters for each
124//! of the input structures fields, the naming is the same as the standard `read_{field}` and
125//! `write_{field}` functions.
126//! * `fn read_{field}(&self) -> {field_type} { .. }`
127//! * `fn write_{field}(&mut self) -> {field_type} { .. }`
128//!
129//! Example Cargo.toml Bondrewd dependency
130//! `bondrewd = { version = "^0.1", features = ["derive", "slice_fns"] }`
131//! Example Generated Slice Api:
132//! ```compile_fail
133//! impl Simple {
134//! pub fn check_slice(buffer: &[u8]) -> Result<SimpleChecked, BitfieldSliceError> { .. }
135//! pub fn check_slice_mut(buffer: &mut [u8]) -> Result<SimpleCheckedMut, BitfieldSliceError> { .. }
136//! #[inline]
137//! pub fn read_slice_one(input_byte_buffer: &[u8]) -> Result<u8, BitfieldSliceError> { .. }
138//! #[inline]
139//! pub fn read_slice_two(input_byte_buffer: &[u8]) -> Result<bool, BitfieldSliceError> { .. }
140//! #[inline]
141//! pub fn read_slice_three(input_byte_buffer: &[u8]) -> Result<u8, BitfieldSliceError> { .. }
142//! #[inline]
143//! pub fn write_slice_one(output_byte_buffer: &mut [u8],one: u8) -> Result<(), BitfieldSliceError> { .. }
144//! #[inline]
145//! pub fn write_slice_two(output_byte_buffer: &mut [u8],two: bool) -> Result<(), BitfieldSliceError> { .. }
146//! #[inline]
147//! pub fn write_slice_three(output_byte_buffer: &mut [u8],three: u8) -> Result<(), BitfieldSliceError> { .. }
148//! }
149//! struct SimpleChecked<'a> {
150//! buffer: &'a [u8],
151//! }
152//! impl<'a> SimpleChecked<'a> {
153//! #[inline]
154//! pub fn read_one(&self) -> u8 { .. }
155//! #[inline]
156//! pub fn read_two(&self) -> bool { .. }
157//! #[inline]
158//! pub fn read_three(&self) -> u8 { .. }
159//! }
160//! struct SimpleCheckedMut<'a> {
161//! buffer: &'a mut [u8],
162//! }
163//! impl<'a> SimpleCheckedMut<'a> {
164//! #[inline]
165//! pub fn read_one(&self) -> u8 { .. }
166//! #[inline]
167//! pub fn read_two(&self) -> bool { .. }
168//! #[inline]
169//! pub fn read_three(&self) -> u8 { .. }
170//! #[inline]
171//! pub fn write_one(&mut self, one: u8) { .. }
172//! #[inline]
173//! pub fn write_two(&mut self, two: bool) { .. }
174//! #[inline]
175//! pub fn write_three(&mut self, three: u8) { .. }
176//! }
177//! ```
178//!
179//! `hex_fns` provided from/into hex functions like from/into bytes. The hex inputs/outputs are \[u8;N\]
180//! where N is double the calculated bondrewd STRUCT_SIZE. Hex encoding and decoding is based off the
181//! [hex](https://crates.io/crates/hex) crate's from/into slice functions but with statically sized
182//! arrays so we could eliminate sizing errors.
183//!
184//! ### Full Example Generated Code
185//! ```
186//! use bondrewd::*;
187//! struct SimpleExample {
188//! one: bool,
189//! two: f32,
190//! three: i16,
191//! four: u8,
192//! }
193//! impl Bitfields<7usize> for SimpleExample {
194//! const BIT_SIZE: usize = 53usize;
195//! fn into_bytes(self) -> [u8; 7usize] {
196//! let mut output_byte_buffer: [u8; 7usize] = [0u8; 7usize];
197//! let one = self.one;
198//! output_byte_buffer[0usize] |= ((one as u8) << 7usize) & 128u8;
199//! let two = self.two;
200//! let two_bytes = (two.to_bits().rotate_right(1u32)).to_be_bytes();
201//! output_byte_buffer[0usize] |= two_bytes[0usize] & 127u8;
202//! output_byte_buffer[1usize] |= two_bytes[1usize];
203//! output_byte_buffer[2usize] |= two_bytes[2usize];
204//! output_byte_buffer[3usize] |= two_bytes[3usize];
205//! output_byte_buffer[4usize] |= two_bytes[0] & 128u8;
206//! let three = self.three;
207//! let three_bytes = (three.rotate_right(7u32)).to_be_bytes();
208//! output_byte_buffer[4usize] |= three_bytes[1usize] & 127u8;
209//! output_byte_buffer[5usize] |= three_bytes[0] & 254u8;
210//! let four = self.four;
211//! let four_bytes = (four.rotate_right(5u32)).to_be_bytes();
212//! output_byte_buffer[5usize] |= four_bytes[0usize] & 1u8;
213//! output_byte_buffer[6usize] |= four_bytes[0] & 248u8;
214//! output_byte_buffer
215//! }
216//! fn from_bytes(mut input_byte_buffer: [u8; 7usize]) -> Self {
217//! let one = Self::read_one(&input_byte_buffer);
218//! let two = Self::read_two(&input_byte_buffer);
219//! let three = Self::read_three(&input_byte_buffer);
220//! let four = Self::read_four(&input_byte_buffer);
221//! Self {
222//! one,
223//! two,
224//! three,
225//! four,
226//! }
227//! }
228//! }
229//! impl SimpleExample {
230//! #[inline]
231//! pub fn read_one(input_byte_buffer: &[u8; 7usize]) -> bool {
232//! ((input_byte_buffer[0usize] & 128u8) != 0)
233//! }
234//! #[inline]
235//! pub fn read_two(input_byte_buffer: &[u8; 7usize]) -> f32 {
236//! f32::from_bits(
237//! u32::from_be_bytes({
238//! let mut two_bytes: [u8; 4usize] = [0u8; 4usize];
239//! two_bytes[0usize] |= input_byte_buffer[0usize] & 127u8;
240//! two_bytes[1usize] |= input_byte_buffer[1usize];
241//! two_bytes[2usize] |= input_byte_buffer[2usize];
242//! two_bytes[3usize] |= input_byte_buffer[3usize];
243//! two_bytes[0] |= input_byte_buffer[4usize] & 128u8;
244//! two_bytes
245//! })
246//! .rotate_left(1u32),
247//! )
248//! }
249//! #[inline]
250//! pub fn read_three(input_byte_buffer: &[u8; 7usize]) -> i16 {
251//! i16::from_be_bytes({
252//! let mut three_bytes: [u8; 2usize] = if (input_byte_buffer[4usize] & 64u8) == 64u8 {
253//! [1u8, 128u8]
254//! } else {
255//! [0u8; 2usize]
256//! };
257//! three_bytes[1usize] |= input_byte_buffer[4usize] & 127u8;
258//! three_bytes[0] |= input_byte_buffer[5usize] & 254u8;
259//! three_bytes
260//! })
261//! .rotate_left(7u32)
262//! }
263//! #[inline]
264//! pub fn read_four(input_byte_buffer: &[u8; 7usize]) -> u8 {
265//! u8::from_be_bytes({
266//! let mut four_bytes: [u8; 1usize] = [0u8; 1usize];
267//! four_bytes[0usize] |= input_byte_buffer[5usize] & 1u8;
268//! four_bytes[0] |= input_byte_buffer[6usize] & 248u8;
269//! four_bytes
270//! })
271//! .rotate_left(5u32)
272//! }
273//! #[inline]
274//! pub fn write_one(output_byte_buffer: &mut [u8; 7usize], mut one: bool) {
275//! output_byte_buffer[0usize] &= 127u8;
276//! output_byte_buffer[0usize] |= ((one as u8) << 7usize) & 128u8;
277//! }
278//! #[inline]
279//! pub fn write_two(output_byte_buffer: &mut [u8; 7usize], mut two: f32) {
280//! output_byte_buffer[0usize] &= 128u8;
281//! output_byte_buffer[1usize] = 0u8;
282//! output_byte_buffer[2usize] = 0u8;
283//! output_byte_buffer[3usize] = 0u8;
284//! output_byte_buffer[4usize] &= 127u8;
285//! let two_bytes = (two.to_bits().rotate_right(1u32)).to_be_bytes();
286//! output_byte_buffer[0usize] |= two_bytes[0usize] & 127u8;
287//! output_byte_buffer[1usize] |= two_bytes[1usize];
288//! output_byte_buffer[2usize] |= two_bytes[2usize];
289//! output_byte_buffer[3usize] |= two_bytes[3usize];
290//! output_byte_buffer[4usize] |= two_bytes[0] & 128u8;
291//! }
292//! #[inline]
293//! pub fn write_three(output_byte_buffer: &mut [u8; 7usize], mut three: i16) {
294//! output_byte_buffer[4usize] &= 128u8;
295//! output_byte_buffer[5usize] &= 1u8;
296//! let three_bytes = (three.rotate_right(7u32)).to_be_bytes();
297//! output_byte_buffer[4usize] |= three_bytes[1usize] & 127u8;
298//! output_byte_buffer[5usize] |= three_bytes[0] & 254u8;
299//! }
300//! #[inline]
301//! pub fn write_four(output_byte_buffer: &mut [u8; 7usize], mut four: u8) {
302//! output_byte_buffer[5usize] &= 254u8;
303//! output_byte_buffer[6usize] &= 7u8;
304//! let four_bytes = (four.rotate_right(5u32)).to_be_bytes();
305//! output_byte_buffer[5usize] |= four_bytes[0usize] & 1u8;
306//! output_byte_buffer[6usize] |= four_bytes[0] & 248u8;
307//! }
308//! }
309//! ```
310extern crate proc_macro;
311mod enums;
312use enums::parse::EnumInfo;
313mod structs;
314use structs::common::StructInfo;
315use structs::from_bytes::create_from_bytes_field_quotes;
316use structs::into_bytes::create_into_bytes_field_quotes;
317
318use proc_macro::TokenStream;
319use quote::{format_ident, quote};
320use syn::{parse_macro_input, DeriveInput};
321
322/// Generates an implementation of the bondrewd::Bitfield trait, as well as peek and set functions for direct
323/// sized u8 arrays access. This crate is designed so that attributes are only required for fields that
324/// are not what you would expect without the attribute. For example if you provide a u8 fields with no
325/// attributes, the field would be assumed to be the next 8 bits after the field before it. If a field
326/// of bool type without attributes is defined, the field would be assumed to be the next bit after
327/// the field before it.
328///
329/// # Supported Field Types
330/// - All primitives other than usize and isize (i believe ambiguous sizing is bad for this type of work).
331/// - Floats currently must be full sized.
332/// - Its important to know that there is a small runtime cost for signed numbers.
333/// - Enums which implement the BitfieldEnum trait in Bondrewd.
334/// - Structs which implement the Bitfield trait in Bondrewd.
335///
336/// # Struct Attributes
337/// - `default_endianness = {"le" or "be"}` Describes a default endianness for primitive fields.
338/// [example](#endianness-examples)
339/// - `read_from = {"msb0" or "lsb0"}` Defines bit positioning. which end of the byte array to start at.
340/// [example](#bit-positioning-examples)
341/// - `enforce_bytes = {BYTES}` Adds a check that requires total bytes defined by fields to equal provided
342/// BYTES. [example](#enforce-bits-examples)
343/// - `enforce_bits = {BITS}` Adds a check that requires total bits defined by fields to equal provided
344/// BITS. [example](#enforce-bits-examples)
345/// - `enforce_full_bytes` Adds a check that requires total bits defined by fields to equal a multiple of 8.
346/// [example](#enforce-full-bytes-example)
347/// - `fill_bytes = {BYTES}` Will force the output/input byte array size to be the provided SIZE amount of
348/// bytes. [example](#fill-bytes-examples)
349/// - `reverse` Defines that the entire byte array should be read backward (first byte index becomes last
350/// byte index). This has no runtime cost. [example](#reverse-example)
351///
352/// # Field Attributes
353/// - `bit_length = {BITS}` Define the total amount of bits to use when condensed. [example](#simple-example)
354/// - `byte_length = {BYTES}` Define the total amount of bytes to use when condensed. [example](#simple-example)
355/// - `endianness = {"le" or "be"}` Define per field endianess. [example](#endianness-examples)
356/// - `block_bit_length = {BITS}` Describes a bit length for the entire array dropping lower indexes first.
357/// [example](#bitfield-array-examples)
358/// - `block_byte_length = {BYTES}` Describes a byte length for the entire array dropping lower indexes
359/// first. [example](#bitfield-array-examples)
360/// - `element_bit_length = {BITS}` Describes a bit length for each element of an array. (default array
361/// type). [example](#bitfield-array-examples)
362/// - `element_byte_length = {BYTES}` Describes a byte length for each element of an array. (default array
363/// type). [example](#bitfield-array-examples)
364/// - `enum_primitive = "u8"` Defines the size of the enum. the BitfieldEnum currently only supports u8.
365/// [example](#enum-examples)
366/// - `struct_size = {SIZE}` Defines the field as a struct which implements the Bitfield trait and the
367/// BYTE_SIZE const defined in said trait. [example](#bitfield-struct-as-field-examples)
368/// - `reserve` Defines that this field should be ignored in from and into bytes functions.
369/// [example](#reserve-examples)
370/// - Reserve requires the fields type to impl ['Default'](https://doc.rust-lang.org/std/default/trait.Default.html).
371/// due to from_bytes needed to provided a value.
372///
373/// # Experimental Field Attributes
374/// if you decide to use these remember that they have not been exhaustively tested. when using
375/// experimental attributes please be careful and report unexpected behavior to our github issues.
376/// - `bits = "{RANGE}"` - Define the bit indexes yourself rather than let the proc macro figure
377/// it out. using a rust range in quotes. the RANGE must provide a inclusively below and exclusively
378/// above bounded range (ex. bits = "0..2" means use bits 0 and 1 but NOT 2).
379/// [example](#bits-attribute-example)
380/// - `read_only` - Bondrewd will not include writing/into_bytes logic for the field.
381/// - `overlapping_bits = {BITS}` - Tells bondrewd that the provided BITS amount is shared
382/// with at least 1 other field and should not be included in the overall structure size.
383/// - `redundant` - Tells bondrewd that this field's bits are all shared by at least one other field.
384/// Bondrewd will not include the bit length in the structures overall bit length
385/// (because they are redundant).
386/// [example](#redundant-examples)
387/// - Bondrewd will read the assigned bits but will not write.
388/// - This behaves exactly as combining the attributes:
389/// - `read_only`
390/// - `overlapping_bits = {FIELD_BIT_LENGTH}` FIELD_BIT_LENGTH being the total amount of bits that the field uses.
391///
392/// # Simple Example
393/// This example is on the front page for bondrewd-derive. Here i will be adding some asserts to show what
394/// to expect.
395/// I will be defining a data structure with 7 total bytes as:
396/// - A boolean field named one will be the first bit.
397/// - A floating point field named two will be the next 32 bits. floats must be full sized
398/// currently.
399/// - A signed integer field named three will be the next 14 bits.
400/// - An unsigned integer field named four will be the next 6 bits.
401/// - Because these fields do not add up to a number divisible by 8 the last 3 bits will be unused.
402/// ```
403/// use bondrewd::*;
404/// #[derive(Bitfields)]
405/// #[bondrewd(default_endianness = "be")]
406/// struct SimpleExample {
407/// // fields that are as expected do not require attributes.
408/// one: bool,
409/// two: f32,
410/// #[bondrewd(bit_length = 14)]
411/// three: i16,
412/// #[bondrewd(bit_length = 6)]
413/// four: u8,
414/// }
415///
416/// assert_eq!(7, SimpleExample::BYTE_SIZE);
417/// assert_eq!(53, SimpleExample::BIT_SIZE);
418/// let mut bytes = SimpleExample {
419/// one: false,
420/// two: -4.25,
421/// three: -1034,
422/// four: 63,
423/// }.into_bytes();
424/// // check the output binary is correct. (i did math by hand
425/// // to get the binary). each field is separated by a underscore
426/// // in the binary assert to make it easy to see.
427/// assert_eq!([
428/// 0b0_1100000, // one_two,
429/// 0b01000100, // two,
430/// 0b00000000, // two,
431/// 0b00000000, // two,
432/// 0b0_1110111, // two_three,
433/// 0b1110110_1, // three_four,
434/// 0b11111_000, // four_unused
435/// ], bytes);
436/// // use read functions to get the fields value without
437/// // doing a from_bytes call.
438/// assert_eq!(false, SimpleExample::read_one(&bytes));
439/// assert_eq!(-4.25, SimpleExample::read_two(&bytes));
440/// assert_eq!(-1034, SimpleExample::read_three(&bytes));
441/// assert_eq!(63, SimpleExample::read_four(&bytes));
442/// // overwrite the values with new ones in the byte array.
443/// SimpleExample::write_one(&mut bytes, true);
444/// SimpleExample::write_two(&mut bytes, 5.5);
445/// SimpleExample::write_three(&mut bytes, 511);
446/// SimpleExample::write_four(&mut bytes, 0);
447/// // from bytes uses the read function so there is no need to
448/// // assert the read functions again.
449/// let reconstructed = SimpleExample::from_bytes(bytes);
450/// // check the values read by from bytes and check if they are
451/// // what we wrote to the bytes NOT the origanal values.
452/// assert_eq!(true,reconstructed.one);
453/// assert_eq!(5.5,reconstructed.two);
454/// assert_eq!(511,reconstructed.three);
455/// assert_eq!(0,reconstructed.four);
456/// ```
457/// # Reverse Example
458/// Reverse simply makes Bondrewd index the bytes in the output/input buffers in the opposite order.
459/// First index becomes last index and last index becomes the first.
460/// ```
461/// use bondrewd::*;
462/// #[derive(Bitfields)]
463/// struct Example {
464/// one: u8,
465/// two: u8,
466/// three: u8,
467/// four: u8,
468/// }
469///
470/// #[derive(Bitfields)]
471/// #[bondrewd(reverse)]
472/// struct ExampleReversed {
473/// one: u8,
474/// two: u8,
475/// three: u8,
476/// four: u8,
477/// }
478///
479/// let test = Example {
480/// one: 0,
481/// two: u8::MAX,
482/// three: 0,
483/// four: 0b01010101,
484/// };
485/// let test_reverse = ExampleReversed {
486/// one: 0,
487/// two: u8::MAX,
488/// three: 0,
489/// four: 0b01010101,
490/// };
491/// assert_eq!(test.into_bytes(), [0b00000000, 0b11111111, 0b000000, 0b01010101]);
492/// assert_eq!(test_reverse.into_bytes(), [0b01010101, 0b000000, 0b11111111, 0b00000000]);
493/// ```
494/// # Bit Positioning Examples
495/// Here Bit positioning will control where bit 0 is. for example if you have a field with 2 bits then
496/// 2 fields with 3 bits each, bit positioning will define the direction in which it traverses bit indices,
497/// so in our example if 0 is the least significant bit the first field would be the least significant bit
498/// in the last index in the byte array. `msb0` is the default.
499/// ```
500/// use bondrewd::*;
501/// #[derive(Bitfields)]
502/// #[bondrewd(read_from = "msb0")]
503/// struct ExampleMSB {
504/// #[bondrewd(bit_length = 2)]
505/// one: u8,
506/// #[bondrewd(bit_length = 3)]
507/// two: u8,
508/// #[bondrewd(bit_length = 3)]
509/// three: u8,
510/// }
511///
512/// #[derive(Bitfields)]
513/// #[bondrewd(read_from = "lsb0")]
514/// struct ExampleLSB {
515/// #[bondrewd(bit_length = 2)]
516/// one: u8,
517/// #[bondrewd(bit_length = 3)]
518/// two: u8,
519/// #[bondrewd(bit_length = 3)]
520/// three: u8,
521/// }
522///
523/// let test_msb = ExampleMSB {
524/// one: 0,
525/// two: 5,
526/// three: 0,
527/// };
528/// let test_lsb = ExampleLSB {
529/// one: 0,
530/// two: 5,
531/// three: 0,
532/// };
533/// // in msb0 field one is the first 2 bits followed by field two
534/// // then field three is the last 3 bits.
535/// assert_eq!(test_msb.into_bytes(), [0b00_101_000]);
536/// // in msb0 field three is the first 3 bits followed by field
537/// // 2 then field one being the last 2 bits
538/// assert_eq!(test_lsb.into_bytes(), [0b000_101_00]);
539/// ```
540/// When using `reverse` and `read_from` in the same structure:
541/// - `lsb0` would begin at the least significant bit in the first byte.
542/// - 'msb0` would begin at the most significant bit in the last byte.
543/// ```
544/// use bondrewd::*;
545/// #[derive(Bitfields)]
546/// #[bondrewd(read_from = "msb0", reverse)]
547/// struct ExampleMSB {
548/// #[bondrewd(bit_length = 5)]
549/// one: u8,
550/// #[bondrewd(bit_length = 4)]
551/// two: u8,
552/// #[bondrewd(bit_length = 7)]
553/// three: u8,
554/// }
555///
556/// #[derive(Bitfields)]
557/// #[bondrewd(read_from = "lsb0", reverse)]
558/// struct ExampleLSB {
559/// #[bondrewd(bit_length = 5)]
560/// one: u8,
561/// #[bondrewd(bit_length = 4)]
562/// two: u8,
563/// #[bondrewd(bit_length = 7)]
564/// three: u8,
565/// }
566///
567/// let test_msb = ExampleMSB {
568/// one: 0,
569/// two: u8::MAX,
570/// three: 0,
571/// };
572/// let test_lsb = ExampleLSB {
573/// one: 0,
574/// two: u8::MAX,
575/// three: 0,
576/// };
577/// // here the 1's belong to feild two. i hope this is understandable.
578/// assert_eq!(test_msb.into_bytes(), [0b10000000, 0b00000111]);
579/// assert_eq!(test_lsb.into_bytes(), [0b11100000, 0b00000001]);
580/// ```
581/// # Endianness Examples
582/// There are 2 ways to define endianess of fields that require endianness (multi-byte numbers, char, ...)
583/// - Default endianness which will give provided endianness to all fields that require endianness but
584/// do not have it defined.
585/// - Per field endianess which defines the endianness of a particular field.
586///
587/// Default endianness and per fields endianness can also be used in the same struct
588/// ```
589/// use bondrewd::*;
590/// #[derive(Bitfields)]
591/// // tell bondrewd to default to Big Endian
592/// #[bondrewd(default_endianness = "be")]
593/// struct SimpleExample {
594/// // this field will be given the default endianness
595/// one: u16,
596/// // here we give the field endianness which means it will not use default endianness.
597/// #[bondrewd(endianness = "le")]
598/// two: u16,
599/// }
600///
601/// let test = SimpleExample {
602/// one: 5,
603/// two: 5,
604/// };
605/// // check that each field are in the correct endianness
606/// assert_eq!(test.into_bytes(),[0b00000000, 0b00000101, 0b00000101, 0b00000000]);
607/// ```
608/// If you define the endianness of all values that require it default_endianness is not required.
609/// ```
610/// use bondrewd::*;
611/// #[derive(Bitfields)]
612/// struct SimpleExample {
613/// #[bondrewd(endianness = "be")]
614/// one: u16,
615/// #[bondrewd(endianness = "le")]
616/// two: u16,
617/// // because this field does not use more than 1 byte, endianness is not required.
618/// three: bool,
619/// }
620///
621/// let test = SimpleExample {
622/// one: 5,
623/// two: 5,
624/// three: true,
625/// };
626/// // check that each field are in the correct endianness
627/// assert_eq!(test.into_bytes(),[0b00000000, 0b00000101, 0b00000101, 0b00000000, 0b10000000]);
628/// ```
629/// # Bitfield Struct as Field Examples
630/// Inner structs must implement the
631/// [`Bitfields`](https://docs.rs/bondrewd/latest/bondrewd/trait.Bitfields.html) trait and be given the
632/// `struct_size = {BYTE_SIZE}, the BYTE_SIZE being the number of bytes in the outputs byte array or
633/// value in the traits const BYTE_SIZE.
634/// ```
635/// // this struct uses 52 total bits which means the total BYTE_SIZE is 7.
636/// use bondrewd::*;
637/// #[derive(Bitfields)]
638/// #[bondrewd(default_endianness = "be")]
639/// struct Simple {
640/// #[bondrewd(bit_length = 3)]
641/// one: u8,
642/// #[bondrewd(bit_length = 27)]
643/// two: char,
644/// #[bondrewd(bit_length = 14)]
645/// three: u16,
646/// four: i8,
647/// }
648///
649/// #[derive(Bitfields)]
650/// #[bondrewd(default_endianness = "be")]
651/// struct SimpleWithStruct {
652/// #[bondrewd(struct_size = 7)]
653/// one: Simple,
654/// // structs can also be used in arrays.
655/// #[bondrewd(struct_size = 7)]
656/// two: [Simple; 2],
657/// }
658/// ```
659/// We can also trim the struct to a bit length, this can be very useful for struct that do not use the
660/// full amount of bits available in the byte array. For example if we have a struct that uses 4 bits
661/// leaving the remaining 4 bits as unused data, we can make a structure with 2 of the bits structure
662/// that still only uses 1 byte.
663/// ```
664/// // this struct uses 4 total bits which means the total BYTE_SIZE is 1.
665/// use bondrewd::*;
666/// #[derive(Bitfields, Clone)]
667/// #[bondrewd(default_endianness = "be")]
668/// struct Simple {
669/// #[bondrewd(bit_length = 2)]
670/// one: u8,
671/// #[bondrewd(bit_length = 2)]
672/// two: u8,
673/// }
674///
675/// #[derive(Bitfields)]
676/// #[bondrewd(default_endianness = "be")]
677/// struct SimpleWithStruct {
678/// #[bondrewd(struct_size = 1, bit_length = 4)]
679/// one: Simple,
680/// #[bondrewd(struct_size = 1, bit_length = 4)]
681/// two: Simple,
682/// }
683///
684/// // SimpleWithStruct uses the amount of bits that 2
685/// // Simple structures would use.
686/// assert_eq!(SimpleWithStruct::BIT_SIZE, Simple::BIT_SIZE * 2);
687/// // But both structures use 1 byte.
688/// assert_eq!(SimpleWithStruct::BYTE_SIZE, 1);
689/// assert_eq!(SimpleWithStruct::BYTE_SIZE, Simple::BYTE_SIZE);
690/// ```
691/// # Bitfield Array Examples
692/// There are 2 types of arrays in Bondrewd:
693/// - Block Arrays are "bit chucks" that define a total-used-bits amount and will drop bits starting
694/// at the lowest index.
695/// - Element Arrays treat each element of the array as its own field and requires a per element
696/// bit-length.
697/// ```
698/// use bondrewd::*;
699/// #[derive(Bitfields)]
700/// #[bondrewd(default_endianness = "be")]
701/// struct SimpleWithArray {
702/// // each u8 in the array contains 4 bits of useful information.
703/// #[bondrewd(element_bit_length = 4)]
704/// one: [u8; 4],
705/// // due to no attributes being present for field `two`,
706/// // no bits are missing and the type of array shouldn't
707/// // matter, Bondrewd will use element array logic. also boolean
708/// // values are assumed to be 1 bit so this will produce
709/// // 5 bits in an output.
710/// #[bondrewd(element_bit_length = 1)]
711/// two: [bool; 5],
712/// // the total amount bits in the array should be 20.
713/// // [{4 bits},{8 bits},{8 bits}]
714/// #[bondrewd(block_bit_length = 20)]
715/// three: [u8; 3],
716/// }
717///
718/// let test = SimpleWithArray {
719/// // the first 4 bits in index 0 and 2 are 1's to show
720/// // that they will not be in the final result due to
721/// // each element being set to 4 bits, meaning the values
722/// // in those indices will become 0 after into_bytes is called.
723/// one: [0b11110000, 0b00001111, 0b11110000, 0b00001001],
724/// two: [false, true, false, true, false],
725/// // its also worth noting that index 0 here will lose the 4
726/// // most significant bits.
727/// three: [u8::MAX, 0, 0b10101010],
728/// };
729/// assert_eq!(test.into_bytes(),
730/// [0b0000_1111, // one[0 and 1]
731/// 0b0000_1001, // one[2 and 3]
732/// 0b01010_111, // two and three[0]
733/// 0b1_0000000, // remaining three[0] and three[1]
734/// 0b0_1010101, // remaining three[1] and three[2]
735/// 0b0_0000000]);// remaining three[2] and 7 unused bits.
736/// ```
737/// Structures and Enums can also be used in arrays but there are some extra things to consider.
738/// - If bit_length of the structs or enums needs to be smaller than the output of either into_bytes or
739/// into_primitive then it is recommended to use element arrays.
740/// - Block Arrays, in my opinion, shouldn't be used for Structs or Enums. because in the below example
741/// if the compressed_structures field was to use `block_bit_length = 104` the array would use
742/// 48 bits for index 0 and 56 bits for index 1.
743/// ```
744/// // this struct uses 52 total bits which means the total
745/// // BYTE_SIZE is 7.
746/// use bondrewd::*;
747/// #[derive(Bitfields)]
748/// #[bondrewd(default_endianness = "be")]
749/// struct SimpleStruct {
750/// #[bondrewd(bit_length = 3)]
751/// one: u8,
752/// #[bondrewd(bit_length = 27)]
753/// two: char,
754/// #[bondrewd(bit_length = 14)]
755/// three: u16,
756/// four: i8,
757/// }
758///
759/// // this enum has 4 variants therefore only uses 2 bits
760/// // out of 8 in the primitive type.
761/// #[derive(BitfieldEnum)]
762/// enum SimpleEnum {
763/// Zero,
764/// One,
765/// Two,
766/// Three,
767/// }
768///
769/// #[derive(Bitfields)]
770/// #[bondrewd(default_endianness = "be")]
771/// struct ArraysWithStructsAndEnums {
772/// // if the bit size should be the full size of the primitive, only
773/// // the enum attribute is needed.
774/// #[bondrewd(enum_primitive = "u8")]
775/// four_byte_four_values: [SimpleEnum; 4],
776/// // if we use the element_bit_length we can say to only use 2
777/// // bits per SimpleEnum, and due to SimpleEnum only needing 2
778/// // bits, this could be desirable. means instead of using 4
779/// // bytes to store 4 SimpleEnums, we can use 1 byte.
780/// #[bondrewd(enum_primitive = "u8", element_bit_length = 2)]
781/// one_byte_four_values: [SimpleEnum; 4],
782/// // again if the size doesn't need to change, no array attribute
783/// // is needed.
784/// #[bondrewd(struct_size = 7)]
785/// waste_a_byte: [SimpleStruct; 2],
786/// // if we want to compress the 2 struct in the array we can
787/// // take advantage of the fact our struct is only using 52 out
788/// // of 56 bits in the compressed/byte form by adding
789/// // element bit length = 52. this will make the total size of
790/// // the 2 structs in compressed/byte form 104 bits instead of
791/// // 112.
792/// #[bondrewd(struct_size = 7, element_bit_length = 52)]
793/// compressed_structures: [SimpleStruct; 2],
794/// }
795/// ```
796/// # Reserve Examples
797/// Reserve fields tell Bondrewd to not include logic for reading or writing the field in the from and
798/// into bytes functions. Currently only primitive types are supported.
799/// ```
800/// use bondrewd::*;
801/// #[derive(Bitfields)]
802/// #[bondrewd(default_endianness = "be")]
803/// struct ReserveExample {
804/// #[bondrewd(bit_length = 7)]
805/// one: u8,
806/// #[bondrewd(bit_length = 7)]
807/// two: u8,
808/// #[bondrewd(bit_length = 10, reserve)]
809/// reserve: u16
810/// }
811/// assert_eq!(3, ReserveExample::BYTE_SIZE);
812/// assert_eq!(24, ReserveExample::BIT_SIZE);
813/// let mut bytes = ReserveExample {
814/// one: 127,
815/// two: 127,
816/// reserve: 1023,
817/// }.into_bytes();
818/// assert_eq!([0b11111111, 0b11111100, 0b00000000], bytes);
819/// assert_eq!(127,ReserveExample::read_one(&bytes));
820/// assert_eq!(127,ReserveExample::read_two(&bytes));
821/// assert_eq!(0,ReserveExample::read_reserve(&bytes));
822/// // quick note write_reserve will actually change the bytes in the byte array.
823/// ReserveExample::write_reserve(&mut bytes, 42);
824/// assert_eq!(42,ReserveExample::read_reserve(&bytes));
825/// // but again from/into bytes doesn't care.
826/// let reconstructed = ReserveExample::from_bytes(bytes);
827/// assert_eq!(127,reconstructed.one);
828/// assert_eq!(127,reconstructed.two);
829/// assert_eq!(0,reconstructed.reserve);
830/// ```
831/// Reserves do not need to be at the end.
832/// ```
833/// use bondrewd::*;
834/// #[derive(Bitfields)]
835/// #[bondrewd(default_endianness = "be", fill_bytes = 3)]
836/// struct ReserveExample {
837/// #[bondrewd(bit_length = 7)]
838/// one: u8,
839/// #[bondrewd(bit_length = 10, reserve)]
840/// reserve: u16,
841/// #[bondrewd(bit_length = 7)]
842/// two: u8,
843/// }
844/// assert_eq!(3, ReserveExample::BYTE_SIZE);
845/// assert_eq!(24, ReserveExample::BIT_SIZE);
846/// let mut bytes = ReserveExample {
847/// one: 127,
848/// two: 127,
849/// reserve: 1023,
850/// }.into_bytes();
851/// assert_eq!(127, ReserveExample::read_one(&bytes));
852/// assert_eq!(127, ReserveExample::read_two(&bytes));
853/// assert_eq!(0, ReserveExample::read_reserve(&bytes));
854/// ReserveExample::write_reserve(&mut bytes, 42);
855/// assert_eq!(42, ReserveExample::read_reserve(&bytes));
856/// let reconstructed = ReserveExample::from_bytes(bytes);
857/// assert_eq!(127,reconstructed.one);
858/// assert_eq!(127,reconstructed.two);
859/// assert_eq!(0,reconstructed.reserve);
860/// ```
861/// # Fill Bytes Examples
862/// Fill bytes is used here to make the total output byte size 3 bytes. If fill bytes attribute was not
863/// present the total output byte size would be 2.
864/// ```
865/// use bondrewd::*;
866/// #[derive(Bitfields)]
867/// #[bondrewd(default_endianness = "be", fill_bytes = 3)]
868/// struct FilledBytes {
869/// #[bondrewd(bit_length = 7)]
870/// one: u8,
871/// #[bondrewd(bit_length = 7)]
872/// two: u8,
873/// }
874/// assert_eq!(3, FilledBytes::BYTE_SIZE);
875/// assert_eq!(24, FilledBytes::BIT_SIZE);
876/// ```
877/// Here im going to compare the example above to the closest alternative using a reserve field:
878/// - FilledBytes only has 2 field, so only 2 fields are required for instantiation, where as ReservedBytes
879/// still needs a value for the reserve field despite from/into bytes not using the value anyway.
880/// - ReservedBytes has 2 extra functions that FilledBytes does not, `write_reserve` and `read_reserve`.
881/// - One more thing to consider is reserve fields are currently confined to primitives, if more than 128
882/// reserve bits are required at the end, fill_bytes is the only supported way of doing this.
883/// ```
884/// use bondrewd::*;
885/// #[derive(Bitfields)]
886/// #[bondrewd(default_endianness = "be")]
887/// struct ReservedBytes {
888/// #[bondrewd(bit_length = 7)]
889/// one: u8,
890/// #[bondrewd(bit_length = 7)]
891/// two: u8,
892/// #[bondrewd(bit_length = 10, reserve)]
893/// reserve: u16
894/// }
895/// assert_eq!(3, ReservedBytes::BYTE_SIZE);
896/// assert_eq!(24, ReservedBytes::BIT_SIZE);
897/// ```
898/// # Enforce Bits Examples
899/// Enforce Bits/Bytes Main purpose is to act as a compile time check to ensure how many bit you think
900/// are being use is the actual amount of bits being used.
901/// Here i have 2 fields with a total defined bit-length of 6, and then an undecorated boolean field. I
902/// also have trust issues so i want to verify that the bool is only using 1 bit making the total bit
903/// length of the struct 7 bits. Adding `enforce_bits = 7` will force a compiler error if the calculated
904/// total bit length is not 7.
905/// ```
906/// use bondrewd::*;
907/// #[derive(Bitfields)]
908/// #[bondrewd(default_endianness = "be", enforce_bits = 7)]
909/// struct FilledBytesEnforced {
910/// #[bondrewd(bit_length = 4)]
911/// one: u8,
912/// #[bondrewd(bit_length = 2)]
913/// two: u8,
914/// three: bool
915/// }
916/// assert_eq!(1, FilledBytesEnforced::BYTE_SIZE);
917/// assert_eq!(7, FilledBytesEnforced::BIT_SIZE);
918/// ```
919/// Here is the same example where but i messed up the bit_length of the first field making the total 8
920/// instead of 7.
921/// ```compile_fail
922/// use bondrewd::*;
923/// #[derive(Bitfields)]
924/// #[bondrewd(default_endianness = "be", enforce_bits = 7)]
925/// struct FilledBytesEnforced {
926/// #[bondrewd(bit_length = 5)]
927/// one: u8,
928/// #[bondrewd(bit_length = 2)]
929/// two: u8,
930/// three: bool
931/// }
932/// assert_eq!(1, FilledBytesEnforced::BYTE_SIZE);
933/// assert_eq!(7, FilledBytesEnforced::BIT_SIZE);
934/// ```
935///
936/// These next 3 examples all attempt to have near the same end results. A total output of 3 bytes, but the
937/// last 10 of them will be reserved/unused (should be ignored and assumed to be 0).
938///
939/// In this first example i will be showing what a struct might look like without fill bytes, then in the
940/// second example i will show the the same end result but without a reserve field. First will be defining
941/// all 24 total bits as 3 fields marking the last field of 10 bits with the reserve attribute
942/// because we don't want from/into bytes functions to process those bytes.
943/// ```
944/// use bondrewd::*;
945/// #[derive(Bitfields)]
946/// #[bondrewd(default_endianness = "be", enforce_bytes = 3)]
947/// struct FilledBytesEnforced {
948/// #[bondrewd(bit_length = 7)]
949/// one: u8,
950/// #[bondrewd(bit_length = 7)]
951/// two: u8,
952/// #[bondrewd(bit_length = 10, reserve)]
953/// reserve: u16
954/// }
955/// assert_eq!(3, FilledBytesEnforced::BYTE_SIZE);
956/// assert_eq!(24, FilledBytesEnforced::BIT_SIZE);
957/// ```
958/// Also note that [`fill_bytes`](#fill-bytes-examples) does NOT effect how `enforce_bytes` works.
959/// `enforce_bytes` will check the total bit length before the bits are filled.
960///
961/// Here i am telling Bondrewd to make the total bit length 3 bytes using `fill_bytes`.
962/// This Example fails to build because only 14 bits are being defined by fields and `enforce_bytes`
963/// is telling Bondrewd to expect 24 bits to be used by defined fields.
964/// ```compile_fail
965/// use bondrewd::*;
966/// #[derive(Bitfields)]
967/// #[bondrewd(default_endianness = "be", fill_bytes = 3, enforce_bytes = 3)]
968/// struct FilledBytesEnforced {
969/// #[bondrewd(bit_length = 7)]
970/// one: u8,
971/// #[bondrewd(bit_length = 7)]
972/// two: u8,
973/// }
974/// ```
975/// To fix this we need to make sure our enforcement value is the amount fo bits defined by the fields NOT
976/// the expected FilledBytesEnforced::BYTE_SIZE.
977///
978/// Here is the Correct usage of these two attributes working together.
979/// ```
980/// use bondrewd::*;
981/// #[derive(Bitfields)]
982/// #[bondrewd(default_endianness = "be", fill_bytes = 3, enforce_bits = 14)]
983/// struct FilledBytesEnforced {
984/// #[bondrewd(bit_length = 7)]
985/// one: u8,
986/// #[bondrewd(bit_length = 7)]
987/// two: u8,
988/// }
989/// assert_eq!(3, FilledBytesEnforced::BYTE_SIZE);
990/// // we are enforcing 14 bits but fill_bytes is creating
991/// // an imaginary reserve field from bit index 14 to
992/// // index 23
993/// assert_eq!(24, FilledBytesEnforced::BIT_SIZE);
994/// ```
995/// # Enforce Full Bytes Example
996/// `enforce_full_bytes` adds a check during parsing phase of Bondrewd which will throw an error if the
997/// total bits determined from the defined fields is not a multiple of 8. This was included for those
998/// like me that get paranoid they entered something in wrong.
999/// ```compile_fail
1000/// use bondrewd::*;
1001/// #[derive(Bitfields)]
1002/// #[bondrewd(default_endianness = "be", enforce_full_bytes)]
1003/// struct FilledBytesEnforced {
1004/// #[bondrewd(bit_length = 7)]
1005/// one: u8,
1006/// #[bondrewd(bit_length = 7)]
1007/// two: u8,
1008/// }
1009/// ```
1010/// In this case if we still wanted fields one and two to remain 7 bits we need to add another field
1011/// to use the remaining 2 bits.
1012/// ```
1013/// use bondrewd::*;
1014/// #[derive(Bitfields)]
1015/// #[bondrewd(default_endianness = "be", enforce_full_bytes)]
1016/// struct FilledBytesEnforced {
1017/// #[bondrewd(bit_length = 7)]
1018/// one: u8,
1019/// #[bondrewd(bit_length = 7)]
1020/// two: u8,
1021/// #[bondrewd(bit_length = 2, reserve)]
1022/// reserve: u16
1023/// }
1024/// assert_eq!(2, FilledBytesEnforced::BYTE_SIZE);
1025/// assert_eq!(16, FilledBytesEnforced::BIT_SIZE);
1026/// ```
1027/// # Enum Examples
1028/// For enum derive examples goto [BitfieldEnum Derive](BitfieldEnum).
1029/// ```
1030/// use bondrewd::*;
1031/// #[derive(BitfieldEnum)]
1032/// enum SimpleEnum {
1033/// Zero,
1034/// One,
1035/// Two,
1036/// Three,
1037/// }
1038/// #[derive(Bitfields)]
1039/// #[bondrewd(default_endianness = "le")]
1040/// struct StructWithEnumExample {
1041/// #[bondrewd(bit_length = 3)]
1042/// one: u8,
1043/// #[bondrewd(enum_primitive = "u8", bit_length = 2)]
1044/// two: SimpleEnum,
1045/// #[bondrewd(bit_length = 3)]
1046/// three: u8,
1047/// }
1048/// ```
1049/// Enums can also be used in [arrays](#bitfield-array-examples)
1050/// ```
1051/// use bondrewd::*;
1052/// #[derive(BitfieldEnum)]
1053/// enum Simple {
1054/// One,
1055/// Two,
1056/// Three,
1057/// Four,
1058/// }
1059///
1060/// #[derive(Bitfields)]
1061/// #[bondrewd(default_endianness = "be")]
1062/// struct SimpleWithStruct {
1063/// // bit length is not required for enums but in this case where only 4 possible variants are in
1064/// // our enums 2 bits is all that is needed. also note using more bits than possible variants is
1065/// // not a problem because the catch all system will protect you from bad inputs.
1066/// #[bondrewd(bit_length = 2, enum_primitive = "u8")]
1067/// one: Simple,
1068/// #[bondrewd(element_bit_length = 2, enum_primitive = "u8")]
1069/// two: [Simple; 3],
1070/// }
1071/// ```
1072/// # Bits Attribute Example
1073/// First i will replicate the [Simple Example](#simple-example) to show an equivalent use.
1074/// ```
1075/// use bondrewd::*;
1076/// #[derive(Bitfields)]
1077/// #[bondrewd(default_endianness = "be")]
1078/// struct SimpleExample {
1079/// // fields that are as expected do not require attributes.
1080/// // #[bondrewd(bits = "0..1")] this could be used but is not needed.
1081/// one: bool,
1082/// // #[bondrewd(bits = "1..33")] this could be used but is not needed.
1083/// two: f32,
1084/// #[bondrewd(bits = "33..47")]
1085/// three: i16,
1086/// #[bondrewd(bits = "47..53")]
1087/// four: u8,
1088/// }
1089///
1090/// assert_eq!(7, SimpleExample::BYTE_SIZE);
1091/// assert_eq!(53, SimpleExample::BIT_SIZE);
1092/// let mut bytes = SimpleExample {
1093/// one: false,
1094/// two: -4.25,
1095/// three: -1034,
1096/// four: 63,
1097/// }.into_bytes();
1098/// // check the output binary is correct. (i did math by hand
1099/// // to get the binary). each field is separated by a underscore
1100/// // in the binary assert to make it easy to see.
1101/// assert_eq!([
1102/// 0b0_1100000, // one_two,
1103/// 0b01000100, // two,
1104/// 0b00000000, // two,
1105/// 0b00000000, // two,
1106/// 0b0_1110111, // two_three,
1107/// 0b1110110_1, // three_four,
1108/// 0b11111_000, // four_unused
1109/// ], bytes);
1110/// // use read functions to get the fields value without
1111/// // doing a from_bytes call.
1112/// assert_eq!(false, SimpleExample::read_one(&bytes));
1113/// assert_eq!(-4.25, SimpleExample::read_two(&bytes));
1114/// assert_eq!(-1034, SimpleExample::read_three(&bytes));
1115/// assert_eq!(63, SimpleExample::read_four(&bytes));
1116/// // overwrite the values with new ones in the byte array.
1117/// SimpleExample::write_one(&mut bytes, true);
1118/// SimpleExample::write_two(&mut bytes, 5.5);
1119/// SimpleExample::write_three(&mut bytes, 511);
1120/// SimpleExample::write_four(&mut bytes, 0);
1121/// // from bytes uses the read function so there is no need to
1122/// // assert the read functions again.
1123/// let reconstructed = SimpleExample::from_bytes(bytes);
1124/// // check the values read by from bytes and check if they are
1125/// // what we wrote to the bytes NOT the origanal values.
1126/// assert_eq!(true,reconstructed.one);
1127/// assert_eq!(5.5,reconstructed.two);
1128/// assert_eq!(511,reconstructed.three);
1129/// assert_eq!(0,reconstructed.four);
1130/// ```
1131/// # Redundant Examples
1132/// In this example we will has fields share data. flags in the example will represent a u8 storing
1133/// multiple boolean flags, but all of the flags within are also fields in the struct. if we mark
1134/// flags as `redundant` above the boolean flag fields then flags will be "read_only"(effects nothing
1135/// during an into_bytes() call).
1136/// ```
1137/// use bondrewd::*;
1138/// #[derive(Bitfields)]
1139/// #[bondrewd(default_endianness = "be")]
1140/// struct SimpleExample {
1141/// // fields that are as expected do not require attributes.
1142/// one: bool,
1143/// two: f32,
1144/// #[bondrewd(bit_length = 14)]
1145/// three: i16,
1146/// // the field is above the bits it shares because bondrewd
1147/// // will get the last non-shared set of bits to base its start from.
1148/// #[bondrewd(redundant, bit_length = 6)]
1149/// flags: u8,
1150/// flag_one: bool,
1151/// flag_two: bool,
1152/// flag_three: bool,
1153/// flag_four: bool,
1154/// flag_five: bool,
1155/// flag_six: bool,
1156/// }
1157///
1158/// assert_eq!(7, SimpleExample::BYTE_SIZE);
1159/// assert_eq!(53, SimpleExample::BIT_SIZE);
1160/// let mut bytes = SimpleExample {
1161/// one: false,
1162/// two: -4.25,
1163/// three: -1034,
1164/// flags: 0,
1165/// flag_one: true,
1166/// flag_two: true,
1167/// flag_three: true,
1168/// flag_four: true,
1169/// flag_five: true,
1170/// flag_six: true,
1171/// }.into_bytes();
1172/// // check the output binary is correct. (i did math by hand
1173/// // to get the binary). each field is separated by a underscore
1174/// // in the binary assert to make it easy to see.
1175/// assert_eq!([
1176/// 0b0_1100000, // one_two,
1177/// 0b01000100, // two,
1178/// 0b00000000, // two,
1179/// 0b00000000, // two,
1180/// 0b0_1110111, // two_three,
1181/// 0b1110110_1, // three_four,
1182/// 0b11111_000, // four_unused
1183/// ], bytes);
1184/// // use read functions to get the fields value without
1185/// // doing a from_bytes call.
1186/// assert_eq!(false, SimpleExample::read_one(&bytes));
1187/// assert_eq!(-4.25, SimpleExample::read_two(&bytes));
1188/// assert_eq!(-1034, SimpleExample::read_three(&bytes));
1189/// // notice i can still use the read calls for the redundant field.
1190/// assert_eq!(63, SimpleExample::read_flags(&bytes));
1191/// assert_eq!(true,SimpleExample::read_flag_one(&bytes));
1192/// assert_eq!(true,SimpleExample::read_flag_two(&bytes));
1193/// assert_eq!(true,SimpleExample::read_flag_three(&bytes));
1194/// assert_eq!(true,SimpleExample::read_flag_four(&bytes));
1195/// assert_eq!(true,SimpleExample::read_flag_five(&bytes));
1196/// assert_eq!(true,SimpleExample::read_flag_six(&bytes));
1197/// // overwrite the values with new ones in the byte array.
1198/// SimpleExample::write_one(&mut bytes, true);
1199/// SimpleExample::write_two(&mut bytes, 5.5);
1200/// SimpleExample::write_three(&mut bytes, 511);
1201/// // notice i can still use the write calls for the redundant field.
1202/// SimpleExample::write_flags(&mut bytes, 0);
1203/// // from bytes uses the read function so there is no need to
1204/// // assert the read functions again.
1205/// let reconstructed = SimpleExample::from_bytes(bytes);
1206/// // check the values read by from bytes and check if they are
1207/// // what we wrote to the bytes NOT the origanal values.
1208/// assert_eq!(true,reconstructed.one);
1209/// assert_eq!(5.5,reconstructed.two);
1210/// assert_eq!(511,reconstructed.three);
1211/// assert_eq!(0,reconstructed.flags);
1212/// assert_eq!(false,reconstructed.flag_one);
1213/// assert_eq!(false,reconstructed.flag_two);
1214/// assert_eq!(false,reconstructed.flag_three);
1215/// assert_eq!(false,reconstructed.flag_four);
1216/// assert_eq!(false,reconstructed.flag_five);
1217/// assert_eq!(false,reconstructed.flag_six);
1218/// ```
1219/// we can also have the flags below if we use the `bits` attribute.
1220/// ```
1221/// use bondrewd::*;
1222/// #[derive(Bitfields)]
1223/// #[bondrewd(default_endianness = "be")]
1224/// struct SimpleExample {
1225/// // fields that are as expected do not require attributes.
1226/// one: bool,
1227/// two: f32,
1228/// #[bondrewd(bit_length = 14)]
1229/// three: i16,
1230/// // the field is above the bits it shares because bondrewd
1231/// // will get the last non-shared set of bits to base its start from.
1232/// flag_one: bool,
1233/// flag_two: bool,
1234/// flag_three: bool,
1235/// flag_four: bool,
1236/// flag_five: bool,
1237/// flag_six: bool,
1238/// #[bondrewd(redundant, bits = "47..53")]
1239/// flags: u8,
1240/// }
1241///
1242/// assert_eq!(7, SimpleExample::BYTE_SIZE);
1243/// assert_eq!(53, SimpleExample::BIT_SIZE);
1244/// let mut bytes = SimpleExample {
1245/// one: false,
1246/// two: -4.25,
1247/// three: -1034,
1248/// flags: 0,
1249/// flag_one: true,
1250/// flag_two: true,
1251/// flag_three: true,
1252/// flag_four: true,
1253/// flag_five: true,
1254/// flag_six: true,
1255/// }.into_bytes();
1256/// // check the output binary is correct. (i did math by hand
1257/// // to get the binary). each field is separated by a underscore
1258/// // in the binary assert to make it easy to see.
1259/// assert_eq!([
1260/// 0b0_1100000, // one_two,
1261/// 0b01000100, // two,
1262/// 0b00000000, // two,
1263/// 0b00000000, // two,
1264/// 0b0_1110111, // two_three,
1265/// 0b1110110_1, // three_four,
1266/// 0b11111_000, // four_unused
1267/// ], bytes);
1268/// // use read functions to get the fields value without
1269/// // doing a from_bytes call.
1270/// assert_eq!(false, SimpleExample::read_one(&bytes));
1271/// assert_eq!(-4.25, SimpleExample::read_two(&bytes));
1272/// assert_eq!(-1034, SimpleExample::read_three(&bytes));
1273/// // notice i can still use the read calls for the redundant field.
1274/// assert_eq!(63, SimpleExample::read_flags(&bytes));
1275/// assert_eq!(true,SimpleExample::read_flag_one(&bytes));
1276/// assert_eq!(true,SimpleExample::read_flag_two(&bytes));
1277/// assert_eq!(true,SimpleExample::read_flag_three(&bytes));
1278/// assert_eq!(true,SimpleExample::read_flag_four(&bytes));
1279/// assert_eq!(true,SimpleExample::read_flag_five(&bytes));
1280/// assert_eq!(true,SimpleExample::read_flag_six(&bytes));
1281/// // overwrite the values with new ones in the byte array.
1282/// SimpleExample::write_one(&mut bytes, true);
1283/// SimpleExample::write_two(&mut bytes, 5.5);
1284/// SimpleExample::write_three(&mut bytes, 511);
1285/// // notice i can still use the write calls for the redundant field.
1286/// SimpleExample::write_flags(&mut bytes, 0);
1287/// // from bytes uses the read function so there is no need to
1288/// // assert the read functions again.
1289/// let reconstructed = SimpleExample::from_bytes(bytes);
1290/// // check the values read by from bytes and check if they are
1291/// // what we wrote to the bytes NOT the origanal values.
1292/// assert_eq!(true,reconstructed.one);
1293/// assert_eq!(5.5,reconstructed.two);
1294/// assert_eq!(511,reconstructed.three);
1295/// assert_eq!(0,reconstructed.flags);
1296/// assert_eq!(false,reconstructed.flag_one);
1297/// assert_eq!(false,reconstructed.flag_two);
1298/// assert_eq!(false,reconstructed.flag_three);
1299/// assert_eq!(false,reconstructed.flag_four);
1300/// assert_eq!(false,reconstructed.flag_five);
1301/// assert_eq!(false,reconstructed.flag_six);
1302/// ```
1303#[proc_macro_derive(Bitfields, attributes(bondrewd,))]
1304pub fn derive_bitfields(input: TokenStream) -> TokenStream {
1305 let input = parse_macro_input!(input as DeriveInput);
1306 // parse the input into a StructInfo which contains all the information we
1307 // along with some helpful structures to generate our Bitfield code.
1308 let struct_info = match StructInfo::parse(&input) {
1309 Ok(parsed_struct) => parsed_struct,
1310 Err(err) => {
1311 return TokenStream::from(err.to_compile_error());
1312 }
1313 };
1314 // println!("{:?}", struct_info);
1315 // get the struct size and name so we can use them in a quote.
1316 let struct_size = struct_info.total_bytes();
1317 let struct_name = format_ident!("{}", struct_info.name);
1318
1319 // get a list of all fields from_bytes logic which gets there bytes from an array called
1320 // input_byte_buffer.
1321 let slice_fns: bool;
1322 #[cfg(not(feature = "slice_fns"))]
1323 {
1324 slice_fns = false;
1325 }
1326 #[cfg(feature = "slice_fns")]
1327 {
1328 slice_fns = true;
1329 }
1330 // get a list of all fields into_bytes logic which puts there bytes into an array called
1331 // output_byte_buffer.
1332 let fields_into_bytes = match create_into_bytes_field_quotes(&struct_info, slice_fns) {
1333 Ok(ftb) => ftb,
1334 Err(err) => return TokenStream::from(err.to_compile_error()),
1335 };
1336 let fields_from_bytes = match create_from_bytes_field_quotes(&struct_info, slice_fns) {
1337 Ok(ffb) => ffb,
1338 Err(err) => return TokenStream::from(err.to_compile_error()),
1339 };
1340 // combine all of the into_bytes quotes separated by newlines
1341 let into_bytes_quote = fields_into_bytes.into_bytes_fn;
1342 let mut set_quotes = fields_into_bytes.set_field_fns;
1343
1344 if let Some(set_slice_quote) = fields_into_bytes.set_slice_field_fns {
1345 set_quotes = quote! {
1346 #set_quotes
1347 #set_slice_quote
1348 }
1349 }
1350
1351 let from_bytes_quote = fields_from_bytes.from_bytes_fn;
1352 let mut peek_quotes = fields_from_bytes.peek_field_fns;
1353
1354 if let Some(peek_slice_quote) = fields_from_bytes.peek_slice_field_fns {
1355 peek_quotes = quote! {
1356 #peek_quotes
1357 #peek_slice_quote
1358 }
1359 }
1360
1361 let setters: bool;
1362 #[cfg(not(feature = "setters"))]
1363 {
1364 setters = false;
1365 }
1366 #[cfg(feature = "setters")]
1367 {
1368 setters = true;
1369 }
1370 let setters_quote = if setters {
1371 match structs::struct_fns::create_into_bytes_field_quotes(&struct_info) {
1372 Ok(parsed_struct) => parsed_struct,
1373 Err(err) => {
1374 return TokenStream::from(err.to_compile_error());
1375 }
1376 }
1377 } else {
1378 quote! {}
1379 };
1380
1381 let getter_setters_quotes = quote! {
1382 impl #struct_name {
1383 #peek_quotes
1384 #set_quotes
1385 #setters_quote
1386 }
1387 };
1388 let hex;
1389 #[cfg(feature = "hex_fns")]
1390 {
1391 hex = true;
1392 }
1393 #[cfg(not(feature = "hex_fns"))]
1394 {
1395 hex = false;
1396 }
1397 let hex_size = struct_size * 2;
1398 let hex_fns_quote = if hex {
1399 quote! {
1400 impl bondrewd::BitfieldHex<#hex_size> for #struct_name {
1401 fn from_hex(hex: [u8;#hex_size]) -> Result<Self, bondrewd::BitfieldHexError> {
1402 let bytes: [u8; #struct_size] = [0;#struct_size];
1403 let mut bytes: [u8; Self::BYTE_SIZE] = [0;Self::BYTE_SIZE];
1404 for i in 0usize..#struct_size {
1405 let index = i * 2;
1406 let index2 = index + 1;
1407 let decode_nibble = |c, c_i| match c {
1408 b'A'..=b'F' => Ok(c - b'A' + 10u8),
1409 b'a'..=b'f' => Ok(c - b'a' + 10u8),
1410 b'0'..=b'9' => Ok(c - b'0'),
1411 _ => return Err(bondrewd::BitfieldHexError(
1412 c as char,
1413 c_i,
1414 )),
1415 };
1416 bytes[i] = ((decode_nibble(hex[index], index)? & 0b00001111) << 4) | decode_nibble(hex[index2], index2)?;
1417 }
1418 Ok(Self::from_bytes(bytes))
1419
1420 }
1421
1422 fn into_hex_upper(self) -> [u8;#hex_size] {
1423 let bytes = self.into_bytes();
1424 let mut output: [u8;#hex_size] = [0; #hex_size];
1425 for (i, byte) in (0..#hex_size).step_by(2).zip(bytes) {
1426 output[i] = (Self::UPPERS[((byte & 0b11110000) >> 4) as usize]);
1427 output[i + 1] = (Self::UPPERS[(byte & 0b00001111) as usize]);
1428 }
1429 output
1430 }
1431
1432 fn into_hex_lower(self) -> [u8;#hex_size] {
1433 let bytes = self.into_bytes();
1434 let mut output: [u8;#hex_size] = [0; #hex_size];
1435 for (i, byte) in (0..#hex_size).step_by(2).zip(bytes) {
1436 output[i] = (Self::LOWERS[((byte & 0b11110000) >> 4) as usize]);
1437 output[i + 1] = (Self::LOWERS[(byte & 0b00001111) as usize]);
1438 }
1439 output
1440 }
1441 }
1442 }
1443 } else {
1444 quote! {}
1445 };
1446
1447 // get the bit size of the entire set of fields to fill in trait requirement.
1448 let bit_size = struct_info.total_bits();
1449
1450 // put it all together.
1451 // to_bytes_quote will put all of the fields in self into a array called output_byte_buffer.
1452 // so for into_bytes all we need is the fn declaration, the output_byte_buffer, and to return
1453 // that buffer.
1454 // from_bytes is essentially the same minus a variable because input_byte_buffer is the input.
1455 // slap peek quotes inside a impl block at the end and we good to go
1456 let to_bytes_quote = quote! {
1457 impl bondrewd::Bitfields<#struct_size> for #struct_name {
1458 const BIT_SIZE: usize = #bit_size;
1459 #into_bytes_quote
1460 #from_bytes_quote
1461 }
1462 #getter_setters_quotes
1463 #hex_fns_quote
1464 };
1465
1466 if slice_fns {
1467 let vis = struct_info.vis;
1468 let checked_ident = format_ident!("{}Checked", &struct_name);
1469 let checked_mut_ident = format_ident!("{}CheckedMut", &struct_name);
1470 let unchecked_functions = fields_from_bytes.peek_slice_field_unchecked_fns;
1471 let unchecked_mut_functions = fields_into_bytes.set_slice_field_unchecked_fns;
1472 let comment = format!("A Structure which provides functions for getting the fields of a [{struct_name}] in its bitfield form.");
1473 let comment_mut = format!("A Structure which provides functions for getting and setting the fields of a [{struct_name}] in its bitfield form.");
1474 let unchecked_comment = format!("Panics if resulting `{checked_ident}` does not contain enough bytes to read a field that is attempted to be read.");
1475 let unchecked_comment_mut = format!("Panics if resulting `{checked_mut_ident}` does not contain enough bytes to read a field that is attempted to be read or written.");
1476 let to_bytes_quote = quote! {
1477 #to_bytes_quote
1478 #[doc = #comment]
1479 #vis struct #checked_ident<'a> {
1480 buffer: &'a [u8],
1481 }
1482 impl<'a> #checked_ident<'a> {
1483 #unchecked_functions
1484 #[doc = #unchecked_comment]
1485 pub fn from_unchecked_slice(data: &'a [u8]) -> Self {
1486 Self{
1487 buffer: data
1488 }
1489 }
1490 }
1491 #[doc = #comment_mut]
1492 #vis struct #checked_mut_ident<'a> {
1493 buffer: &'a mut [u8],
1494 }
1495 impl<'a> #checked_mut_ident<'a> {
1496 #unchecked_functions
1497 #unchecked_mut_functions
1498 #[doc = #unchecked_comment_mut]
1499 pub fn from_unchecked_slice(data: &'a mut [u8]) -> Self {
1500 Self{
1501 buffer: data
1502 }
1503 }
1504 }
1505 };
1506 TokenStream::from(to_bytes_quote)
1507 } else {
1508 TokenStream::from(to_bytes_quote)
1509 }
1510}
1511
1512/// Generates an implementation of bondrewd::BitfieldEnum trait.
1513///
1514/// Important Note: u8 is the only primitive type i have tested. My newest code should be able to handle
1515/// all primitive types but, to reiterate, i have NOT tested any primitive type other than u8.
1516///
1517/// # Features
1518/// - Generates code for the BitfieldEnum trait which allows an enum to be used by Bitfield structs.
1519/// - Literal values. [example](#literal-example)
1520/// - Automatic Value Assignment for non-literal variants. Variants are assigned values starting from 0
1521/// incrementing by 1 skipping values taken by literal definitions (That means you can mix and match
1522/// inferred values a code defined literal values). [example](#typical-example)
1523/// - Catch Variants
1524/// - Catch All variant is used to insure that Results are not needed. Catch all will generate a
1525/// `_ => {..}` match arm so that enums don't need to have as many variants as there are values in
1526/// the defined primitive. Catch all can be defined with a `#[bondrewd_enum(invalid)]` attribute or last variant will
1527/// Automatically become a catch all if no Catch is defined. [example](#custom-catch-all-example)
1528/// - Catch Value is a variant that will store values that don't match the reset of the variants.
1529/// using a Catch Value is as simple as making a variant with a primitive value (if the bondrewd_enum
1530/// attribute is present the primitive types must match). [example](#catch-value-example)
1531///
1532/// # Other Features
1533/// - Support for implementation of [`std::cmp::PartialEq`] for the given primitive (currently only u8)
1534///
1535/// # Typical Example
1536/// Here i am letting the Derive do all of the work. The primitive type will be assumed to be u8 because
1537/// there are less than 256 variants. Variants that do not define a value will be assigned a value
1538/// starting with the lowest available value. Also due to the catch all system we can ignore the fact
1539/// i have not covered all 255 values of a u8 because the last Variant, SimpleEnum::Three is this example,
1540/// will be used a a default to insure not errors can occur.
1541/// ```
1542/// use bondrewd::BitfieldEnum;
1543/// #[derive(BitfieldEnum, PartialEq, Debug)]
1544/// enum SimpleEnum {
1545/// Zero, // assigned value 0
1546/// One, // assigned value 1
1547/// Two, // assigned value 2
1548/// Three,// assigned value 3
1549/// }
1550///
1551/// assert_eq!(SimpleEnum::Zero.into_primitive(), 0);
1552/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(0));
1553/// assert_eq!(SimpleEnum::One.into_primitive(), 1);
1554/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(1));
1555/// assert_eq!(SimpleEnum::Two.into_primitive(), 2);
1556/// assert_eq!(SimpleEnum::Two, SimpleEnum::from_primitive(2));
1557/// assert_eq!(SimpleEnum::Three.into_primitive(), 3);
1558/// for i in 3..=u8::MAX {
1559/// assert_eq!(SimpleEnum::Three, SimpleEnum::from_primitive(i));
1560/// }
1561///
1562/// ```
1563/// If you do not want the last variant to be a
1564/// catch all you must either:
1565/// - Cover all possible values in the primitive type with a variant each.
1566/// - Mark the variant you would like to be the catch all [example](#custom-catch-all-example).
1567/// - Add a catch primitive variant [example](#catch-value-example)
1568/// # Literal Example
1569/// ```
1570/// use bondrewd::BitfieldEnum;
1571/// #[derive(BitfieldEnum, PartialEq, Debug)]
1572/// enum SimpleEnum {
1573/// Life = 42,
1574/// Min = 0,
1575/// U8Max = 255,
1576/// Unlucky = 13,
1577/// }
1578///
1579/// assert_eq!(SimpleEnum::Life.into_primitive(), 42);
1580/// assert_eq!(SimpleEnum::Life, SimpleEnum::from_primitive(42));
1581/// assert_eq!(SimpleEnum::Min.into_primitive(), 0);
1582/// assert_eq!(SimpleEnum::Min, SimpleEnum::from_primitive(0));
1583/// assert_eq!(SimpleEnum::U8Max.into_primitive(), 255);
1584/// assert_eq!(SimpleEnum::U8Max, SimpleEnum::from_primitive(255));
1585/// assert_eq!(SimpleEnum::Unlucky.into_primitive(), 13);
1586/// // check all values not defined and 13 get detected as Unlucky
1587/// for i in 1..42 {
1588/// assert_eq!(SimpleEnum::Unlucky, SimpleEnum::from_primitive(i));
1589/// }
1590/// for i in 43..u8::MAX {
1591/// assert_eq!(SimpleEnum::Unlucky, SimpleEnum::from_primitive(i));
1592/// }
1593/// ```
1594/// # Custom Catch All Example
1595/// If you don't decorate the Enum at all the last variant will be assumed to be an Invalid variant. This
1596/// means if the input value doesn't match any defined value we can use the Invalid variant as a default.
1597/// ```
1598/// use bondrewd::BitfieldEnum;
1599/// #[derive(BitfieldEnum, PartialEq, Debug)]
1600/// enum SimpleEnum {
1601/// Zero, // assigned 0
1602/// One, // assigned 1
1603/// Two, // assigned 2
1604/// Three, // assigned 3 and catches invalid values
1605/// }
1606///
1607/// assert_eq!(SimpleEnum::Zero.into_primitive(), 0);
1608/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(0));
1609/// assert_eq!(SimpleEnum::One.into_primitive(), 1);
1610/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(1));
1611/// assert_eq!(SimpleEnum::Two.into_primitive(), 2);
1612/// assert_eq!(SimpleEnum::Two, SimpleEnum::from_primitive(2));
1613/// assert_eq!(SimpleEnum::Three.into_primitive(), 3);
1614/// assert_eq!(SimpleEnum::Three, SimpleEnum::from_primitive(3));
1615/// // remaining possible values are caught as One.
1616/// for i in 4..=u8::MAX {
1617/// assert_eq!(SimpleEnum::Three, SimpleEnum::from_primitive(i));
1618/// }
1619/// ```
1620/// This example shows that we can mark any variant as the catch all variant. In this case Bondrewd will
1621/// give SimpleEnum::One the value of 1 and make One catch all values not defined because
1622/// of the invalid attribute.
1623/// ```
1624/// use bondrewd::BitfieldEnum;
1625/// #[derive(BitfieldEnum, PartialEq, Debug)]
1626/// enum SimpleEnum {
1627/// Zero, // assigned 0
1628/// #[bondrewd_enum(invalid)]
1629/// One, // assigned 1 and catches invalid values
1630/// Two, // assigned 2
1631/// Three, // assigned 3
1632/// }
1633///
1634/// assert_eq!(SimpleEnum::Zero.into_primitive(), 0);
1635/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(0));
1636/// assert_eq!(SimpleEnum::One.into_primitive(), 1);
1637/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(1));
1638/// assert_eq!(SimpleEnum::Two.into_primitive(), 2);
1639/// assert_eq!(SimpleEnum::Two, SimpleEnum::from_primitive(2));
1640/// assert_eq!(SimpleEnum::Three.into_primitive(), 3);
1641/// assert_eq!(SimpleEnum::Three, SimpleEnum::from_primitive(3));
1642/// // remaining possible values are caught as One.
1643/// for i in 4..=u8::MAX {
1644/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(i));
1645/// }
1646/// ```
1647/// # Catch Value Example
1648/// In some cases we might need to know what the invalid value passed into from_primitive actually was. In
1649/// my own code there is an enum field that gets encrypted and can become pretty much any value and cause
1650/// panics in the library i used before writing Bondrewd. To fix this Bondrewd offers the ability to make 1
1651/// variant a tuple or struct variant with exactly one field which must be the primitive type the enum
1652/// gets converted into/from, than the variant values not covered will be stored in the variants field.
1653/// ```
1654/// use bondrewd::BitfieldEnum;
1655/// #[derive(BitfieldEnum, PartialEq, Debug)]
1656/// enum SimpleEnum {
1657/// Zero,
1658/// One,
1659/// Two,
1660/// Three(u8),
1661/// }
1662///
1663/// assert_eq!(SimpleEnum::Zero.into_primitive(), 0);
1664/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(0));
1665/// assert_eq!(SimpleEnum::One.into_primitive(), 1);
1666/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(1));
1667/// assert_eq!(SimpleEnum::Two.into_primitive(), 2);
1668/// assert_eq!(SimpleEnum::Two, SimpleEnum::from_primitive(2));
1669/// for i in 3..=u8::MAX {
1670/// assert_eq!(SimpleEnum::Three(i), SimpleEnum::from_primitive(i));
1671/// }
1672/// ```
1673/// # Complex Example
1674/// Here i just want to show that Literals, Auto Value Assignment, and Invalid catch all can all be used
1675/// together. As you might expect Catch Primitive can not have a Literal value because it stores a value.
1676/// Here we expect:
1677/// - SimpleEnum::Nine = 9,
1678/// - SimpleEnum::One = 1,
1679/// - SimpleEnum::Zero = 0 and accept 3, 4, 6, 7, 8, and 10..u8::MAX in from_primitive(),
1680/// - SimpleEnum::Five = 5,
1681/// - SimpleEnum::Two = 2,
1682/// ```
1683/// use bondrewd::BitfieldEnum;
1684/// #[derive(BitfieldEnum, PartialEq, Debug)]
1685/// enum SimpleEnum {
1686/// Nine = 9,
1687/// // because variant `One` is the first non-literal variant it will be
1688/// // given the first available value
1689/// One,
1690/// // Literals can still be a catch all.
1691/// #[bondrewd_enum(invalid)]
1692/// Zero = 0,
1693/// Five = 5,
1694/// // because variant `One` is the second non-literal variant it will be
1695/// // given the second available value
1696/// Two,
1697/// }
1698///
1699/// assert_eq!(SimpleEnum::Nine.into_primitive(), 9);
1700/// assert_eq!(SimpleEnum::Nine, SimpleEnum::from_primitive(9));
1701/// assert_eq!(SimpleEnum::One.into_primitive(), 1);
1702/// assert_eq!(SimpleEnum::One, SimpleEnum::from_primitive(1));
1703/// assert_eq!(SimpleEnum::Zero.into_primitive(), 0);
1704/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(0));
1705/// assert_eq!(SimpleEnum::Five.into_primitive(), 5);
1706/// assert_eq!(SimpleEnum::Five, SimpleEnum::from_primitive(5));
1707/// assert_eq!(SimpleEnum::Two.into_primitive(), 2);
1708/// assert_eq!(SimpleEnum::Two, SimpleEnum::from_primitive(2));
1709/// // Invalid tests
1710/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(3));
1711/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(4));
1712/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(6));
1713/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(7));
1714/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(8));
1715/// for i in 10..=u8::MAX {
1716/// assert_eq!(SimpleEnum::Zero, SimpleEnum::from_primitive(i));
1717/// }
1718/// ```
1719#[proc_macro_derive(BitfieldEnum, attributes(bondrewd_enum))]
1720pub fn derive_bondrewd_enum(input: TokenStream) -> TokenStream {
1721 // TODO added the ability to give a Catch Value Variant a Literal value.
1722 let input = parse_macro_input!(input as DeriveInput);
1723 let enum_info = match EnumInfo::parse(&input) {
1724 Ok(parsed_enum) => parsed_enum,
1725 Err(err) => {
1726 return TokenStream::from(err.to_compile_error());
1727 }
1728 };
1729 let into = match enums::into_bytes::generate_into_bytes(&enum_info) {
1730 Ok(i) => i,
1731 Err(err) => return TokenStream::from(err.to_compile_error()),
1732 };
1733 let from = match enums::from_bytes::generate_from_bytes(&enum_info) {
1734 Ok(f) => f,
1735 Err(err) => return TokenStream::from(err.to_compile_error()),
1736 };
1737 let partial_eq = enums::partial_eq::generate_partial_eq(&enum_info);
1738 let enum_name = enum_info.name;
1739 let primitive = enum_info.primitive;
1740 TokenStream::from(quote! {
1741 impl bondrewd::BitfieldEnum for #enum_name {
1742 type Primitive = #primitive;
1743 #into
1744 #from
1745 }
1746
1747 #partial_eq
1748 })
1749}