我正在用Rust编写代码来解析数据流,trait Stream。流可以由其他流组成。特征StreamIterator提供对子流的访问。这是在解析tar文件、zip文件和其他包含文件的文件时使用的。
在写这段代码的时候,我一直在与借入检查器做斗争,但没有成功。
下面的代码是一个简化的示例。在main中,文件以流的形式打开。该流被传递给analyze函数,该函数尝试将流作为TarStreamIterator打开,以迭代tar中的流。还分析了每个嵌入的流。
我想我可能会在StreamIterator特征中引入第二个生命周期。
use std::io;
trait Stream<T> {
fn read(&mut self) -> io::Result<&[T]>;
}
trait StreamIterator<'a,T,S: Stream<T>> {
fn next(&'a mut self) -> Option<io::Result<S>>;
}
struct FileStream {
}
impl<T> Stream<T> for FileStream {
fn read(&mut self) -> io::Result<&[T]> {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, ""))
}
}
struct TarStream<'a> {
stream: &'a mut Stream<u8>
}
impl<'a> Stream<u8> for TarStream<'a> {
fn read(&mut self) -> io::Result<&[u8]> {
self.stream.read()
}
}
struct TarStreamIterator<'a> {
stream: &'a mut Stream<u8>
}
impl<'a> StreamIterator<'a,u8,TarStream<'a>> for TarStreamIterator<'a> {
fn next(&'a mut self) -> Option<io::Result<TarStream>> {
// todo: read tar header
Some(Ok(TarStream{stream: self.stream}))
}
}
fn analyzeAsTar(s: &mut Stream<u8>) -> bool {
let mut tar = TarStreamIterator{stream: s};
while let Some(Ok(mut substream)) = tar.next() {
analyze(&mut substream);
}
true
}
fn analyze(s: &mut Stream<u8>) -> bool {
analyzeAsTar(s)
}
fn main() {
let mut fs = FileStream{};
analyze(&mut fs);
}这将产生以下错误:
<anon>:38:41: 38:44 error: cannot borrow `tar` as mutable more than once at a time [E0499]
<anon>:38 while let Some(Ok(mut substream)) = tar.next() {
^~~
<anon>:38:41: 38:44 help: see the detailed explanation for E0499
<anon>:38:41: 38:44 note: previous borrow of `tar` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `tar` until the borrow ends
<anon>:38 while let Some(Ok(mut substream)) = tar.next() {
^~~
<anon>:42:2: 42:2 note: previous borrow ends here
<anon>:36 fn analyzeAsTar(s: &mut Stream<u8>) -> bool {
...
<anon>:42 }发布于 2016-05-09 18:01:24
有一种解决方法。可以使用具有iterate函数的特征,而不是具有next()函数的特征。在下面的示例中,TarStreamIterator有一个函数iterate可以接受闭包。(或者,可以将iterator称为for_each。)
该实现仍然具有next函数,但借用检查器接受此形式。
这个简短的示例实际上不会对流做任何事情。
use std::io;
// generic version of std::io::Read
trait Stream<T> {
fn read(&mut self) -> io::Result<&[T]>;
}
trait StreamIterator<T> {
// call `f` on each of the streams in the iterator
fn iterate<F>(&mut self, mut f: F) where F: FnMut(&mut Stream<T>);
}
struct FileStream {
}
impl<T> Stream<T> for FileStream {
fn read(&mut self) -> io::Result<&[T]> {
Err(io::Error::new(io::ErrorKind::UnexpectedEof, ""))
}
}
struct TarStream<'a> {
stream: &'a mut Stream<u8>
}
impl<'a> Stream<u8> for TarStream<'a> {
fn read(&mut self) -> io::Result<&[u8]> {
self.stream.read()
}
}
struct TarStreamIterator<'a> {
stream: &'a mut Stream<u8>
}
impl<'a> TarStreamIterator<'a> {
// pass the next embedded stream or None if there are no more
fn next(&mut self) -> Option<TarStream> {
Some(TarStream{stream: self.stream})
}
}
impl<'a> StreamIterator<u8> for TarStreamIterator<'a> {
fn iterate<F>(&mut self, mut f: F) where F: FnMut(&mut Stream<u8>) {
while let Some(mut substream) = self.next() {
f(&mut substream);
}
}
}
fn analyze_as_tar(stream: &mut Stream<u8>) {
TarStreamIterator{stream: stream}.iterate(|substream| {
analyze(substream);
});
}
fn analyze(s: &mut Stream<u8>) {
analyze_as_tar(s)
}
fn main() {
let mut fs = FileStream{};
analyze(&mut fs);
}https://stackoverflow.com/questions/37075674
复制相似问题