2017-08-05 82 views
1

在標準庫中是否存在支持向數據流中「推送」字節的流類型Read,以便隨後的讀取將在數據流中的其他字節之前首先返回所述字節?如何將字節推回到Rust中的Read實現類型?

n = stream.read(&mut buf).unwrap(); 
if ... { 
    stream.???PUT_BACK???(&buf[..n]) 
} 
+0

是'stream'限於'Read'特性還是可以選擇更具體的類型? – the8472

+0

只要基本的字節源可以是實現「Read」的任何對象,任何類型都是可以接受的。 – Doe

回答

2

反過來思考問題:如何在某些情況下只讀取一些字節。然後你可以使用BufRead特點:

use std::fs::File; 
use std::io::{BufRead, BufReader}; 

fn main() { 
    let f = File::open("/etc/hosts").expect("unable to open"); 
    let mut f = BufReader::new(f); 

    { 
     let bytes = f.fill_buf().expect("cannot read"); 
     println!("{:?}", bytes[0]); 
    } 

    if some_condition() { 
     f.consume(2); 
    } 

    { 
     let bytes = f.fill_buf().expect("cannot read"); 
     println!("{:?}", bytes[0]); 
    } 
} 

在您需要添加數據不是原始源部分,然後用chain,作爲Florian Weimer shows罕見的情況下,很可能會更合適。在罕見的情況下,你可以寫你需要的東西:

use std::fs::File; 
use std::io::{self, Read}; 
use std::cmp::min; 

/// Warning: lightly tested; never shrinks 
struct PushableRead<R> { 
    extra: Vec<u8>, 
    offset: usize, 
    inner: R, 
} 

impl<R> PushableRead<R> 
where 
    R: Read, 
{ 
    fn new(inner: R) -> Self { 
     Self { 
      extra: Vec::new(), 
      offset: 0, 
      inner, 
     } 
    } 

    fn push(&mut self, bytes: &[u8]) { 
     self.extra.extend(bytes) 
    } 
} 

impl<R> Read for PushableRead<R> 
where 
    R: Read, 
{ 
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 
     let extra_bytes = self.extra.len() - self.offset; 

     if extra_bytes > 0 { 
      let to_copy = min(extra_bytes, buf.len()); 

      let dst = &mut buf[0..to_copy]; 
      let src = &self.extra[self.offset..self.offset + to_copy]; 

      dst.copy_from_slice(src); 
      self.offset += to_copy; 
      Ok(to_copy) 
     } else { 
      self.inner.read(buf) 
     } 
    } 
} 

fn main() { 
    let f = File::open("/etc/hosts").expect("unable to open"); 
    let mut f = PushableRead::new(f); 

    f.push(b"This is extra junk"); 

    let mut data = Vec::new(); 
    f.read_to_end(&mut data).expect("Unable to read"); 

    println!("{:?}", std::str::from_utf8(&data)); 
} 
4

看一看在chain method of std::io::read及其例子(這裏略作修改):

fn main() { 
    use std::io::prelude::*; 
    use std::fs::File; 

    let f1 = File::open("foo.txt").unwrap(); 
    let f2 = File::open("bar.txt").unwrap(); 

    let mut handle = f1.chain(f2); 

    let mut buffer = String::new(); 
    handle.read_to_string(&mut buffer).unwrap(); 
    println!("{:?}", buffer); 
} 

沒有辦法與原來的Read對象要做到這一點,因爲特質根本不提供此設施。如果您需要某種形式的lookahead,您需要查看BufRead traitBufReader struct,儘管它的超前支持非常有限。

相關問題