如何“结构”转换为“&[U8]”?如何“结构”转换为“&[U8]”?(How to convert

2019-05-12 04:39发布

我想通过一个送我的结构TcpStream 。 我可以把Stringu8 ,但我不能发送任意的结构。 例如:

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,因为我想给快和尽可能小的数据,所以我想没有或者非常小的开销。

Answer 1:

(无耻地从被盗雷纳托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);
}

然后你就可以发送任何你想要的字节数。 我假设你已经与天真各地发送字节数(如潜在的排列顺序问题或版本)已知的问题,但我会提到他们,以防万一^ _ ^。



Answer 2:

正确大小结构作为零复制的字节可以用做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]这将是自修改可以很容易地创建不一致/损坏的数据相当危险的。



文章来源: How to convert 'struct' to '&[u8]'?
标签: rust