Crate enum_parity

Crate enum_parity 

Source
Expand description

This crate exposes the bit_parity macro to enforce a given bit parity

§Motivation

Without bit parity, erroneous/random bit flips can lead to unexpected behavior.

§Without Bit Parity

use enum_parity::bit_parity;
use serde_repr::{Serialize_repr, Deserialize_repr};

#[repr(u8)]
// `serialize_repr` must be used, because `serde` uses enum indexes for binary serializations
#[derive(Serialize_repr, Deserialize_repr)]
enum Foo { A, B, C, D }

let val = Foo::A;
let mut serialized_val = postcard::to_allocvec(&val).unwrap();

// *Random bit flip*
serialized_val[0] |= 0x01;

// This successfully deserializes, but is the incorrect value!
let new_val: Foo = postcard::from_bytes(&serialized_val).unwrap();
assert_eq!(new_val, Foo::B);
assert_ne!(val, new_val);

§With Bit Parity

#[repr(u8)]
#[bit_parity(even)] // using bit parity!
#[derive(Serialize_repr, Deserialize_repr)]
enum Foo { A, B, C, D }
let val = Foo::A;
let mut serialized_val = postcard::to_allocvec(&val).unwrap();

// *Random bit flip*
serialized_val[0] |= 0x01;

// This fails to deserialize
let new_par_err: postcard::Result<Foo> = postcard::from_bytes(&serialized_val);
assert_eq!(new_par_err, Err(postcard::Error::SerdeDeCustom));

§Examples

§Even Bit Parity

use enum_parity::bit_parity;

#[repr(u8)]
#[bit_parity(even)]
pub enum EvenSample {
    Foo,
    Bar,
    Baz,
    Quo,
}

assert_eq!(EvenSample::Foo as u8, 0x00);
assert_eq!(EvenSample::Bar as u8, 0x03);
assert_eq!(EvenSample::Baz as u8, 0x05);
assert_eq!(EvenSample::Quo as u8, 0x06);

§Odd Bit Parity

use enum_parity::bit_parity;

#[repr(u8)]
#[bit_parity(odd)]
pub enum OddSample {
    Lorem,
    Ipsum,
    Dolor,
    Sit,
}

assert_eq!(OddSample::Lorem as u8, 0x01);
assert_eq!(OddSample::Ipsum as u8, 0x02);
assert_eq!(OddSample::Dolor as u8, 0x04);
assert_eq!(OddSample::Sit as u8, 0x07);

Attribute Macros§

bit_parity
An attribute macro for enums that enforces discriminant bit parity