From cca7d8956b1c11aaa5ff6fb9f8c058bb9a45d7e1 Mon Sep 17 00:00:00 2001 From: wcampbell Date: Fri, 3 Nov 2023 17:43:07 -0400 Subject: [PATCH] Add attribute docs --- src/attributes.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++ src/ctx.rs | 6 ++-- tests/bit_order.rs | 20 +++++++++-- 3 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 048dfc65..79dbd4e8 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -33,6 +33,7 @@ enum DekuEnum { | Attribute | Scope | Description |-----------|------------------|------------ | [endian](#endian) | top-level, field | Set the endianness +| [bit_order](#bit_order) | top-level, field | Set the field representing the order in which to read the bits | [magic](#magic) | top-level | A magic value that must be present at the start of this struct/enum | [assert](#assert) | field | Assert a condition | [assert_eq](#assert_eq) | field | Assert equals on the field @@ -141,6 +142,92 @@ assert_eq!( let value: Vec = value.try_into().unwrap(); assert_eq!(&*data, value); ``` +# bit_order + +Specify the field or containers bit order. By default all bits are read in `Msb0` (Most significant bit) order. + +### Top-Level Example +```rust +# use deku::prelude::*; +# use std::convert::{TryInto, TryFrom}; +# #[derive(Debug, DekuRead, DekuWrite, PartialEq)] +#[deku(bit_order = "lsb")] +pub struct SquashfsV3 { + #[deku(bits = "4")] + inode_type: u32, + #[deku(bits = "12")] + mode: u32, + #[deku(bits = "8")] + uid: u32, + #[deku(bits = "8")] + guid: u32, + mtime: u32, + inode_number: u32, +} + +let data: &[u8] = &[ + 0x31, 0x12, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, +]; +let header = SquashfsV3::try_from(data).unwrap(); +assert_eq!( + SquashfsV3 { + inode_type: 0x01, + mode: 0x123, + uid: 0x4, + guid: 0x5, + mtime: 0x6, + inode_number: 0x7 + }, + header, +); +``` + +With endian-ness: +```rust +# use deku::prelude::*; +# use std::convert::{TryInto, TryFrom}; +# #[derive(Debug, DekuRead, DekuWrite, PartialEq)] +#[deku(endian = "big", bit_order = "lsb")] +pub struct BigEndian { + #[deku(bits = "13")] + offset: u16, + #[deku(bits = "3")] + t: u8, +} + +let data = vec![0x40, 0x40]; +let big_endian = BigEndian::try_from(data.as_ref()).unwrap(); +assert_eq!( + more_first, + BigEndian { + offset: 0x4000, + t: 2 + } +); + +let bytes = big_endian.to_bytes().unwrap(); +assert_eq!(bytes, data); +```` + +### Field Example +```rust +# use deku::prelude::*; +# use std::convert::{TryInto, TryFrom}; +# #[derive(Debug, DekuRead, DekuWrite, PartialEq)] +pub struct LsbField { + #[deku(bit_order = "lsb", bits = "13")] + offset: u16, + #[deku(bit_order = "lsb", bits = "3")] + t: u8, +} + +let data = vec![0x40, 0x40]; +let more_first = LsbField::try_from(data.as_ref()).unwrap(); +assert_eq!(more_first, LsbField { offset: 0x40, t: 2 }); + +let bytes = more_first.to_bytes().unwrap(); +assert_eq!(bytes, data); +``` # magic diff --git a/src/ctx.rs b/src/ctx.rs index df7c3ddc..2935c472 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -4,12 +4,12 @@ use core::marker::PhantomData; use core::str::FromStr; -/// An Bit Order +/// Bit numbering #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Order { - /// Big endian + /// Most significant bit Msb0, - /// Little endian + /// least significant bit Lsb0, } diff --git a/tests/bit_order.rs b/tests/bit_order.rs index 9fe1c9a0..1b826775 100644 --- a/tests/bit_order.rs +++ b/tests/bit_order.rs @@ -229,13 +229,30 @@ pub struct MoreFirst { fn test_bit_order_more_first() { let data = vec![0x40, 0x40]; let more_first = MoreFirst::try_from(data.as_ref()).unwrap(); - // bits: 13 3 assert_eq!(more_first, MoreFirst { offset: 0x40, t: 2 }); let bytes = more_first.to_bytes().unwrap(); assert_eq_hex!(bytes, data); } +#[derive(Debug, DekuRead, DekuWrite, PartialEq)] +pub struct LsbField { + #[deku(bit_order = "lsb", bits = "13")] + offset: u16, + #[deku(bit_order = "lsb", bits = "3")] + t: u8, +} + +#[test] +fn test_bit_order_lsb_field() { + let data = vec![0x40, 0x40]; + let more_first = LsbField::try_from(data.as_ref()).unwrap(); + assert_eq!(more_first, LsbField { offset: 0x40, t: 2 }); + + let bytes = more_first.to_bytes().unwrap(); + assert_eq_hex!(bytes, data); +} + #[test] fn test_bit_order_custom_reader_writer() { fn reader_lsb(reader: &mut Reader) -> Result<(u16, u8), DekuError> { @@ -309,7 +326,6 @@ pub struct MoreFirstBe { #[test] fn test_bit_order_more_first_be() { - env_logger::init(); let data = vec![0x40, 0x40]; let more_first = MoreFirstBe::try_from(data.as_ref()).unwrap(); assert_eq!(