不使用动态分发处理BufReader<File>与BufReader<Stdin>时lines方法报错求助
解决BufInput枚举的lines方法类型不匹配问题
你的问题根源在于手动实现lines方法时,试图返回内部BufReader的Lines迭代器,而这些迭代器的类型(Lines<BufReader<File>>、Lines<BufReader<Stdin>>)与BufRead trait要求的Lines<BufInput>不匹配。以下是两种可行的解决方案:
方案一:依赖BufRead的默认lines实现
BufRead trait的lines方法有默认实现,它会基于你的BufInput类型创建Lines<BufInput>迭代器,而这个迭代器会自动复用你已经实现的fill_buf和consume方法。你只需要删除自己手动写的lines方法即可。
完整代码示例:
use std::fs::File; use std::io::{self, BufRead, BufReader, Read}; use std::path::Path; enum BufInput { File(BufReader<File>), Stdin(BufReader<io::Stdin>), } impl Read for BufInput { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { match self { BufInput::File(f) => f.read(buf), BufInput::Stdin(s) => s.read(buf), } } } impl BufRead for BufInput { fn fill_buf(&mut self) -> io::Result<&[u8]> { match self { BufInput::File(f) => f.fill_buf(), BufInput::Stdin(s) => s.fill_buf(), } } fn consume(&mut self, amt: usize) { match self { BufInput::File(f) => f.consume(amt), BufInput::Stdin(s) => s.consume(amt), } } // 无需手动实现lines,使用默认实现即可 } // 使用示例 fn main() -> io::Result<()> { let input = BufInput::Stdin(BufReader::new(io::stdin())); for line in input.lines() { println!("{}", line?); } Ok(()) }
方案二:自定义迭代器包装不同的Lines类型
如果你需要完全自定义行读取逻辑,可以创建一个枚举来包装两种Lines迭代器,并为其实现Iterator trait:
use std::fs::File; use std::io::{self, BufRead, BufReader, Lines, Read}; use std::path::Path; enum BufInput { File(BufReader<File>), Stdin(BufReader<io::Stdin>), } // 自定义迭代器枚举 enum BufInputLines { File(Lines<BufReader<File>>), Stdin(Lines<BufReader<io::Stdin>>), } impl Iterator for BufInputLines { type Item = io::Result<String>; fn next(&mut self) -> Option<Self::Item> { match self { BufInputLines::File(lines) => lines.next(), BufInputLines::Stdin(lines) => lines.next(), } } } impl Read for BufInput { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { match self { BufInput::File(f) => f.read(buf), BufInput::Stdin(s) => s.read(buf), } } } impl BufRead for BufInput { fn fill_buf(&mut self) -> io::Result<&[u8]> { match self { BufInput::File(f) => f.fill_buf(), BufInput::Stdin(s) => s.fill_buf(), } } fn consume(&mut self, amt: usize) { match self { BufInput::File(f) => f.consume(amt), BufInput::Stdin(s) => s.consume(amt), } } // 重写lines方法返回自定义迭代器 fn lines(self) -> BufInputLines { match self { BufInput::File(f) => BufInputLines::File(f.lines()), BufInput::Stdin(s) => BufInputLines::Stdin(s.lines()), } } }
这种方式能完全控制迭代逻辑,但需要额外维护自定义迭代器的实现。
内容的提问来源于stack exchange,提问作者foehn
相关产品推荐
相关产品推荐

