如何组合std::str::行和std::io::行



我想写一个函数来解析文本,但文本可能来自外部文件或内部&strparse功能可能如下所示:

fn parse(lines: GenericLinesGenerator) {
   for line in lines {
       // parse content
   }
}

它可以这样调用:

use std::io::BufReader;
use std::fs::File;
let fin = BufReader::new(File::open("info.txt").expect("not found"));
parse(TransformFromIO(fin.lines()))

let content: &'static str = "somenlongntext";
parse(TransformFromStr(content.lines()))

有可能实现这样的parse功能吗?

两个迭代器不会产生相同的值:

impl<B: BufRead> Iterator for io::Lines<B> {
    type Item = Result<String>;
}
impl<'a> Iterator for str::Lines<'a> {
    type Item = &'a str;
}

你必须以某种方式处理这种差异。最重要的区别是io::Lines可以失败。你的程序必须决定如何处理这一问题;我选择了中止这个程序。

接下来需要做的是接受任何可以转换为迭代器的类型,并且迭代器产生的值必须转换为可以处理的类型。看来&str是公约数。

这是通过使用IntoIteratorBorrow:来解决的

use std::borrow::Borrow;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
fn parse<I>(lines: I)
where
    I: IntoIterator,
    I::Item: Borrow<str>,
{
    for line in lines {
        println!("line: {}", line.borrow());
    }
}
fn main() {
    parse("alphanbetangamma".lines());
    println!("----");
    let f = File::open("/etc/hosts").expect("Couldn't open");
    let b = BufReader::new(f);
    parse(b.lines().map(|l| l.expect("Bad line!")));
}

有关特征边界的更多信息,请查看where子句上的Rust编程语言部分。

parse函数中使用Borrow绑定将允许您借用&str,但如果您需要String值,更好的方法是使用Cow

使用line.borrow().to_string()获得String值将始终进行分配,即使使用文件中的行调用parse(在这种情况下,lines.map产生String)也是如此。

当使用&str中的行调用时,使用line.into_owned()将进行分配,但当使用文件中的行时不会进行分配(只会打开传递给Cow::OwnedString值)。

use std::borrow::Cow;
use std::io::{BufReader, BufRead};
use std::iter::IntoIterator;
use std::fs::File;
fn parse<'a, I>(lines: I)
    where I: IntoIterator,
          I::Item: Into<Cow<'a, str>>
{
    for line in lines {
        let line: Cow<'a, str> = line.into();
        let line: String = line.into_owned();
        // or
        let line = line.into().into_owned()
        println!("{}", line);
    }
}
fn main() {
    let fin = BufReader::new(File::open("/etc/hosts").expect("cannot open file"));
    parse(fin.lines().map(|r| r.expect("file read failed")));
    let content: &'static str = "somenlongntext";
    parse(content.lines());
}

相关内容

最新更新