我有一些解析文件的代码,非常类似于以下内容:
use std::io::Cursor;
use std::io::Result;
use std::io::Read;
fn main() {
let v1 = [1, 2, 3, 4, 5];
let mut c1 = Cursor::new(v1); // *
println!("{:?}", read_one(&mut c1)); // 1
println!("{:?}", read_three(&mut c1)); // 2, 3, 4
println!("{:?}", read_one(&mut c1)); // 5
println!("{:?}", read_one(&mut c1)); // eof
}
fn read_one<R: Read>(r: &mut R) -> Result<u8> {
let mut buf = [0; 1];
r.read_exact(&mut buf)?;
Ok(buf[0])
}
fn read_three<R: Read>(r: &mut R) -> Result<[u8; 3]> {
let mut buf = [0; 3];
r.read_exact(&mut buf)?;
Ok(buf)
}
此处,read_one
和read_three
采用Read
特征,从中获取一些字节,然后返回结果。然后我可以一块一块地读取字节。
我希望将此代码转换为使用迭代器。也就是说,让*
行为
let mut i1 = v1.iter();
尝试这一点,我遇到了一些问题,我无法找到能够轻松提取多个项目(类似于read_exact
)或以其他方式部分处理迭代器的函数。似乎大多数迭代器函数都是为了完全使用内容而设计的。
迭代器只是一个坏工具还是我使用它错了?如果是后者,我该如何将此代码转换为使用迭代器?
答案 0 :(得分:3)
你可以为自己做出自己的特质
use std::io::{Error, ErrorKind, Result};
trait ReadExact {
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>;
}
impl<T> ReadExact for T
where
T: Iterator<Item = u8>,
{
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
for p in buf {
if let Some(b) = self.next() {
*p = b;
} else {
return Err(Error::new(ErrorKind::UnexpectedEof, "Iterator exhausted"));
}
}
Ok(())
}
}
答案 1 :(得分:2)
以下是您可以collect into an array
的解释如果您仍想使用迭代器,可以将返回类型更改为Vec
并打电话
r.take(n).collect();
答案 2 :(得分:1)
你可以用迭代器写几乎相同的东西。您遇到的问题是阵列难以使用,因为他们不会(截至2017年12月)实施FromIterator
。作为user1541501 suggested,最简单的解决方案是将collect()
转换为Vec
而不是:
fn main() {
let v1 = vec![1, 2, 3, 4, 5];
let mut c1 = v1.into_iter();
println!("{:?}", read_one(&mut c1)); // 1
println!("{:?}", read_three(&mut c1)); // 2, 3, 4
println!("{:?}", read_one(&mut c1)); // 5
println!("{:?}", read_one(&mut c1)); // eof
}
fn read_one<I: Iterator<Item = u8>>(i: &mut I) -> Option<u8> {
i.next()
}
fn read_three<I: Iterator<Item = u8>>(i: &mut I) -> Result<Vec<u8>, Vec<u8>> {
let buf: Vec<u8> = i.take(3).collect();
if buf.len() == 3 {
Ok(buf)
} else {
Err(buf)
}
}
阵列也未实现IntoIterator
,因此我将v1
变为Vec<u8>
以致电v1.into_iter()
。您可以改为编写v1.iter().cloned()
。
我做的另一项重大更改是让read_one
返回Option
而不是io::Result
,并使read_three
返回Result<Vec<u8>, Vec<u8>>
。这是因为迭代器只能通过耗尽数据而失败。 (如果read_three
失败,则Err
变体包含收集的元素。)