Using byteorder generically?


#1

I’ve been looking around for something that does this, and maybe I’m missing something obvious, but what I’d like to do is something like:

trait OB {
    fn from_bytes(bytes: &[u8]) -> Self;
}

...

fn foo<T: OB>(bytes: &[u8]) {
    let v = T::from_bytes(bytes);
}

Where OB is implemented for the primitive integer and float types. Essentially, I want the byteorder crate, but with a trait that lets me use it in generic contexts. I tried writing it up, and this is what I came up with:

use byteorder::ByteOrder;

pub trait OrderBytes {
    fn from_bytes<B: ByteOrder>(bytes: &[u8]) -> Self;
}

impl OrderBytes for u8 {
    fn from_bytes<B: ByteOrder>(bytes: &[u8]) -> u8 {
        *bytes.first().unwrap()
    }
}

impl OrderBytes for i8 {
    fn from_bytes<B: ByteOrder>(bytes: &[u8]) -> i8 {
        let b: *const u8 = bytes.first().unwrap();
        unsafe { *(b as *const i8) }
    }
}

macro_rules! order_bytes_impl {
    ($int_type:ident, $reader_fn:ident) => {
        impl OrderBytes for $int_type {
            fn from_bytes<B: ByteOrder>(bytes: &[u8]) -> $int_type {
                B::$reader_fn(bytes)
            }
        }
    }
}

order_bytes_impl!(u16, read_u16);
order_bytes_impl!(i16, read_i16);
order_bytes_impl!(u32, read_u32);
order_bytes_impl!(i32, read_i32);
order_bytes_impl!(u64, read_u64);
order_bytes_impl!(i64, read_i64);
order_bytes_impl!(f32, read_f32);
order_bytes_impl!(f64, read_f64);

Is there something already out there that does this?