2016-03-18 8 views
6

私はファイルか標準入力から読み込んでいるかどうかを隠す "多形"のInput enumを実装しようとしています。具体的には、linesメソッドを持つエニュメントを作成しようとしています。このメソッドは、BufReaderまたはStdInLock(いずれもlines()メソッドを使用しています)にラップされたFileのいずれかに呼び出しを委譲します。ここでRustでポリモーフィックIO(ファイルまたは標準入力)を行う方法は?

は、列挙型です:

enum Input<'a> { 
    Console(std::io::StdinLock<'a>), 
    File(std::io::BufReader<std::fs::File>) 
} 

私は三つの方法があります:

  • from_argを我々は、引数(ファイル名)があったかどうかチェックすることにより、ファイルまたは標準入力から読んでいるかどうかを判断するために提供、
  • fileBufReaderのファイルをラップするには、
  • console for locki標準にしてください。

実装:

impl <'a> Input<'a> { 

    fn console() -> Input<'a> { 
     Input::Console(io::stdin().lock()) 
    } 

    fn file(path: String) -> io::Result<Input<'a>> { 
     match File::open(path) { 
      Ok(file) => Ok(Input::File(std::io::BufReader::new(file))), 
      Err(_) => { panic!("kita") } 
     } 
    } 

    fn from_arg(arg: Option<String>) -> io::Result<Input<'a>> { 
     Ok(match arg { 
      None  => Input::console(), 
      Some(path) => try!(Input::file(path)) 
     }) 
    } 
} 

は、私の知る限り理解し、私はこれが機能するためのボットBufReadRead特徴を実装する必要があります。

impl <'a> io::Read for Input<'a> { 
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 
     match *self { 
      Input::Console(ref mut c) => c.read(buf), 
      Input::File(ref mut f)  => f.read(buf), 
     } 
    } 
} 

impl <'a> io::BufRead for Input<'a> { 
    fn lines(self) -> Lines<Self> { 
     match self { 
      Input::Console(ref c) => c.lines(), 
      Input::File(ref f)  => f.lines() 
     } 
    } 

    fn consume(&mut self, amt: usize) { 
     match *self { 
      Input::Console(ref mut c) => c.consume(amt), 
      Input::File(ref mut f) => f.consume(amt) 
     } 
    } 

    fn fill_buf(&mut self) -> io::Result<&[u8]> { 
     match *self { 
      Input::Console(ref mut c) => c.fill_buf(), 
      Input::File(ref mut f) => f.fill_buf() 
     } 
    } 
} 

最後に、呼び出し:

fn load_input<'a>() -> io::Result<Input<'a>> { 
    Ok(try!(Input::from_arg(env::args().skip(1).next()))) 
} 

fn main() { 
    let mut input = match load_input() { 
     Ok(input) => input, 
     Err(error) => panic!("Failed: {}", error), 
    }; 


    for line in input.lines() { 
     /* do stuff */ 
    } 
} 

の問題は、私はパターンが誤って一致すると私はmismatched typesを持っていることだと私は私に言って、コンパイラこれは私の試みです。私はそれを満足させようとしました:

match self { 
    Input::Console(std::io::StdinLock(ref c)) => c.lines(), 
    Input::File(std::io::BufReader(ref f)) => f.lines() 
} 

...でも、それはうまくいきません。

poly_input.rs:43:40: 43:49 error: mismatched types: 
expected `std::io::Lines<Input<'a>>`, 
    found `std::io::Lines<std::io::stdio::StdinLock<'_>>` 
(expected enum `Input`, 
    found struct `std::io::stdio::StdinLock`) [E0308] 
poly_input.rs:43    Input::Console(ref c) => c.lines(), 
                 ^~~~~~~~~ 

、第2の場合でunresolved variantエラー:私はmismatched typesエラーを取得しています最初のケースで

私はここに私の深さのうち、本当によ

poly_input.rs:45:29: 45:47 error: unresolved enum variant, struct or const `StdinLock` [E0419] 
poly_input.rs:45    Input::Console(std::io::StdinLock(ref c))   => c.lines(), 

、そうみたいです。

+0

'StdinLock'に' Stdin'オブジェクトへの参照が含まれているため、あなたの現在のアプローチは機能しません。 –

+0

時間があれば少し拡大できますか?ありがとう。 – neektza

答えて

9

これは最も簡単な解決策ですが、Stdinを借りてロックします。デフォルトの形質メソッドへ

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

struct Input<'a> { 
    source: Box<BufRead + 'a> 
} 

impl<'a> Input<'a> { 
    fn console(stdin: &'a io::Stdin) -> Input<'a> { 
     Input { source: Box::new(stdin.lock()) } 
    } 

    fn file(path: &str) -> io::Result<Input<'a>> { 
     File::open(path) 
      .map(|file| Input { source: Box::new(io::BufReader::new(file)) }) 
    } 
} 

impl<'a> Read for Input<'a> { 
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 
     self.source.read(buf) 
    } 
} 

impl<'a> BufRead for Input<'a> { 
    fn fill_buf(&mut self) -> io::Result<&[u8]> { 
     self.source.fill_buf() 
    } 
    fn consume(&mut self, amt: usize) { 
     self.source.consume(amt); 
    } 
} 

ReadBufReadは完全にInputのために実装されています。したがって、linesInputに電話することができます。

let input = Input::file("foo.txt").unwrap(); 
for line in input.lines() { 
    println!("input line: {:?}", line); 
} 
+0

ありがとうございました。 – neektza

関連する問題