kni*_*t42 5 io serialization rust
我已阅读如何从Rust中的文件读取结构?,但std::slice::raw::mut_buf_as_slice已被弃用,因此我想重新提出这个问题.
我想读一个struct utmp来自/var/run/utmp,我尝试了以下代码:
fn read_utmp() -> Utmp {
let mut reader = BufReader::new(File::open("/var/run/utmp").unwrap());
let mut ut = vec![];
let size = mem::size_of::<Utmp>();
reader.take(size as u64).read_to_end(&mut ut);
unsafe {
std::mem::transmute(ut)
}
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,编译器投诉:
错误:使用不同大小的类型调用transmute:std :: vec :: Vec(192位)到Utmp(3056位)[E0512]
我怎么能这样做?
我相信那raw::mut_buf_as_slice被替换为slice::from_raw_parts_mut.
请注意,以下代码未考虑任何字节序或填充问题,并且旨在与POD 类型一起使用。struct utmp在这种情况下应该是安全的。
这是一个可以从文件中读取结构体(pod 类型)的函数:
use std::io::{self, BufReader, Read};
use std::fs::{self, File};
use std::path::Path;
use std::slice;
fn read_struct<T, R: Read>(mut read: R) -> io::Result<T> {
let num_bytes = ::std::mem::size_of::<T>();
unsafe {
let mut s = ::std::mem::uninitialized();
let mut buffer = slice::from_raw_parts_mut(&mut s as *mut T as *mut u8, num_bytes);
match read.read_exact(buffer) {
Ok(()) => Ok(s),
Err(e) => {
::std::mem::forget(s);
Err(e)
}
}
}
}
// use
// read_struct::<Utmp>(reader)
Run Code Online (Sandbox Code Playgroud)
如果要从 utmp 文件中读取所有 utmp 结构,可以执行read_struct多次或一次读取所有文件:
fn read_structs<T, P: AsRef<Path>>(path: P) -> io::Result<Vec<T>> {
let path = path.as_ref();
let struct_size = ::std::mem::size_of::<T>();
let num_bytes = try!(fs::metadata(path)).len() as usize;
let num_structs = num_bytes / struct_size;
let mut reader = BufReader::new(try!(File::open(path)));
let mut r = Vec::<T>::with_capacity(num_structs);
unsafe {
let mut buffer = slice::from_raw_parts_mut(r.as_mut_ptr() as *mut u8, num_bytes);
try!(reader.read_exact(buffer));
r.set_len(num_structs);
}
Ok(r)
}
// use
// read_structs::<Utmp, _>("/var/run/utmp"))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2568 次 |
| 最近记录: |