如何将具有 Read 特征的 string-like 传递给 From 的实现?

How can I pass something string-like with the `Read` trait to an implementation of `From`?

我正在编写分词器,为了方便起见,我写了一个 Reader object,returns 一次一个词。当 words 耗尽时,它从 BufReader 中读取以填充 words。因此,我认为 filewords 都应该存在于结构中。

我遇到的问题是我想通过传递要标记化的字符串来测试它,而不是必须依赖文件。这就是为什么我尝试在 File&strString 上实现 From。后两个不起作用(如下突出显示)。

我试图用一生来注释 Reader,然后我在 From<&'a str> 的实现中使用了它,但那没有用。我最终得到了 Reader<'a, T: Read>,但编译器抱怨说没有使用生命周期参数。

From<&'static str> 的替代实现工作正常,但这意味着传入的任何字符串都必须在静态生命周期内存在。

我也看到了这个,但是好像不一样,因为他们的Enum有生命周期参数。

我有两个补充问题以及标题中的整体问题:

  1. 我也看到了 FromStr,但还没有尝试使用它 - 它适合这个吗?
  2. 下面我的代码注释变量 ownership/lifetimes 是否正确?

我的最小示例在这里(省略了导入):

#[derive(Debug)]
struct Reader<T: Read> {
    file: BufReader<T>,
    words: Vec<String>,
}

impl From<File> for Reader<File> {
    fn from(value: File) -> Self {                     // value moves into from
        Reader::new(BufReader::new(value))             // value moves into BufReader(?)
    }
}

// THE NEXT TWO DON'T WORK
impl From<&str> for Reader<&[u8]> {
    fn from(value: &str) -> Self {                     // Compiler can't know how long the underlying data lives
        Reader::new(BufReader::new(value.as_bytes()))  // The data may not live as long as BufReader
    }
}

impl From<String> for Reader<&[u8]> {
    fn from(value: String) -> Self {                   // value moves into from
        Reader::new(BufReader::new(value.as_bytes()))  // value doesn't move into BufReader or Reader
    }                                                  // value gets dropped
}


impl<T: Read> Reader<T> {
    fn new(input: BufReader<T>) -> Self {
        Self {
            file: input,
            words: vec![],
        }
    }
}

&str 编译时带有生命周期注解 (playground):

impl<'a> From<&'a str> for Reader<&'a [u8]> {
    fn from(value: &'a str) -> Self {
        Reader::new(BufReader::new(value.as_bytes()))
    }
}

如评论中所述,您只需要注释引用,而不是尝试将生命周期注释合并到 Reader 本身。

请注意,相同的方法对 String 不起作用,因为 from 的签名将其移入函数中,并且该函数不能 return 属于本地的字节多变的。您可以为 &String 实施它,但您也可以使用 &str.