Crate simple_endian

source ·
Expand description

Many byte-order-handling libraries focus on providing code to convert to and from big- or little-endian. However, this requires users of those libraries to use a lot of explicit logic. This library uses the Rust type system to enforce conversions invisibly, and also ensure that they are done consistently. A struct member can be read and written simply using the standard From and Into trait methods (from() and into()). No explicit endian checks are required.

§Example 1:

 use simple_endian::*;

 fn init() {
     #[repr(C)]
     struct BinPacket {
         a: u64be,
         b: u32be,
     }
     let mut bp = BinPacket{a: 0xfe.into(), b: 10.into()};
     let new_a = bp.a.to_native() * 1234;
     bp.a = new_a.into();
     bp.b = 1234.into();
 }

Trying to write bp.a = new_a; causes an error because the type u64 can’t be directly stored.

§Example 2: Writing a portable struct to a file.

Of course, just storing things in memory isn’t that useful unless you write somewhere.

use simple_endian::*;
use std::fs::File;
use std::io::prelude::*;
use std::mem::{transmute, size_of};

// We have to specify a representation in order to define the layout.
#[repr(C)]
struct BinBEStruct {
    pub a: u64be,
    b: u64be,
    c: f64be,
}

fn main() -> std::io::Result<()> {
   let bin_struct = BinBEStruct{a: 345.into(), b: 0xfee.into(), c: 9.345.into()};

   let mut pos = 0;
   let mut data_file = File::create(".test.bin")?;
   let buffer = unsafe { transmute::<&BinBEStruct, &[u8; size_of::<BinBEStruct>()]>(&bin_struct) };

   while pos < buffer.len() {
       let bytes_written = data_file.write(&buffer[pos..])?;
       pos += bytes_written;
   }
   Ok(())
}

§Example 3: Mmapping a portable struct with the memmap crate.

You’ll need to add memmap to your Cargo.toml to get this to actually work:

extern crate memmap;

 use std::{
    io::Error,
    fs::OpenOptions,
    mem::size_of,
};

use memmap::MmapOptions;
use simple_endian::*;

#[repr(C)]
struct MyBEStruct {
    header: u64be,
    label: [u8; 8],
    count: u128be,
}

fn main() -> Result<(), Error> {
    let file = OpenOptions::new()
        .read(true).write(true).create(true)
        .open(".test.bin")?;

    // Truncate the file to the size of the header.
    file.set_len(size_of::<MyBEStruct>() as u64)?;
    let mut mmap = unsafe { MmapOptions::new().map_mut(&file)? };

    let mut ptr = mmap.as_mut_ptr() as *mut MyBEStruct;

    unsafe {
        // Set the magic number
        (*ptr).header = 0xfeedface.into();

        // Increment the counter each time we run.
        (*ptr).count += 1.into();

        (*ptr).label = *b"Iamhere!";
    }

    println!("done.");
    Ok(())
}

Structs§

  • A big-endian representation of type T that implements SpecificEndian<T>. Data stored in the struct must be converted to big-endian using ::from() or .into().
  • A little-endian representation of type T that implements SpecificEndian<T>. Data stored in the struct must be converted to little-endian using ::from() or .into().

Traits§

  • Any object implementing SpecificEndian<T> can be converted between big and little endian. Implement this trait to allow for endian conversion by this crate.

Type Aliases§

  • Shorthand for BigEndian<f32>
  • Shorthand for LittleEndian<f32>
  • Shorthand for BigEndian<f64>
  • Shorthand for LittleEndian<f64>
  • Shorthand for BigEndian<i16>
  • Shorthand for LittleEndian<i16>
  • Shorthand for BigEndian<i32>
  • Shorthand for LittleEndian<i32>
  • Shorthand for BigEndian<i64>
  • Shorthand for LittleEndian<i64>
  • Shorthand for BigEndian<i128>
  • Shorthand for LittleEndian<i128>
  • Shorthand for BigEndian<isize>
  • Shorthand for LittleEndian<isize>
  • Shorthand for BigEndian<u16>
  • Shorthand for LittleEndian<u16>
  • Shorthand for BigEndian<u32>
  • Shorthand for LittleEndian<u32>
  • Shorthand for BigEndian<u64>
  • Shorthand for LittleEndian<u64>
  • Shorthand for BigEndian<u128>
  • Shorthand for LittleEndian<u128>
  • Shorthand for BigEndian<usize>
  • Shorthand for LittleEndian<usize>