1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
//! Bit-level packing and unpacking for Rust

//! ===========================================

//!

//! [![Build Status](https://travis-ci.org/hashmismatch/packed_struct.rs.svg?branch=master)](https://travis-ci.org/hashmismatch/packed_struct.rs)

//!

//! [![Documentation](https://docs.rs/packed_struct/badge.svg)](https://docs.rs/packed_struct)

//!

//! # Introduction

//!

//! Packing and unpacking bit-level structures is usually a programming tasks that needlessly reinvents the wheel. This library provides

//! a meta-programming approach, using attributes to define fields and how they should be packed. The resulting trait implementations

//! provide safe packing, unpacking and runtime debugging formatters with per-field documentation generated for each structure.

//!

//! # Features

//!

//!  * Plain Rust structures, decorated with attributes

//!  * MSB or LSB integers of user-defined bit widths

//!  * Primitive enum code generation helper

//!  * MSB0 or LSB0 bit positioning

//!  * Documents the field's packing table

//!  * Runtime packing visualization

//!  * Nested packed types

//!  * Arrays of packed structures as fields

//!  * Reserved fields, their bits are always 0 or 1

//!

//! # Sample usage

//!

//! ## Cargo.toml

//!

//! ```toml

//! [dependencies]

//! packed_struct = "0.3"

//! packed_struct_codegen = "0.3"

//! ```

//! ## Including the library and the code generator

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use]

//! extern crate packed_struct_codegen;

//! # fn main() {

//! # }

//! ```

//!

//! ## Example of a single-byte structure, with a 3 bit integer, primitive enum and a bool field.

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! use packed_struct::prelude::*;

//!

//! #[derive(PackedStruct)]

//! #[packed_struct(bit_numbering="msb0")]

//! pub struct TestPack {

//!     #[packed_field(bits="0..=2")]

//!     tiny_int: Integer<u8, packed_bits::Bits3>,

//!     #[packed_field(bits="3..=4", ty="enum")]

//!     mode: SelfTestMode,

//!     #[packed_field(bits="7")]

//!     enabled: bool

//! }

//!

//! #[derive(PrimitiveEnum_u8, Clone, Copy, Debug, PartialEq)]

//! pub enum SelfTestMode {

//!     NormalMode = 0,

//!     PositiveSignSelfTest = 1,

//!     NegativeSignSelfTest = 2,

//!     DebugMode = 3,

//! }

//!

//! fn main() {

//!     let test = TestPack {

//!         tiny_int: 5.into(),

//!         mode: SelfTestMode::DebugMode,

//!         enabled: true

//!     };

//!

//!     let packed = test.pack();

//!     assert_eq!([0b10111001], packed);

//!

//!     let unpacked = TestPack::unpack(&packed).unwrap();

//!     assert_eq!(*unpacked.tiny_int, 5);

//!     assert_eq!(unpacked.mode, SelfTestMode::DebugMode);

//!     assert_eq!(unpacked.enabled, true);

//! }

//! ```

//!

//! # Packing attributes

//!

//! ## Syntax

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! #[derive(PackedStruct)]

//! #[packed_struct(attr1="val", attr2="val")]

//! pub struct Structure {

//!     #[packed_field(attr1="val", attr2="val")]

//!     field: u8

//! }

//! # fn main() {

//! # }

//! ```

//!

//! ## Per-structure attributes

//!

//! Attribute | Values | Comment

//! :--|:--|:--

//! ```size_bytes``` | ```1``` ... n | Size of the packed byte stream

//! ```bit_numbering``` | ```msb0``` or ```lsb0``` | Bit numbering for bit positioning of fields. Required if the bits attribute field is used.

//! ```endian``` | ```msb``` or ```lsb``` | Default integer endianness

//!

//! ## Per-field attributes

//!

//! Attribute | Values | Comment

//! :--|:--|:--

//! ```bits``` | ```0```, ```0..1```, ... | Position of the field in the packed structure. Three modes are supported: a single bit, the starting bit, or a range of bits. See details below.

//! ```bytes``` | ```0```, ```0..1```, ... | Same as above, multiplied by 8.

//! ```size_bits``` | ```1```, ... | Specifies the size of the packed structure. Mandatory for certain types. Specifying a range of bits like ```bits="0..2"``` can substite the required usage of ```size_bits```.

//! ```size_bytes``` | ```1```, ... | Same as above, multiplied by 8.

//! ```element_size_bits``` | ```1```, ... | For packed arrays, specifies the size of a single element of the array. Explicitly stating the size of the entire array can substite the usage of this attribute.

//! ```element_size_bytes``` | ```1```, ... | Same as above, multiplied by 8.

//! ```ty``` | ```enum``` | Packing helper for primitive enums.

//! ```endian``` | ```msb``` or ```lsb``` | Integer endianness. Applies to u16/i16 and larger types.

//! 

//! ## Bit and byte positioning

//! 

//! Used for either ```bits``` or ```bytes``` on fields. The examples are for MSB0 positioning.

//! 

//! Value | Comment

//! :--|:--

//! ```0``` | A single bit or byte

//! ```0..```, ```0:``` | The field starts at bit zero

//! ```0..2``` | Exclusive range, bits zero and one

//! ```0:1```, ```0..=1``` | Inclusive range, bits zero and one

//!

//! # More examples

//!

//! ## Mixed endian integers

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! use packed_struct::prelude::*;

//!

//! #[derive(PackedStruct)]

