私はファイルか標準入力から読み込んでいるかどうかを隠す "多形"の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
を我々は、引数(ファイル名)があったかどうかチェックすることにより、ファイルまたは標準入力から読んでいるかどうかを判断するために提供、file
BufReader
のファイルをラップするには、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))
})
}
}
は、私の知る限り理解し、私はこれが機能するためのボットBufRead
とRead
特徴を実装する必要があります。
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(),
、そうみたいです。
'StdinLock'に' Stdin'オブジェクトへの参照が含まれているため、あなたの現在のアプローチは機能しません。 –
時間があれば少し拡大できますか?ありがとう。 – neektza