Another Lifetime Puzzle (tide, mongoDB)

Hi there,

I'm using tide together with mongodb to build up a REST API server. This works quite well and surprisingly easy. However, I'm struggeling with lifetimes when it comes to passing the result from a mongodb query to the response.
I do understand why the compiler complains, but I've no idea at the moment how to solve this.

The function in question:

pub async fn download_file(req: Request<Database>) -> Response {
    let name: String = req.param("name").unwrap();
    let version: String = req.param("version").unwrap();
   
    let db: &Database = req.state();
    let collection = db.collection("files");
    let filter = doc! {
        "name": name,
        "version": version,
    };

    
    match collection.find_one(filter, None) {
        Ok(Some(document)) => {
            let data = document.get_binary_generic("file_content").unwrap();
            Response::new(200)
                .body(&data[..data.len()])
        },
        _ => Response::new(500).body_string("no such file found".into()),
    }

}

The complain is that documentdoes not life long enough which I do understand as the response borrow of the Vec is "converted" into a BufReader while handing over to .body() method.
My naive solution would be to assume I can find a BufReader that takes a copy of this Vec and consumes it so the lifetime would not be an issue, right? But I can't seem to find an approach to do this - except of writing a "custom" BufReader implementation for Vec... but I'd like to not di this.

So I'm seeking for your Ideas and advice how to overcome this problem...
Thx in advance...

Could you please post the full error message?

This is due to body requiring a 'static argument, and data does not live that long. It's weird that Cursor doesn't implement the trait, but it's probably rather easy to create a wrapper struct around Cursor<Vec<u8>> and manually implement the trait.

2 Likes

Hey, sure.
The complete message:

`document` does not live long enough

borrowed value does not live long enoughrustc(E0597)
api.rs(32, 24): borrowed value does not live long enough
api.rs(32, 24): argument requires that `document` is borrowed for `'static`
api.rs(35, 10): `document` dropped here while still borrowed

Hey alice,

thanks for the hint. I'll try this out and come back if I'm getting stuck again :wink:

Hey, in case anyone else comes here, this is how I solved it (it requires a bunch of trait implementations...

struct VecReader {
    inner: io::Cursor<Vec<u8>>,
}

impl VecReader {
    fn new(data: Vec<u8>) -> Self {
        VecReader {
            inner: io::Cursor::new(data),
        }
    }
}

impl io::Read for VecReader {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}

impl io::BufRead for VecReader {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.inner.fill_buf()
    }
    fn consume(&mut self, amt: usize) { 
        self.inner.consume(amt);
     }
}

impl AsyncRead for VecReader {
    fn poll_read(mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>>
    {
        Poll::Ready(io::Read::read(&mut *self, buf))
    }

    fn poll_read_vectored(mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) -> Poll<io::Result<usize>>
    {
        Poll::Ready(io::Read::read_vectored(&mut *self, bufs))
    }
}

impl AsyncBufRead for VecReader {
    fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>>
    {
        Poll::Ready(io::BufRead::fill_buf(self.get_mut()))
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        io::BufRead::consume(self.get_mut(), amt)
    }
}

and the actual usage:

match collection.find_one(filter, None) {
        Ok(Some(document)) => {
            let mut data = Vec::new();
            data.copy_from_slice(document.get_binary_generic("file_cotent").unwrap());
            let vec_reader = VecReader::new(data);
            Response::new(200)
                .body(vec_reader)
        },
        _ => Response::new(500).body_string("no such file found".into()),
    }

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.