我的结构有一些固定大小的数组:
struct PublicHeaderBlock_LAS14 {
file_signature: [u8; 4],
file_source_id: u16,
global_encoding: u16,
project_id_data_1: u32,
project_id_data_2: u16,
project_id_data_3: u16,
project_id_data_4: [u8; 8],
version_major: u8,
version_minor: u8,
systemIdentifier: [u8; 32], // ...
}
我正在从文件中读取字节到固定大小的数组,并将这些字节逐位复制到struct中。
fn create_header_struct_las14(&self, buff: &[u8; 373]) -> PublicHeaderBlock_LAS14 {
PublicHeaderBlock_LAS14 {
file_signature: [buff[0], buff[1], buff[2], buff[3]],
file_source_id: (buff[4] | buff[5] << 7) as u16,
global_encoding: (buff[6] | buff[7] << 7) as u16,
project_id_data_1: (buff[8] | buff[9] << 7 | buff[10] << 7 | buff[11] << 7) as u32,
project_id_data_2: (buff[12] | buff[13] << 7) as u16,
project_id_data_3: (buff[14] | buff[15] << 7) as u16,
project_id_data_4: [buff[16], buff[17], buff[18], buff[19], buff[20], buff[21], buff[22], buff[23]],
version_major: buff[24],
version_minor: buff[25],
systemIdentifier: buff[26..58]
}
}
最后一行(systemIdentifier
)不起作用,因为在结构中它是[u8; 32]
而buff[26..58]
是一个切片。我是否可以将切片返回到一个范围内的固定大小的数组,而不是按照我所说的file_signature
进行操作?
答案 0 :(得分:9)
没有safe
方法来初始化带有切片的结构中的数组。您需要使用直接在未初始化内存上运行的unsafe
块,或者使用以下两种初始化 - 然后 - 变异策略之一:
构造一个所需的数组,然后用它来初始化结构。
struct Foo {
arr: [u8; 32],
}
fn fill(s: &[u8; 373]) -> Foo {
let mut a: [u8; 32] = Default::default();
a.copy_from_slice(&s[26..58]);
Foo { arr: a }
}
或者初始化struct,然后在struct中改变数组。
#[derive(Default)]
struct Foo {
arr: [u8; 32],
}
fn fill(s: &[u8; 373]) -> Foo {
let mut f: Foo = Default::default();
f.arr.copy_from_slice(&s[26..58]);
f
}
如果你的结构有很多成员,那么第一个更干净。如果编译器无法优化中间副本,则第二个可能会快一点。但如果这是您程序的性能瓶颈,您可能会使用unsafe
方法。
答案 1 :(得分:4)
感谢@malbarbo我们可以使用这个辅助函数:
use std::convert::AsMut;
fn clone_into_array<A, T>(slice: &[T]) -> A
where A: Sized + Default + AsMut<[T]>,
T: Clone
{
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
a
}
获得更整洁的语法:
fn main() {
let original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let e = Example {
a: clone_into_array(&original[0..4]),
b: clone_into_array(&original[4..10]),
};
println!("{:?}", e);
}
只要T: Default + Clone
。
如果目标数组和传入的切片长度不同,它将panic!
,因为clone_from_slice
会这样做。