我正在编写一个库,用于对二进制格式的数据进行编码/解码。部分格式是数字,我正在使用Rust的原始基本类型(如i8
,i64
,f32
等。)
是否有一种简单的内置方法可以将这些数据类型转换为二进制数据,或者转换为f64
/ f32
/ i64
/等。变成Vec<u8>
?同样,有一种方法可以将4个u8
(在Vec<u8>
中说)转换为f32
吗?
答案 0 :(得分:19)
不幸的是,目前还没有安全的内置支持从Rust中读取/写入一个字节数组的原语。但是,有几个社区库,byteorder是最常用的库:
extern crate byteorder;
use byteorder::{LittleEndian, WriteBytesExt};
use std::mem;
fn main() {
let i: i64 = 12345;
let mut bs = [0u8; mem::size_of::<i64>()];
bs.as_mut()
.write_i64::<LittleEndian>(i)
.expect("Unable to write");
for i in &bs {
println!("{:X}", i);
}
}
当然,你总是可以投射原始指针。例如,您可以将*const i64
转换为*const i8
,然后将其转换为适当的字节切片&[u8]
。但是,由于endiannness,这很容易出错,unsafe
和平台相关,因此它应该仅作为最后的手段使用:
use std::{mem, slice};
fn main() {
let i: i64 = 12345;
let ip: *const i64 = &i;
let bp: *const u8 = ip as *const _;
let bs: &[u8] = unsafe { slice::from_raw_parts(bp, mem::size_of::<i64>()) };
for i in bs {
println!("{:X}", i);
}
}
答案 1 :(得分:13)
std::mem::transmute
,但它是unsafe
:
fn main() {
let var1 = 12345678_i64;
let raw_bytes: [i8; 8] = unsafe { std::mem::transmute(var1) };
for byte in &raw_bytes {
println!("{}", byte);
}
}
注意:请确保两个变量的大小完全相同。
答案 2 :(得分:6)
从Rust 1.32开始,您可以将{to,from}_{ne,le,be}_bytes
用于整数类型。
let begin = 1234_i32;
let bytes = begin.to_ne_bytes();
let and_back = i32::from_ne_bytes(bytes);
对于浮点,您仍然必须依靠先前的方法。
答案 3 :(得分:2)
Rust 1.32具有:{to,from}_{ne,le,be}_bytes
,to_bits
和from_bits
。
将整数转换为字节然后返回:
let x = 65535_i32;
let x_bytes = x.to_ne_bytes(); // x_bytes = [255, 255, 0, 0]
let original_x = i32::from_ne_bytes(x_bytes); // original_x = 65535 = x
将浮点数转换为字节然后返回:
let y = 255.255_f64;
let y_bytes = y.to_bits().to_ne_bytes();
let original_y = f64::from_bits(u64::from_ne_bytes(y_bytes)); // original_y = 255.255 = y
根据Rust文档from_bits
可以有portability issues。
答案 4 :(得分:-1)
如果您的目标是打印字节或以str
表示形式使用它们,只需在格式大括号中使用:b
表示法
fn main() {
println!("This is the binary of int {:b}", 4 as i32);
}
打印
This is the binary of int 100