Trait for numeric type as a generic

Which trait does implement "from_le_bytes"? I want to use i32 and u32 inplace of generic parameter T.

I need this code to compile:

pub fn read_vector<T:????????>(fname: &str) -> Result<(Vec<T>)> {
    let fnodes = File::open(fname).unwrap();
    let mut reader = BufReader::new(fnodes);
    let mut buffer = [0; 4];
    let mut nodes = Vec::<T>::new();
    while reader.read(&mut buffer)? != 0 {
        let node = T::from_le_bytes(buffer);
        nodes.push(node);
    }
    Ok(nodes)
}

They are inherent methods on the types, not from a trait.

There's a PR for num-traits that I really should get back to:

Currently the easiest is to create your own trait:

trait AsFourBytes {
    fn to_bytes(self) -> [u8; 4];
    fn from_bytes(bytes: [u8; 4]) -> Self;
}

impl AsFourBytes for u32 {
    fn to_bytes(self) -> [u8; 4] { self.to_le_bytes() }
    fn from_bytes(bytes: [u8; 4]) -> u32  { u32::from_le_bytes(bytes) }
}

impl AsFourBytes for i32 {
    fn to_bytes(self) -> [u8; 4] { self.to_le_bytes() }
    fn from_bytes(bytes: [u8; 4]) -> i32  { i32::from_le_bytes(bytes) }
}
4 Likes

It should be noted that this usage of Read::read is incorrect. A call to read may return fewer than 4 bytes. (e.g. if we are fewer than 4 bytes away from the end of the BufReader's buffer)

You will need to use read_exact, but I'm not sure how you can differentiate between an UnexpectedEof after 0 bytes (your termination condition) versus an UnexpectedEof after n != 0 bytes (which ought to be an error).

Thanks!
What if I want i16,u16, i32, u32 in one trait? Something like this

trait AsBytes {
    fn to_bytes(self) -> [u8; ?];
    fn from_bytes(bytes: [u8; ?]) -> Self;
}

You're looking for something like this, but that's called const generics and has yet to land.

You can add type Array: AsRef<[u8]> to the top of the trait and use Self::Array instead of the array. Then in the impl you just type type Array = [u8; 4];, of course with the correct number.

You might also want to add a LENGTH as an associated constant, so you can mention the length in your own code as T::LENGTH.