0

我正在尝试为结构创建一个通用的序列化方案。在类似线程上给出答案之后,我有以下设置:

#[repr(packed)]
struct MyStruct {
    bytes: [u8; 4]
}

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() {
    let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_owned() };
    
    let bytes: &[u8] = unsafe { any_as_u8_slice(&s) };
    
    println!("{:?}", bytes);
}

操场

输出:

[0, 1, 2, 3]

这很好用,但是它没有考虑动态调整大小的结构成员,Vec<u8>并且它们的大小需要在运行时确定。理想情况下,我想将每个元素编码Vec<u8>为字节,并添加一个前缀来指示要读取的字节数。

目前我有这个:

#[repr(packed)]
struct MyStruct {
    bytes: Vec<u8>
}

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() {
    let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_vec() };
    
    let bytes: &[u8] = unsafe { any_as_u8_slice(&s) };
    
    println!("{:?}", bytes);
}

操场

输出:

[208, 25, 156, 239, 136, 85, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]

我假设上面的输出引用了某种指针,但我不确定。

目前,bincode板条箱与板条箱一起执行此操作serde,但它将向量的长度序列化为usize. 我宁愿指定这一点并将长度编码为u8,如该线程中所述。不幸的是,这里最好的解决方案是重写Bincode库,这让我寻找任何替代解决方案。

编辑

使用serdeand实现bincode

use serde::{Serialize};

#[derive(Clone, Debug, Serialize)]
struct MyStruct {
    bytes: Vec<u8>
}

fn main() {
    let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_vec() };
    
    let bytes = bincode::serialize(&s).unwrap();
    
    println!("{:?}", bytes);
}

输出:

[4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]

想要的输出:

[4, 0, 1, 2, 3]
4

2 回答 2

3

您看到的输出Vec完全符合预期。AVec具有三个元素,指针、长度和容量。这是由标准库保证的。在你的情况下,你有指针,长度和容量都是小端的数字 4。

将包含 a 的结构Vec转换&[u8]为您想要的方式是不可能的。&[u8]切片是一块连续的内存,但是,a从Vec根本上说是间接的,这意味着它的元素不与结构的其余部分连续存储。
至少,您需要将字节收集到一个Vec<u8>或类似的位置,因为您需要从多个位置复制数据。

于 2021-09-03T16:53:32.413 回答
2

如果您唯一的问题bincodeusize长度前缀,您可以使用该选项将其配置为使用可变长度前缀。with_varint_encoding

use bincode::{DefaultOptions, Options};
use serde::Serialize;

#[derive(Clone, Debug, Serialize)]
struct MyStruct {
    bytes: Vec<u8>,
}

fn main() {
    let s = MyStruct {
        bytes: [0u8, 1u8, 2u8, 3u8].to_vec(),
    };

    let bytes = DefaultOptions::new()
        .with_varint_encoding()
        .serialize(&s);

    println!("{:?}", bytes);
}

输出:

[4, 0, 1, 2, 3]
于 2021-09-03T17:46:36.573 回答