Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Body can be limiting. #963

Open
daxpedda opened this issue Jul 1, 2020 · 8 comments
Open

Body can be limiting. #963

daxpedda opened this issue Jul 1, 2020 · 8 comments

Comments

@daxpedda
Copy link
Contributor

daxpedda commented Jul 1, 2020

I have a use case where I get a &[u8] over FFI that I want to use as a body to send a request with.
The issue arises because I can't take ownership of it in Rust because it can't be deallocated in Rust and has to be deallocated over FFI. So the only solution is to convert it to a &'static [u8] via unsafe and make sure nothing goes wrong.

I was thinking that one simple solution might just be to enable Body to take any T that implements AsRef<[u8]> for example. That way that T can implement it's own Drop that deallocates properly over FFI.

Is this appropriate/in scope? Are there alternatives?

@seanmonstar
Copy link
Owner

The body needs to be static, because it might (and in case of blocking, will) be sent to another thread.

Casting a buffer to a static slice could be very dangerous. Is the FFI caller giving you ownership of the buffer?

@daxpedda
Copy link
Contributor Author

daxpedda commented Jul 1, 2020

Casting a buffer to a static slice could be very dangerous.

Thats why I'm trying to avoid it.

Is the FFI caller giving you ownership of the buffer?

No, let me illustrate my problem:

struct Buffer {
    data: *const u8
    len: usize
}

impl AsRef<[u8]> for Buffer { ... }

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe { ffi::free(self.data) }
    }
}

This Buffer is what I have, the issue is that Body only accepts String, Vec, Bytes or any &'static references of it.
My suggestion to a solution to the problem is to let Body accept any T that implements AsRef<[u8]>, so I can pass ownership to Body.

@seanmonstar
Copy link
Owner

Are you using the blocking client? If so, you can use reqwest::blocking::Body::new (or sized) to pass an impl Read. With your Buffer, you could wrap it in a std::io::Cursor to get one.

@daxpedda
Copy link
Contributor Author

daxpedda commented Jul 1, 2020

I just switched from the blocking one to the async one because my workload demanded it, before that I was using exactly that solution.

@seanmonstar
Copy link
Owner

In that case, probably the best thing would be for us to make the Bytes vtable constructor public, so you could define how to clone and drop your buffer.

@daxpedda
Copy link
Contributor Author

daxpedda commented Jul 1, 2020

Mh, I didn't even know Bytes had a vtable ...
In any case, currently I was playing around with extending Body with a Custom variant that has a Box<Buf>, seems to be working actually, but obviously far from optimal.

I will look into the Bytes solution tomorrow, any guidance would be appreciated, thanks!

@daxpedda
Copy link
Contributor Author

daxpedda commented Jul 1, 2020

daxpedda@59a3e35

Here is my little experiment.

@daxpedda
Copy link
Contributor Author

daxpedda commented Jul 2, 2020

I was just looking into the vtable stuff, that would definitly be fixing the problem right at the source, instead of exposing a new API in reqwest.

So I assume the related issue is: tokio-rs/bytes#359?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants