我正在使用打包的结构,我需要能够从原始的 字节到结构,反之亦然,没有任何解码/编码开销。
我写了一些似乎有用的代码:
#[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)
}
}
}
}
但是我有几个不同的结构需要序列化/去序列化 所以我想使用通用函数来减少代码重复。
以下代码无法使用错误消息进行编译:“错误:无法移出*
的引用 - 指针”
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)
}
}
}
奇怪的是,如果我没有返回选项,则返回选项&lt;&amp; T&gt;然后代码编译:
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)
}
}
}
我做错了什么或者我在借阅检查器中遇到了错误?
答案 0 :(得分:3)
参数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>
来完成这项工作。
第一种情况中的直接impl有效,因为Test
包含所有Copy
字段,因此被隐式复制(而不是需要显式的clone()
)。
此probably will change soon,Copy
将来必须明确派生。