//! pub struct EndianExample {

//!     #[packed_field(endian="lsb")]

//!     int1: u16,

//!     #[packed_field(endian="msb")]

//!     int2: i32

//! }

//!

//! fn main() {

//!     let example = EndianExample {

//!         int1: 0xBBAA,

//!         int2: 0x11223344

//!     };

//!

//!     let packed = example.pack();

//!     assert_eq!([0xAA, 0xBB, 0x11, 0x22, 0x33, 0x44], packed);

//! }

//! ```

//!

//! ## 24 bit LSB integers

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! use packed_struct::prelude::*;

//!

//! #[derive(PackedStruct)]

//! #[packed_struct(endian="lsb")]

//! pub struct LsbIntExample {

//!     int1: Integer<u32, packed_bits::Bits24>,

//! }

//!

//! fn main() {

//!     let example = LsbIntExample {

//!         int1: 0xCCBBAA.into()

//!     };

//!

//!     let packed = example.pack();

//!     assert_eq!([0xAA, 0xBB, 0xCC], packed);

//! }

//! ```

//!

//! ## Nested packed types within arrays

//!

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! use packed_struct::prelude::*;

//!

//! #[derive(PackedStruct, Default, Debug, PartialEq)]

//! #[packed_struct(bit_numbering="msb0")]

//! pub struct TinyFlags {

//!     _reserved: ReservedZero<packed_bits::Bits4>,

//!     flag1: bool,

//!     val1: Integer<u8, packed_bits::Bits2>,

//!     flag2: bool

//! }

//!

//! #[derive(PackedStruct, Debug, PartialEq)]

//! pub struct Settings {

//!     #[packed_field(element_size_bits="4")]

//!     values: [TinyFlags; 4]

//! }

//!

//! fn main() {

//!     let example = Settings {

//!         values: [

//!             TinyFlags { flag1: true,  val1: 1.into(), flag2: false, .. TinyFlags::default() },

//!             TinyFlags { flag1: true,  val1: 2.into(), flag2: true,  .. TinyFlags::default() },

//!             TinyFlags { flag1: false, val1: 3.into(), flag2: false, .. TinyFlags::default() },

//!             TinyFlags { flag1: true,  val1: 0.into(), flag2: false, .. TinyFlags::default() },

//!         ]

//!     };

//!

//!     let packed = example.pack();

//!     let unpacked = Settings::unpack(&packed).unwrap();

//!

//!     assert_eq!(example, unpacked);

//! }

//! ```

//! 

//! # Primitive enums with simple discriminants

//! 

//! Supported backing integer types: ```u8```, ```u16```, ```u32```, ```u64```, ```i8```, ```i16```, ```i32```, ```i64```.

//! 

//! Explicit or implicit backing type:

//! 

//! ```rust

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! #[derive(PrimitiveEnum, Clone, Copy)]

//! pub enum ImplicitType {

//!     VariantMin = 0,

//!     VariantMax = 255

//! }

//! 

//! #[derive(PrimitiveEnum_i16, Clone, Copy)]

//! pub enum ExplicitType {

//!     VariantMin = -32768,

//!     VariantMax = 32767

//! }

//! 

//! # fn main() {}

//! ```

//! 

//! # Primitive enum packing with support for catch-all unknown values

//! 

//! ```rust

//! # use packed_struct::prelude::*;

//! extern crate packed_struct;

//! #[macro_use] extern crate packed_struct_codegen;

//!

//! #[derive(PrimitiveEnum_u8, Debug, Clone, Copy)]

//! pub enum Field {

//!     A = 1,

//!     B = 2,

//!     C = 3

//! }

//! 

//! #[derive(PackedStruct, Debug, PartialEq)]

//! #[packed_struct(bit_numbering="msb0")]

//! pub struct Register {

//!     #[packed_field(bits="0..4", ty="enum")]

//!     field: EnumCatchAll<Field>

//! }

//! 

//! # fn main() {}

//! ```


#![cfg_attr(not(feature = "std"), no_std)]

#![cfg_attr(feature="alloc", feature(alloc))]

#[cfg(feature="alloc")]
#[macro_use]
extern crate alloc;


extern crate serde;
#[macro_use] extern crate serde_derive;

mod internal_prelude;

#[macro_use]
mod packing;

mod primitive_enum;
pub use primitive_enum::*;


#[cfg(any(feature="alloc", feature="std"))]
pub mod debug_fmt;

mod types_array;
mod types_basic;
mod types_bits;
mod types_num;
mod types_reserved;

/// Implementations and wrappers for various packing types.

pub mod types {
    pub use super::types_basic::*;

    /// Types that specify the exact number of bits a packed integer should occupy.

    pub mod bits {
        pub use super::super::types_bits::*;
    }

    pub use super::types_num::*;
    pub use super::types_array::*;
    pub use super::types_reserved::*;
}

pub use self::packing::*;


pub mod prelude {
    //! Re-exports the most useful traits and types. Meant to be glob imported.


    pub use PackedStruct;
    pub use PackedStructSlice;
    pub use PackingError;

    pub use PrimitiveEnum;
    #[cfg(any(feature="alloc", feature="std"))]
    pub use PrimitiveEnumDynamicStr;

    #[cfg(not(any(feature="alloc", feature="std")))]
    pub use PrimitiveEnumStaticStr;


    pub use EnumCatchAll;

    pub use types::*;
    pub use types::bits as packed_bits;
}