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§
- BigEndian
- A big-endian representation of type
Tthat implementsSpecificEndian<T>. Data stored in the struct must be converted to big-endian using::from()or.into(). - Little
Endian - A little-endian representation of type
Tthat implementsSpecificEndian<T>. Data stored in the struct must be converted to little-endian using::from()or.into().
Enums§
- Endian
- Any object implementing
SpecificEndian<T>can be converted between big and little endian. Implement this trait to allow for endian conversion by this crate.
Traits§
Type Aliases§
- f32be
- Shorthand for
BigEndian<f32> - f32le
- Shorthand for
LittleEndian<f32> - f64be
- Shorthand for
BigEndian<f64> - f64le
- Shorthand for
LittleEndian<f64> - i16be
- Shorthand for
BigEndian<i16> - i16le
- Shorthand for
LittleEndian<i16> - i32be
- Shorthand for
BigEndian<i32> - i32le
- Shorthand for
LittleEndian<i32> - i64be
- Shorthand for
BigEndian<i64> - i64le
- Shorthand for
LittleEndian<i64> - i128be
- Shorthand for
BigEndian<i128> - i128le
- Shorthand for
LittleEndian<i128> - isizebe
- Shorthand for
BigEndian<isize> - isizele
- Shorthand for
LittleEndian<isize> - u16be
- Shorthand for
BigEndian<u16> - u16le
- Shorthand for
LittleEndian<u16> - u32be
- Shorthand for
BigEndian<u32> - u32le
- Shorthand for
LittleEndian<u32> - u64be
- Shorthand for
BigEndian<u64> - u64le
- Shorthand for
LittleEndian<u64> - u128be
- Shorthand for
BigEndian<u128> - u128le
- Shorthand for
LittleEndian<u128> - usizebe
- Shorthand for
BigEndian<usize> - usizele
- Shorthand for
LittleEndian<usize>