[Resolved] Struct.pack (python) equivalent in Rust


#1

If I wanted to emulate the struct pack functionality in python, what would be the equivalent of:

struct.pack("!iiii"1, 0,0, 40)

Could it be achieved in the byteorder crate?

Would it be something like:

    let mut bytes = Vec::with_capacity(16usize);
    bytes.write_u32::<BigEndian>(1).unwrap();
    bytes.write_u64::<BigEndian>(0).unwrap();
    bytes.write_u32::<BigEndian>(40).unwrap();

    bytes

Is there another way to do this?

Thank you.


#2

If you are looking for a way to serialize and deserialize structs then serde is what you seek.


#3

I’ve used byteorder in a similar situation. I don’t know if there’s a better way to do it.


#4

Thanks. I guess I’ll keep doing my way. I realize that this question is a bit lacking, so I will mark it as closed.


#5

As mentioned, the equivalent of the Python approach would be Serde. In this case together with bincode:

// [dependencies]
// bincode = "0.7"
// byteorder = "1.0"
// serde = "0.9"

extern crate bincode;
extern crate byteorder;
extern crate serde;

use bincode::Infinite;
use byteorder::BigEndian;
use serde::{Serialize, Deserialize};

// Or error_chain, or whatever strategy you are using for errors.
type Result<T> = ::std::result::Result<T, Box<::std::error::Error>>;

fn pack<T: Serialize>(data: &T) -> Result<Vec<u8>> {
    use bincode::endian_choice::serialize;
    let bytes = serialize::<_, _, BigEndian>(data, Infinite)?;
    Ok(bytes)
}

fn unpack<T: Deserialize>(bytes: &[u8]) -> Result<T> {
    use bincode::endian_choice::deserialize;
    let data = deserialize::<_, BigEndian>(bytes)?;
    Ok(data)
}

fn main() {
    let data = (1, 0, 0, 40);
    let vec = pack(&data).unwrap();
    println!("{:?}", vec);

    let out: (i32, i32, i32, i32);
    out = unpack(&vec).unwrap();
    println!("{:?}", out);
}

The pack and unpack functions can be re-used for any type, including structs and enums that use #[derive(Serialize, Deserialize)] (explained here).