gpt4 book ai didi

rust - 结构的通用反序列化(类型双关)(与借用检查器作斗争)

转载 作者:行者123 更新时间:2023-11-29 08:25:44 27 4
gpt4 key购买 nike

我正在使用打包结构,我需要能够从原始结构字节到结构,反之亦然,没有任何解码/编码开销。

我写了一些似乎有效的代码:

#[packed]
struct Test {
data: u64
}
impl Test {
fn from_byte_slice(bs: &[u8]) -> Option<Test> {
if bs.len() != std::mem::size_of::<Test>() {
None
} else {
let p: *const u8 = &bs[0];
let p2: *const Test = p as *const Test;
unsafe {
Some(*p2)
}
}
}
}

但是我有几个不同的结构需要序列化/反序列化所以我想使用通用函数来减少代码重复。

以下代码无法编译并显示错误消息:“错误:无法移出 *-pointer 的解除引用”

fn from_byte_slice<T>(bs: &[u8]) -> Option<T> {
if bs.len() != std::mem::size_of::<T>() {
None
} else {
let p: *const u8 = &bs[0];
let p2: *const T = p as *const T;
unsafe {
Some(*p2)
}
}
}

奇怪的是,如果我不返回一个 Option 而返回一个 Option<&T> 然后代码编译:

fn from_byte_slice<'a, T>(bs: &'a [u8]) -> Option<&'a T> {
if bs.len() != std::mem::size_of::<T>() {
None
} else {
let p: *const u8 = &bs[0];
let p2: *const T = p as *const T;
unsafe {
Some(&*p2)
}
}
}

我是做错了什么还是在借用检查器中遇到了错误?

最佳答案

参数bs: &[u8]是一个切片,并且是借来的。这是一种临时所有权形式,您无法将数据移出。 *p2这样做,它将数据的所有权移出。

你需要克隆它:

fn from_byte_slice<T: Clone>(bs: &[u8]) -> Option<T> {
if bs.len() != std::mem::size_of::<T>() {
None
} else {
let p: *const u8 = &bs[0];
let p2: *const T = p as *const T;
unsafe {
Some((*p2).clone())
}
}
}

使用 transmute你可能可以用 Vec<u8> 来完成这项工作相反,如果您不介意将拥有的向量移动到函数中。

第一种情况下的直接实现是有效的,因为 Test包含所有 Copy字段,因此被隐式复制(而不是需要显式 clone() )。

probably will change soon , Copy将来必须明确派生。

关于rust - 结构的通用反序列化(类型双关)(与借用检查器作斗争),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26615458/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com