I'm writing a filesystem utils in rust for userspace program and here's the snippet i wrote. It's relative long but i will keep it concise here.
pub(crate) struct TempBuffer {
block: Block,
maxsize: usize,
}
pub(crate) trait Buffer<'a> {
fn content_mut(&'a mut self) -> &'a mut [u8];
fn content(&'a self) -> &'a [u8];
}
impl TempBuffer {
pub(crate) fn new(block: Block, maxsize: usize) -> Self {
Self { block, maxsize }
}
}
impl<'a> Buffer<'a> for TempBuffer {
fn content_mut(&'a mut self) -> &'a mut [u8] {
&mut self.block[0..self.maxsize]
}
fn content(&'a self) -> &'a [u8] {
&self.block[0..self.maxsize]
}
}
impl<'a, 'b, T, U> Iterator for TempBufferIter<'a, 'b, T, U>
where
T: SuperBlockInfo<'a, U>,
U: FileBackend,
{
type Item = TempBuffer;
fn next(&mut self) -> Option<Self::Item> {
...
}
}
pub(crate) struct DirCollection<'a> {
data: &'a [u8],
offset: usize,
total: usize,
}
impl<'a> DirCollection<'a> {
pub(crate) fn new(buffer: &'a [u8]) -> Self {
let desc: &'a DirentDesc = unsafe { &*(buffer.as_ptr() as *const DirentDesc) };
Self {
data: buffer,
offset: 0,
total: desc.nameoff as usize / core::mem::size_of::<DirentDesc>(),
}
}
}
impl<'a, T> SuperBlockInfo<'a, T> for RawFileSystem<T>
where
T: FileBackend,
{
fn find_nid(&self, inode: &Inode, name: &str) -> Option<Nid> {
for buf in self.content_iter(inode){
for dirent in DirCollection::new(buf.content()) {
if dirent.dirname(buf.content()) == name.as_bytes() {
return Some(dirent.desc.nid);
}
}
}
None
}
fn content_iter(&'a self, inode: &Inode) -> impl Iterator<Item = impl Buffer<'a>> {
TempBufferIter::new(&self.backend, MapIter::new(self, inode))
}
}
This code won't compile with this error.
error[E0597]: `buf` does not live long enough
|
24 | for buf in self.content_iter(inode){
| --- binding `buf` declared here
25 | for dirent in DirCollection::new(buf.content()) {
| ^^^ borrowed value does not live long enough
...
30 | }
| -
| |
| `buf` dropped here while still borrowed
| borrow might be used here, when `buf` is dropped and runs the destructor for type `impl data::Buffer<'_>`
I believe this buf simply outlives the inner loop and I just don't don't knowwhy borrow checker fails here I've been trying to resolve this for a long time but i simply cannot find a workaround. Any help or suggestions will be much appreciated. Thanks!
BTW. Are there any ways that i can get detailed lifetime annotations of these scopes so that i can retrieve at least some additional information to diagnose the problem myself? It always seems like a black box to me when i try to understand what happens inside the borrow checker. Whenever i fix it , i often just don't understand why i fix it and why it works. I came from C and i know that lifetime is a good programming model but i find it too daunting to adapt to it.