1

How can I implement a generic function in Rust in a way that can convert a generic type T (u16, u32, or u64) into a Vec<u8> using either little-endian or big-endian formats.

E.g. (not valid Rust code):

fn convert<T>(a: T) -> vec<u8> {
   // a = 0x01234567
   // returns vec![0x01, 0x23, 0x45, 0x67]
}
gagiuntoli
  • 475
  • 5
  • 13
  • Does this answer your question? [Converting number primitives (i32, f64, etc) to byte representations](https://stackoverflow.com/questions/29445026/converting-number-primitives-i32-f64-etc-to-byte-representations) – ShadowRanger Jun 23 '22 at 21:02
  • 1
    Not exactly, I know about `to_le/be_bytes` but how should I implement that trait? is there any crate that has that already implemented in a way that I add that to `T`? – gagiuntoli Jun 23 '22 at 21:05
  • In addition to what ShadowRanger said, if you need it to be generic, you'd define a `trait IntoBytes` with an associated `fn into_bytes() -> Vec` and `impl IntoBytes for u16`, etc. Then you'd require that trait bound on you function: `fn convert`, and you can use `a.into_bytes()` in your function. – PitaJ Jun 23 '22 at 21:06
  • @gagiuntoli: Why do you need `convert` at all, when you can just call `a.to_le_bytes()` or the like diretly? Regardless, the duplicate's current accepted answer suggests the `byteorder` crate as an option, with example code. I'm not seeing what's missing. – ShadowRanger Jun 23 '22 at 21:08
  • Because I need to compute stuff inside the functions with `a` and then transform a `T` type (not `a`) to bytes – gagiuntoli Jun 23 '22 at 21:10

1 Answers1

1

As @PitaJ suggested implementing a trait solves this problem, here is a working example:

trait IntoBytes: Sized {
    fn to_le_bytes(a: Self) -> Vec<u8>;
}

impl IntoBytes for u16 {
    fn to_le_bytes(a: Self) -> Vec<u8> {
        a.to_le_bytes().to_vec()
    }
}

impl IntoBytes for u32 {
    fn to_le_bytes(a: Self) -> Vec<u8> {
        a.to_le_bytes().to_vec()
    }
}

impl IntoBytes for u64 {
    fn to_le_bytes(a: Self) -> Vec<u8> {
        a.to_le_bytes().to_vec()
    }
}

fn foo<T: IntoBytes>(a: T) -> Vec<u8> {
    T::to_le_bytes(a)
}
    
fn main() {
    println!("{:?}", foo::<u32>(87u32));
    println!("{:?}", foo::<u64>(0x0123456789abcdfu64));
}
gagiuntoli
  • 475
  • 5
  • 13