NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #3836 most downloaded on crates.io
bit level serialization/deserialization proc-macro for structs
Last release 8 months ago
15 Jan 2026
Release timing varies
gaps range from 4 weeks to 1.2 years
Most releases are documented
notes for 35 of 39 stable releases
8 versions withdrawn
withdrawn after publishing
7 years old
47 releases · first in 2020
One column per quarter.
DekuSize: Add padding size calculation
### Other - Fix recursive DekuSize impl
Uphold alignment requirements for use of Seek
remove unsafe slice MaybeUninit::uninit().assume_init()
alloc as a selectable feature (#582)bits entry from the 'List of attributes' section of attributes docs (#588)id via ctx and whose variants assign discriminant values (#577)Add missing alloc::vec by @wcampbell0x2a in #550
Full Changelog: deku-v0.19.0...deku-v0.19.1
After much development, bit_order is now a supported attribute! Msb is still the default bit-order for all operations, but if you need Lsb ordering, d
bit_order (#483)After much development, bit_order is now a supported attribute! Msb is still the default bit-order for all operations,
but if you need Lsb ordering, deku now has you covered.
For example, the following is now possible:
# #[derive(Debug, DekuRead, DekuWrite, PartialEq)]
#[deku(bit_order = "lsb")] // <--
pub struct SquashfsV3 {
#[deku(bits = "4")]
inode_type: u8,
#[deku(bits = "12")]
mode: u16,
uid: u8,
guid: u8,
mtime: u32,
inode_number: u32,
}
let data: &[u8] = &[
// inode_type
// ╭-----------
// |
// | mode
// ╭+-------- ...and so on
// || ||
// vv vv
0x31, 0x12, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
];If you were using our internal reader the following changed. As well as the leftover field now containing ordering.
- reader.read_bytes(exact.0, &mut bytes)?;
+ reader.read_bytes(exact.0, &mut bytes, Order::Lsb0)?;CString (#497)#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct Data {
len: u8,
#[deku(bytes = "*len as usize")]
s: CString,
}id_pat (#540)The id_pat attribute has been restored to the behavior of 0.16.0, removing the seek and re-read.
bytes attribute (#489)# #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a_size: u8,
#[deku(bytes = "*field_a_size as usize")]
field_a: u32,
}Arc support by @vhdirk (#522)no-std-io2 to 0.9.0 and Updated MSRV to 1.81 (#529)magic attribute (#503)NoSeek type for unseekable Read + Write impls (#487)count attribute + Vec<u8>(#481)Reader may now take ownership of Read + Seek type. Thanks @wgreenburg (#521).Nothing published for this version
Reading now requires Seek . Attributes such as seek_from_start , seek_from_current , seek_from_end , and seek_rewind were added to be able to control
Seek. Attributes such as seek_from_start, seek_from_current, seek_from_end, and seek_rewind were added to be able to control the position of the reader before reading a field (#360)to_slice was added to write an to a slice (#461)read_all was improved (#441)Add no-assert-string feature to remove panic string on failed assertion
1.71 (#438)[T] (#416)no-assert-string feature to remove panic string on failed assertion (#405)read_all attribute to read until reader.end() (#387)logging feature with massive usability increases (#352), (#355)syn library to 2.0, which required replacing type for Enums with id_type (#386) #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
-#[deku(type = "u8")]
+#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC((u8, u8)),
}io::Read, bringing massive performance and usability improvements (#352)DekuRead to DekuReaderFor example:
use std::io::{Seek, SeekFrom, Read};
use std::fs::File;
use deku::prelude::*;
#[derive(Debug, DekuRead, DekuWrite, PartialEq, Eq, Clone, Hash)]
#[deku(endian = "big")]
struct EcHdr {
magic: [u8; 4],
version: u8,
padding1: [u8; 3],
}
let mut file = File::options().read(true).open("file").unwrap();
let ec = EcHdr::from_reader((&mut file, 0)).unwrap();read(..) was replaced with from_reader_with_ctx(..).deku::input, deku::input_bits, and deku::rest are now not possible and were removed.deku::reader is a replacement for some of the functionality.Old:
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,
#[deku(
reader = "bit_flipper_read(*field_a, deku::rest, BitSize(8))",
)]
field_b: u8,
}
fn custom_read(
field_a: u8,
rest: &BitSlice<u8, Msb0>,
bit_size: BitSize,
) -> Result<(&BitSlice<u8, Msb0>, u8), DekuError> {
// read field_b, calling original func
let (rest, value) = u8::read(rest, bit_size)?;
Ok((rest, value))
}New:
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,
#[deku(
reader = "bit_flipper_read(*field_a, deku::reader, BitSize(8))",
)]
field_b: u8,
}
fn custom_read<R: std::io::Read>(
field_a: u8,
reader: &mut Reader<R>,
bit_size: BitSize,
) -> Result<u8, DekuError> {
// read field_b, calling original func
let value = u8::from_reader_with_ctx(reader, bit_size)?;
Ok(value)
}Read, containing a byte slice with a reference is not supported:Old
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
struct TestStruct<'a> {
bytes: u8,
#[deku(bytes_read = "bytes")]
data: &'a [u8],
}New
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
struct TestStruct {
bytes: u8,
#[deku(bytes_read = "bytes")]
data: Vec<u8>,
}id_pat is now required to be the same type as stored id.Old:
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC((u8, u8)),
}New:
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC {
id: u8,
other: u8,
},
}const_generics was removed and is enabled by default.io::Write, bringing massive performance and usability improvements (#355)DekuWrite to DekuWriterwrite(..) was replaced with to_writer(..).deku::output are now not possible and were removed. deku::writer is a replacement for some of the functionality.Old:
fn bit_flipper_write(
field_a: u8,
field_b: u8,
output: &mut BitVec<u8, Msb0>,
bit_size: BitSize,
) -> Result<(), DekuError> {
// Access to previously written fields
println!("field_a = 0x{:X}", field_a);
// value of field_b
println!("field_b = 0x{:X}", field_b);
// Size of the current field
println!("bit_size: {:?}", bit_size);
// flip the bits on value if field_a is 0x01
let value = if field_a == 0x01 { !field_b } else { field_b };
value.write(output, bit_size)
}
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,
#[deku(
writer = "bit_flipper_write(*field_a, *field_b, deku::output, BitSize(8))"
)]
field_b: u8,
}New:
fn bit_flipper_write<W: Write>(
field_a: u8,
field_b: u8,
writer: &mut Writer<W>,
bit_size: BitSize,
) -> Result<(), DekuError> {
// Access to previously written fields
println!("field_a = 0x{:X}", field_a);
// value of field_b
println!("field_b = 0x{:X}", field_b);
// Size of the current field
println!("bit_size: {:?}", bit_size);
// flip the bits on value if field_a is 0x01
let value = if field_a == 0x01 { !field_b } else { field_b };
value.to_writer(writer, bit_size)
}
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,
#[deku(
writer = "bit_flipper_write(*field_a, *field_b, deku::writer, BitSize(8))"
)]
field_b: u8,
}DekuError::Write to denote io::Write errorsFaster build times: Optimize derive macros (@dullbananas)
id (@wcampbell0x2a) (#315)Small bug fix: Use fully qualified path when calling write as it may clash with other impls
Small bug fix: Use fully qualified path when calling write as it may clash with other impls
Upgrade to bitvec 1.0.0 may cause some breaking changes in some code bases.
Fix issue where endianness trickery wouldn't swap bytes correctly when reading less than the full amount into an integer (@caass)
This release introduces a performance specialization/optimization in the read path for bytes
This release introduces a performance specialization/optimization in the read path for bytes
Size enum removed in favor of BitSize and ByteSize, this change is to allow a performance optimization in the byte readingDocumentation fix for Size::byte_size (@korrat)
Size::byte_size (@korrat) (#261)Clone on DekuError (@interruptinuse) (#255)MaybeUninit in slice implementation (#254)Fixed no_std example/tests (@korrat)
(Backport) Fixed undefined behavior in the use of MaybeUninit in slice implementation
MaybeUninit in slice implementation (#254)Show struct ident in assertion error message (@wcampbell0x2a)
Add Read/Write impls for generic arrays (@xlambein)
Bug fix for structs/enums which also define a to_bytes function
to_bytes functionBug fix for in primitive bitslice convertion (issue/commit)
Add support for raw indentifiers (@Visse)
const_generics feature enabled by default
const_generics feature enabled by defaultconst_generics feature (@soruh) (#187)
Removed bitvec from deku::prelude
bitvec from deku::prelude (#181)
reader and writer function definitionsbitvec is re-exported via: deku::bitvec:: (this contains bitvec::prelude::*)DekuEnumExt to provide extra utility functions to enums. (#176)
#[derive(DekuRead)]deku_id()deku_id can be called on an enum variant to get the deku id of the variantIncomplete(NeedSize) variant on DekuError (#177)CODE_OF_CONDUCT.mdUpdate bitvec dependency to fix build failures
Enum's which don't specify an id attribute now default to their discriminant value instead of being treated as a catch-all
id attribute now default to their discriminant value
instead of being treated as a catch-all (#139)BitSize in favor of a new enum Size with two variants, Bits and Bytes (#138)deku:: is used to access internal variables in token fields. (#150)
For example, reader = "my_reader(deku::rest, deku::bit_offset)" or writer = "my_writer(deku::output)"DekuRead in support of zero-copy reading (#158)pad_bits_before, pad_bytes_before, pad_bits_after, pad_bytes_after (#163)assert, assert_eq (#164)type attribute (#162)id attribute, for example id = b"0x01" (#162)deku:: namespace, deku::bit_offset and deku::byte_offset. (#150)#[deku(temp)] attribute, enabled via deku_derive proc-macro attribute. (#136)
This allows reading/use of a field without it being stored in the container.Patch release to fix semver break in darling, this has since been fixed
Patch release to fix semver break in darling, this has since been fixed
Changed minimum bitvec version to 0.19.4 to have desired offset_from functionality (https://github.com/myrrlyn/bitvec/issues/86). This was missed in 0
offset_from
functionality (https://github.com/myrrlyn/bitvec/issues/86). This was missed in
0.9.0 release.Added magic attribute, this allows the ability to specify a set of bytes which must be present at the start of the data (@samuelsleight)
magic attribute, this allows the ability to specify a set of bytes
which must be present at the start of the data
(@samuelsleight)until attribute, this allows the ability to read until a given predicate
(@samuelsleight)bits_read and bytes_read container attributes, this allows the ability to specify
an amount of bits/bytes to read inside a Vec<T>
(@samuelsleight)write now takes a &mut BitVec instead of returning a BitVec, this optimization speeds up serialization (@agausmann)
write now takes a &mut BitVec instead of returning a BitVec, this optimization
speeds up serialization (@agausmann)The following items have been renamed: (@wcampbell0x2a)
id_type in favor of typeid_bits in favor of bitsid_bytes in favor of bytesInternal:
Added ctx_default attribute, this allows the ability to specify defaults to types accepting a ctx if none are provided
ctx_default attribute, this allows the ability to specify defaults to
types accepting a ctx if none are providedid attributeendian attribute now accepts an expression (still accepts big or little)Added id attribute to top-level enums which allows to specify the enum id, for example a value coming via a context variable
id attribute to top-level enums which allows to specify the enum id,
for example a value coming via a context variableAdded cond attribute which allows for conditional parsing or skipping of a field
cond attribute which allows for conditional parsing or skipping of a fieldid_pat attribute which allows pattern matching for enum variantsCommunity:
ctx attribute which adds the ability to pass context to child parsers from the parent (@constfold)endian, bits and count attributes, they are now sugar around the ctx (@constfold)to_bitvec to to_bits (@wcampbell0x2a)Enum variant specified without an id attribute is now considered the catch-all
id attribute is now considered the catch-allAdded DekuContainerRead and DekuContainerWrite to expose from_bytes, to_bytes and to_bitvec
DekuContainerRead and DekuContainerWrite to expose from_bytes, to_bytes and to_bitvecrelease.tomlCHANGELOG.md to track changesNothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →