atom-macho 0.1.0

MachO file format primitives
Documentation
use byteorder::{BigEndian, LittleEndian, NativeEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Read, Write};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Endian {
    Little,
    Big,
}

#[cfg(target_endian = "little")]
impl Endian {
    pub const NATIVE: Endian = Endian::Little;
    pub const REVERSE: Endian = Endian::Big;
}

#[cfg(target_endian = "big")]
impl Endian {
    pub const NATIVE: Endian = Endian::Big;
    pub const REVERSE: Endian = Endian::Little;
}

macro_rules! read_in {
    ($func:ident, $endian:expr) => {
        match $endian {
            Endian::Little => ReadBytesExt::$func::<LittleEndian>,
            Endian::Big => ReadBytesExt::$func::<BigEndian>,
        }
    };
}

pub trait ReadExt: Read + ReadBytesExt {
    fn read_u8(&mut self) -> u8 {
        ReadBytesExt::read_u8(self).unwrap()
    }

    fn read_u16_in(&mut self, endian: Endian) -> u16 {
        read_in!(read_u16, endian)(self).unwrap()
    }

    fn read_i32_in(&mut self, endian: Endian) -> i32 {
        read_in!(read_i32, endian)(self).unwrap()
    }

    fn read_u32_in(&mut self, endian: Endian) -> u32 {
        read_in!(read_u32, endian)(self).unwrap()
    }

    fn read_u64_in(&mut self, endian: Endian) -> u64 {
        read_in!(read_u64, endian)(self).unwrap()
    }

    fn read_fixed_size_string(&mut self, size: usize) -> String {
        let mut buf = vec![0u8; size];
        self.read_exact(&mut buf).unwrap();

        let valid_len = buf.split(|&b| b == 0).next().unwrap().len();
        buf.truncate(valid_len);
        String::from_utf8(buf).unwrap()
    }
}

impl<T> ReadExt for T where T: Read {}

pub trait WriteExt: Write + WriteBytesExt {
    fn write_u8(&mut self, n: u8) {
        WriteBytesExt::write_u8(self, n).unwrap()
    }

    fn write_u16_native(&mut self, n: u16) {
        self.write_u16::<NativeEndian>(n).unwrap()
    }

    fn write_i32_native(&mut self, n: i32) {
        self.write_i32::<NativeEndian>(n).unwrap()
    }

    fn write_u32_native(&mut self, n: u32) {
        self.write_u32::<NativeEndian>(n).unwrap()
    }

    fn write_u64_native(&mut self, n: u64) {
        self.write_u64::<NativeEndian>(n).unwrap()
    }

    fn write_fixed_size_string(&mut self, s: &str, size: usize) {
        assert!(s.is_ascii());
        assert!(s.len() <= size);

        let mut buf = vec![0u8; size];

        for (i, c) in s.chars().enumerate() {
            buf[i] = c as u8;
        }

        self.write_all(&buf).unwrap();
    }
}

impl<T> WriteExt for T where T: Write {}