Hi everyone! I have a problem with GATs and lifetimes and hope to get from help
I'm trying to implement a trait to read a stream in fixed-size chunks, as the following:
pub trait ChunkRead {
type R<'s>: Read + Seek where Self: 's;
fn read_chunk(&mut self, chunk_number: u64) -> io::Result<Self::R<'_>>;
fn chunk_size(&self) -> u64;
}
And then write abstractions to go stream -> chunked stream
and chunked stream -> stream
For the second case I currently have the following:
pub struct ChunkReader<'r, C, R> {
chunks: &'r mut C,
current_reader: Option<R>,
current_chunk: u64,
current_chunk_read: usize,
}
impl<'r, R, C> ChunkReader<'r, C, R> {
fn new(chunks: &'r mut C) -> Self {
Self {
chunks,
current_reader: None,
current_chunk: 0,
current_chunk_read: 0,
}
}
}
impl<'s, 'r: 's, R: Read + Seek, C: ChunkRead<R<'s> = R> + 's> Read for ChunkReader<'r, C, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let reader = match self.current_reader.as_mut() {
None => {
self.current_reader = Some(self.chunks.read_chunk(self.current_chunk)?);
self.current_reader.as_mut().unwrap()
}
Some(_) => {
if self.current_chunk_read == self.chunks.chunk_size() as usize {
let new_reader = self.chunks.read_chunk(self.current_chunk + 1);
match new_reader {
Ok(new_reader) => {
self.current_chunk += 1;
self.current_chunk_read = 0;
self.current_reader = Some(new_reader);
}
Err(e) => {
return if e.kind() == ErrorKind::UnexpectedEof {
Ok(0)
} else {
Err(e)
}
}
}
}
self.current_reader.as_mut().unwrap()
}
};
let read = reader.read(buf)?;
self.current_chunk_read += read;
Ok(read)
}
}
(I'm not pasting the error here because is fairly large, here's a link to the playground)
In particular I'm not quite understanding why the compiler complains about lifetime '1
which is tied to self
, but self.chunks
should have lifetime 'r
right?
For reference, here's a previous version of the same trait without GATs, however I found it necessary to introduce them when implementing the chunked stream -> stream
use case
Thank you for your help!