#bitfield #storage #handwritten

bitfields

Helpers for storing sub-byte enums in primitive types

2 unstable releases

Uses old Rust 2015

0.2.0 Mar 20, 2019
0.1.0 Aug 8, 2018

#1075 in Rust patterns

Download history 175/week @ 2022-08-10 145/week @ 2022-08-17 160/week @ 2022-08-24 144/week @ 2022-08-31 171/week @ 2022-09-07 145/week @ 2022-09-14 155/week @ 2022-09-21 168/week @ 2022-09-28 193/week @ 2022-10-05 139/week @ 2022-10-12 135/week @ 2022-10-19 59/week @ 2022-10-26 66/week @ 2022-11-02 56/week @ 2022-11-09 59/week @ 2022-11-16 26/week @ 2022-11-23

211 downloads per month
Used in 5 crates (via kompact)

WTFPL license

13KB
319 lines

bitfields-rs

Helpers for storing sub-byte enums in primitive types.

Example


fn example() {
  // Could either be handwritten or extracted from a serialized network buffer
  let mut storage = vec![0u8];
  // write TCP bits
  storage.store(Transport::TCP).unwrap();
  // write address type bits
  storage.store(AddressType::IPv4).unwrap();
  
  // retrieve as named enums from positions indicated by `BitField` implementations
  assert_eq!(storage.get_as::<Transport>().unwrap(), Transport::TCP);
  assert_eq!(storage.get_as::<AddressType>().unwrap(), AddressType::IPv4);
}


#[derive(Debug, PartialEq)]
#[repr(u8)]
enum Transport {
  TCP = 0b01,
  UDP = 0b10,
  UDT = 0b11,
}

#[derive(Debug, PartialEq)]
#[repr(u8)]
pub enum AddressType {
    IPv4 = 0,
    IPv6 = 1,
    DomainName = 2,
}


impl BitField for Transport {
  const POS: usize = 0;
  const WIDTH: usize = 2;
}

impl BitField for AddressType {
    const POS: usize = 2;
    const WIDTH: usize = 2;
}

impl Into<u8> for AddressType {
    fn into(self) -> u8 {
        self as u8
    }
}

impl Into<u8> for Transport {
  fn into(self) -> u8 {
    self as u8
  }
}

impl TryFrom<u8> for AddressType {
    type Error = SerError;

    fn try_from(x: u8) -> Result<Self, Self::Error> {
        match x {
            x if x == AddressType::IPv4 as u8 => Ok(AddressType::IPv4),
            x if x == AddressType::IPv6 as u8 => Ok(AddressType::IPv6),
            _ => Err(SerError::InvalidType("Unsupported AddressType".into())),
        }
    }
}

impl TryFrom<u8> for Transport {
  type Error = ();

  fn try_from(value: u8) -> Result<Self, Self::Error> {
    match value {
      0b01 => Ok(Transport::TCP),
      0b10 => Ok(Transport::UDP),
      0b11 => Ok(Transport::UDT),
      _ => Err(()),
    }
  }
}

No runtime deps