dcpu 0.5.0

An assembler, debugger and emulator for the DCPU-16
Documentation
use std::io::prelude::*;
use std::io;
use std::marker::PhantomData;

pub trait WriteBytesExt: Write {
    fn write_item<I, B>(&mut self, item: I) -> io::Result<()>
    where I: Item, B: ByteOrder {
        let mut data = item.encode_to_big_endian();
        B::encode_to_big_endian::<I>(&mut data);
        self.write_all(data.as_ref())
    }

    fn write_all_items<I, B>(&mut self, items: &[I]) -> io::Result<()>
    where I: Item + Clone, B: ByteOrder {
        for item in items {
            try!(self.write_item::<I, B>(item.clone()));
        }
        Ok(())
    }
}
pub trait ReadBytesExt: Read {
    fn read_item<I: Item, B: ByteOrder>(&mut self) -> io::Result<I> {
        let mut buf = I::Buf::default();
        try!(self.read_exact(buf.as_mut()));
        B::decode_from_big_endian::<I>(&mut buf);
        Ok(I::decode_from_big_endian(&buf))
    }

    fn iter_items<I: Item, B: ByteOrder>(&mut self) -> Iter<Self, I, B> {
        Iter {
            inner: self,
            _phantom: PhantomData,
        }
    }
}

pub struct Iter<'a, R: ReadBytesExt + ?Sized + 'a, I, B> {
    inner: &'a mut R,
    _phantom: PhantomData<(I, B)>,
}

impl<'a, R: ReadBytesExt + ?Sized + 'a, I: Item, B: ByteOrder> Iterator for Iter<'a, R, I, B> {
    type Item = I;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.read_item::<I, B>().ok()
    }
}

impl<W: Read + ?Sized> ReadBytesExt for W {}
impl<W: Write + ?Sized> WriteBytesExt for W {}

pub trait ByteOrder {
    fn encode_to_big_endian<I: Item>(&mut I::Buf);
    fn decode_from_big_endian<I: Item>(&mut I::Buf);
}

pub enum BigEndian {}
pub enum LittleEndian {}

impl ByteOrder for BigEndian {
    fn encode_to_big_endian<I: Item>(_: &mut I::Buf) {
    }
    fn decode_from_big_endian<I: Item>(_: &mut I::Buf) {
    }
}
impl ByteOrder for LittleEndian {
    fn encode_to_big_endian<I: Item>(buf: &mut I::Buf) {
        buf.as_mut().reverse();
    }
    fn decode_from_big_endian<I: Item>(buf: &mut I::Buf) {
        buf.as_mut().reverse();
    }
}

pub trait Item {
    type Buf: AsRef<[u8]> + AsMut<[u8]> + Default;
    fn encode_to_big_endian(&self) -> Self::Buf;
    fn decode_from_big_endian(&Self::Buf) -> Self;
}

impl Item for u16 {
    type Buf = [u8; 2];

    fn encode_to_big_endian(&self) -> Self::Buf {
        [(*self >> 8) as u8, *self as u8]
    }

    fn decode_from_big_endian(buf: &Self::Buf) -> u16 {
        (buf[0] as u16) << 8 | buf[1] as u16
    }
}