I want to cast [f64; 3] to [u8; 24] for data I send using udp socket.
Is there a best way to do it? Not to cast every float to bytes.
For example, Ruby provides pack/unpack functions. It helps to combine strings and numerics in one data package.
I want to cast [f64; 3] to [u8; 24] for data I send using udp socket.
Is there a best way to do it? Not to cast every float to bytes.
For example, Ruby provides pack/unpack functions. It helps to combine strings and numerics in one data package.
I think the general consensus for serialization is to use the Rust project serde. Read up on it and see if it will fit your needs.
I'll go hide right after I suggest ... std::mem::transmute
?
I would say use byteorder - this will let you read/write f32 and f64 to a Read/Write socket, and will work safely communicating between little endian systems and big endian ones.
std::mem::transmute is usable for this too, but it will only work correctly for systems with the same byte order. serde can be nice too if you want more structured messages, maybe with bincode, but it is definitely a 'higher level' solution.
Repeating what others have already said here,
mem::transmute
. It's unsafe, not very nice and it won't work if you're sending the data to a host with different endianness -- that is for floats; more complex objects can even have different layout depending on whether you compile a debug
or a release
build.byteorder
crate. It's higher-level and safe. Still, it's an ad-hoc solution.For the format, you can use, for example, bincode
. Here's the code that converts an [f64; 3]
to bincode using Serde and sends it to a UDP socket:
#[macro_use]
extern crate bincode;
let data: [f64; 3] = [1.2, 3.4, 5.6];
let serialized = bincode::serialize(&data, bincode::SizeLimit::Infinite)
.expect("couldn't serialize data");
let socket = std::net::UdpSocket::bind("127.0.0.1:3542")
.expect("couldn't bind to address");
socket.send_to(&serialized, "127.0.0.1:2267")
.expect("couldn't send data");
Notice how bincode::serialize
call is in fact simpler and more convenient than unsafe { std::mem::transmute::<&[u8; 24]>(&data) }
(or the version without &
s).
Wow! Glad to see community in the action.
Thank you all, I will take a look.
I'd be remiss if I didn't plug: https://github.com/m4b/scroll whichs supports endian-aware reading of the numeric types, and can read arbitrary types out of the data as long as they implement trait TryFromCtx
, as well as several other features that I think are cool.
I choose bincode. Satisfied all my needs, easy to pick up, easy to use.