我想通过一个送我的结构TcpStream
。 我可以把String
或u8
,但我不能发送任意的结构。 例如:
struct MyStruct {
id: u8,
data: [u8; 1024],
}
let my_struct = MyStruct { id: 0, data: [1; 1024] };
let bytes: &[u8] = convert_struct(my_struct); // how??
tcp_stream.write(bytes);
接收到数据后,我想转换&[u8]
回MyStruct
。 我怎么可以在这两个之间转换?
我知道锈病用于串行数据的JSON模块,但我不希望使用JSON,因为我想给快和尽可能小的数据,所以我想没有或者非常小的开销。
(无耻地从被盗雷纳托Zannon的评论上类似的问题)
也许就像一个解决方案bincode
会适合你的情况? 这里有一个工作的摘录:
Cargo.toml
[package]
name = "foo"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
[dependencies]
serde_derive = "1.0.34"
bincode = "1.0.0"
serde = "1.0.34"
main.rs
extern crate bincode;
#[macro_use]
extern crate serde_derive;
extern crate serde;
use std::fs::File;
#[derive(Serialize, Deserialize)]
struct A {
id: i8,
key: i16,
name: String,
values: Vec<String>,
}
fn main() {
let a = A {
id: 42,
key: 1337,
name: "Hello world".to_string(),
values: vec!["alpha".to_string(), "beta".to_string()],
};
// Encode to something implementing Write
let mut f = File::create("/tmp/output.bin").unwrap();
bincode::serialize_into(&mut f, &a).unwrap();
// Or just to a buffer
let bytes = bincode::serialize(&a).unwrap();
println!("{:?}", bytes);
}
然后你就可以发送任何你想要的字节数。 我假设你已经与天真各地发送字节数(如潜在的排列顺序问题或版本)已知的问题,但我会提到他们,以防万一^ _ ^。
正确大小结构作为零复制的字节可以用做stdlib
和通用功能。
在下面有例子有一个叫做可重复使用的功能any_as_u8_slice
代替convert_struct
,因为这是一种实用工具包铸和切片创建。
请注意,这个问题询问有关转换 ,这个例子创建了一个只读片,所以具有不需要复制内存的优势。
继承人基于问题的工作示例:
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
fn main() {
struct MyStruct {
id: u8,
data: [u8; 1024],
}
let my_struct = MyStruct { id: 0, data: [1; 1024] };
let bytes: &[u8] = unsafe { any_as_u8_slice(&my_struct) };
// tcp_stream.write(bytes);
println!("{:?}", bytes);
}
注1)即使第三方包装箱可能会在某些情况下更好,这是这样一个基本的操作,其很有必要知道如何做锈。
注2)在写本新闻时(锈1.15),不存在用于支持const
功能。 一旦有,这将是可能的浇铸成固定大小的阵列,而不是一个切片。
注3)将any_as_u8_slice
函数标记为unsafe
,因为在任何填充字节struct
可以是未初始化的存储器(给未定义的行为)。 如果有一种方法来确保只使用这是结构输入参数#[repr(packed)]
,那么它可能是安全的。
否则函数是相当安全的,因为它可以防止缓冲器超限运行,因为输出是只读的,固定数目字节,并且它的寿命被绑定到输入。
如果你想要一个返回的版本&mut [u8]
这将是自修改可以很容易地创建不一致/损坏的数据相当危险的。