首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用生命周期来嵌套可变访问?

如何使用生命周期来嵌套可变访问?
EN

Stack Overflow用户
提问于 2016-05-06 23:03:19
回答 1查看 82关注 0票数 2

我正在用Rust编写代码来解析数据流,trait Stream。流可以由其他流组成。特征StreamIterator提供对子流的访问。这是在解析tar文件、zip文件和其他包含文件的文件时使用的。

在写这段代码的时候,我一直在与借入检查器做斗争,但没有成功。

下面的代码是一个简化的示例。在main中,文件以流的形式打开。该流被传递给analyze函数,该函数尝试将流作为TarStreamIterator打开,以迭代tar中的流。还分析了每个嵌入的流。

我想我可能会在StreamIterator特征中引入第二个生命周期。

代码语言:javascript
复制
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);
}

这将产生以下错误:

代码语言:javascript
复制
<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 }
EN

回答 1

Stack Overflow用户

发布于 2016-05-09 18:01:24

有一种解决方法。可以使用具有iterate函数的特征,而不是具有next()函数的特征。在下面的示例中,TarStreamIterator有一个函数iterate可以接受闭包。(或者,可以将iterator称为for_each。)

该实现仍然具有next函数,但借用检查器接受此形式。

这个简短的示例实际上不会对流做任何事情。

代码语言:javascript
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37075674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档