Я пытаюсь прочитать двоичные 16-битные машинные инструкции из 16-битной архитектуры (точная природа здесь не имеет значения) и вывести их обратно в виде шестнадцатеричных значений.В C я нашел это простым, используя функцию fread
для считывания 16 битов в uint16_t
.
. Я решил, что попытаюсь повторить fread
в Rust.Кажется, это довольно тривиально, если я могу заранее знать точный размер переменной, в которую выполняется чтение, и у меня это работало специально для 16 битов.
Я решил, что хочу попробоватьсделать функцию fread
обобщенной для различных встроенных целочисленных типов без знака.Для этого я придумал следующую функцию, используя некоторые черты из ящика Num:
fn fread<T>(
buffer: &mut T,
element_count: usize,
stream: &mut BufReader<File>,
) -> Result<usize, std::io::Error>
where
T: num::PrimInt + num::Unsigned,
{
let type_size = std::mem::size_of::<T>();
let mut buf = Vec::with_capacity(element_count * type_size);
let buf_slice = buf.as_mut_slice();
let bytes_read = match stream.read_exact(buf_slice) {
Ok(()) => element_count * type_size,
Err(ref e) if e.kind() == std::io::ErrorKind::UnexpectedEof => 0,
Err(e) => panic!("{}", e),
};
*buffer = buf_slice
.iter()
.enumerate()
.map(|(i, &b)| {
let mut holder2: T = num::zero();
holder2 = holder2 | T::from(b).expect("Casting from u8 to T failed");
holder2 << ((type_size - i) * 8)
})
.fold(num::zero(), |acc, h| acc | h);
Ok(bytes_read)
}
Проблема в том, что когда я вызываю ее в основной функции, мне кажется, что я всегда получаю 0x00
обратно, но число прочитанных байтов, возвращаемых функцией, всегда равно 2, так что программа входит в бесконечный цикл:
extern crate num;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::Read;
fn main() -> Result<(), std::io::Error> {
let cmd_line_args = std::env::args().collect::<Vec<_>>();
let f = File::open(&cmd_line_args[1])?;
let mut reader = BufReader::new(f);
let mut instructions: Vec<u16> = Vec::new();
let mut next_instruction: u16 = 0;
fread(&mut next_instruction, 1, &mut reader)?;
let base_address = next_instruction;
while fread(&mut next_instruction, 1, &mut reader)? > 0 {
instructions.push(next_instruction);
}
println!("{:#04x}", base_address);
for i in instructions {
println!("0x{:04x}", i);
}
Ok(())
}
Мне кажется, что я почему-то ничего не читаю из файла, так что функция всегда просто возвращает количество байтов, которое она должна была прочитать.Я явно не правильно что-то здесь использую, но честно говоря не уверен, что делаю неправильно.
Это скомпилировано в Rust 1.26 stable для Windows, если это имеет значение.
Что я делаю не так, и что я должен делать по-другому для репликации fread
?Я понимаю, что это, вероятно, случай проблемы XY (в которой почти наверняка есть лучший способ Rust многократно читать некоторые байты из файла и упаковывать их в одно целое число без знака), но мне действительно любопытно, что яЯ делаю неправильно здесь.