Wednesday 13 May 2015

Rust: serializing structs to bytes

Back when I wrote C code for platform-dependent binary formats it was fairly common to perform stream I/O with structs and unions. This post looks at similar functionality in Rust.

use std::mem;

#[allow(dead_code)]
pub struct Ser {
  prop: u32
}

pub fn to_bytes(ser: Ser) -> [u8; 4] {
  unsafe { mem::transmute_copy::<Ser, [u8; 4]>(&ser) }
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_to_bytes() {
    let instance = Ser { prop: 0x0A0B0C0D };
    let bigend = Ser { prop: instance.prop.to_be() };
    let actual = to_bytes(bigend);
    let expected: [u8; 4] = [0xA, 0xB, 0xC, 0xD];
    assert_eq!(expected, actual);
  }
}

In the above example a struct's byte representation is accessed directly and a copy is taken. This requires an unsafe block.

use std::mem;

#[allow(dead_code)]
pub struct DeSer {
  prop: u32
}

pub fn from_bytes(arr: [u8; 4]) -> DeSer {
  unsafe { mem::transmute_copy::<[u8; 4], DeSer>(&arr) }
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn test_from_bytes() {
    let expected = DeSer { prop: 0x0A0B0C0D };
    let instance: [u8; 4] = [0xA, 0xB, 0xC, 0xD];
    let actual = from_bytes(instance);
    let sysend = u32::from_be(actual.prop);
    assert_eq!(expected.prop, sysend);
  }
}

De-serialising a struct from bytes is very similar.

This post is just a code snippet written by someone getting started. No promises are made about code quality. Version: rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-04-30)

No comments:

Post a Comment

All comments are moderated