2017-02-15 50 views
2

Vec s support std::io::Write, поэтому можно написать код, который принимает, например, File или Vec. Из ссылки API не похоже ни на Vec, ни на поддержку фрагментов std::io::Read.Как читать (std :: io :: Read) из Vec или Slice?

Есть ли удобный способ достичь этого? Нужно ли писать структуру обертки?

Вот пример рабочего кода, который читает и записывает файл с одной строкой, прокомментированной, которая должна читать вектор.

use ::std::io; 

// Generic IO 
fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error> 
    where W: io::Write, 
{ 
    let len = file.write(b"1234")?; 
    Ok(len) 
} 

fn read_4_bytes<R>(mut file: R) -> Result<[u8; 4], io::Error> 
    where R: io::Read, 
{ 
    let mut buf: [u8; 4] = [0; 4]; 
    file.read(&mut buf)?; 
    Ok(buf) 
} 

// Type specific 

fn write_read_vec() { 
    let mut vec_as_file: Vec<u8> = Vec::new(); 

    { // Write 
     println!("Writing Vec... {}", write_4_bytes(&mut vec_as_file).unwrap()); 
    } 

    { // Read 
//  println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap()); 
     //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     //        Comment this line above to avoid an error! 
    } 
} 

fn write_read_file() { 
    let filepath = "temp.txt"; 
    { // Write 
     let mut file_as_file = ::std::fs::File::create(filepath).expect("open failed"); 
     println!("Writing File... {}", write_4_bytes(&mut file_as_file).unwrap()); 
    } 

    { // Read 
     let mut file_as_file = ::std::fs::File::open(filepath).expect("open failed"); 
     println!("Reading File... {:?}", read_4_bytes(&mut file_as_file).unwrap()); 
    } 
} 

fn main() { 
    write_read_vec(); 
    write_read_file(); 
} 

Это терпит неудачу с ошибкой:

error[E0277]: the trait bound `std::vec::Vec<u8>: std::io::Read` is not satisfied 
    --> src/main.rs:29:42 
    | 
29 |   println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap()); 
    |           ^^^^^^^^^^^^ the trait `std::io::Read` is not implemented for `std::vec::Vec<u8>` 
    | 
    = note: required by `read_4_bytes` 

Я хотел бы писать тесты для формата файла кодера/декодера, без записи в файловой системе.

+0

Я удалил свой ответ. Этот вопрос теперь значительно больше_ и предоставляет больше контекста, чем при первоначальном запросе. –

+0

@ simon-whitehead, извинившись за то, что не дал исчерпывающего вопроса изначально, я думал, что может быть какая-то совершенно очевидная вещь, которую я отсутствовал, что не требовало примера рабочего кода. – ideasman42

ответ

5

В то время как векторы не поддерживают std::io::Read, ломтики делают.

Существует некоторая путаница, вызванная тем, что Rust может принудить Vec к кусочку в некоторых ситуациях, но не к другим.

В этом случае явное принуждение к ломтику необходимо, поскольку на этапе применяется приведения типов, компилятор не знает, что Vec<u8>не реализовать Read.


Код в этом вопросе будет работать, когда вектор принуждается ломти, либо как: read_4_bytes(&*vec_as_file) или read_4_bytes(&vec_as_file[..]).


Примечание:

  • Задавая вопрос на начальном этапе, я принимал &Read вместо Read. Это сделало передачу ссылки на потерю фрагмента, если я не прошел в &&*vec_as_file, который я не думал делать.
  • Благодаря @arete на #rust для поиска решения!