Я пишу код в 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 }
Сложно, вы пытаетесь создать то, что называется потоковым итератором *, который возвращает ссылки на ** сам ** как часть контракта. Есть проекты [1] (https://github.com/emk/rust -streaming) [2] (http://burntsushi.net/rustdoc/fst/trait.Streamer.html), Reddit threads [1] (https://www.reddit.com/r/rust/comments/303a09/looking_for_more_information_on_streaming/), [2] (https://www.reddit.com/r/rust/comments/2t1rxx), [сообщения на форуме] (https://users.rust-lang.org/t/x/1096) и даже [SO questions] (http://stackoverflow.com/q/31969710/155423) о теме. – Shepmaster