Bence bir dosyadan veya bir girdiden okuma olmanıza gizleyen bir "polimorfik" Input
enum uygulamaya çalışıyorum. Daha somut olarak, birya da BufReader
ya da StdInLock
(her ikisi de lines()
yöntemine sahip olan) biryöntemine sahip olacak "temsilci" olacak bir enum inşa çalışıyorum. Ben üç yöntem varRust'ta polimorfik IO (Dosya veya stdin) nasıl yapılır?
enum Input<'a> {
Console(std::io::StdinLock<'a>),
File(std::io::BufReader<std::fs::File>)
}
: Burada
enum var biz bir argüman (dosya adı) olup olmadığını kontrol ederek bir dosyadan veya bir stdin'den okuyorsanız karar vermektenfrom_arg
oldu Locki için, birBufReader
içeren bir dosyayı sarılması için,console
file
sağlanan Stdin.
uygulaması:
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))
})
}
}
Bildiğim kadarıyla anladığım kadarıyla, çalışmak için bot bunun için
BufRead
ve
Read
özellikleri uygulamak zorunda.
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()
}
}
}
Son olarak, çağırma:
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 */
}
}
sorun olduğunu ben desen yanlış eşleştirme ve ben mismatched types
olduğunu olduğumu Banasöylemediğin derleyici Bu benim girişimidir. Bunu tatmin etmek için:
match self {
Input::Console(std::io::StdinLock(ref c)) => c.lines(),
Input::File(std::io::BufReader(ref f)) => f.lines()
}
... ama bu da çalışmıyor. ,
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(),
Burada gerçekten benim derinlik yokum: Bir unresolved variant
hata
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(),
^~~~~~~~~
ve ikinci durumda:
İlk durumda ben mismatched types
hatası alıyorum görünüyor.
'StdinLock' bir Stdin nesnesi için bir başvuru içerdiğinden mevcut yaklaşımınız çalışmayacaktır. –
Zamanınız varsa biraz daha genişleyebilir misiniz? Teşekkürler. – neektza