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

remove 'static lifetime for add() argument #48

Open
raffomania opened this issue Mar 23, 2020 · 6 comments
Open

remove 'static lifetime for add() argument #48

raffomania opened this issue Mar 23, 2020 · 6 comments

Comments

@raffomania
Copy link

When using add, AFAIK the data I pass in has to be moved into the method because the argument requires a 'static lifetime.
This makes the following impossible:

    let mut child = Command::new("cat")
        .arg("test.txt")
        .stdout(Stdio::piped())
        .spawn()?;

    let hash = ipfs.add(child.stdout?);
    child.wait()?; // error: child was moved in the previous line
    hash

What I want to do:

  1. directly pipe stdout into ipfs, without waiting
  2. then wait for the first command to finish and check if it returned status 0
  3. then return the ipfs hash

please correct me if I'm wrong, but with a 'static lifetime I think there's no way to do this.

@ferristseng
Copy link
Owner

Sorry for the late response. I think this might be a requirement for hyper. See this related issue: ferristseng/rust-multipart-rfc7578#4

@rand0m-cloud
Copy link

The 'static requirement on data is extremely limited and makes the function useless because the usecase of adding compile time data to IPFS only exists in example code. I'm reverting to using the ipfs cli in my project because of this issue.

@ferristseng
Copy link
Owner

I believe this lifetime is a restriction of Actix/Hyper (example: https://docs.rs/hyper/0.14.16/hyper/struct.Body.html#method.wrap_stream).

What exactly are you trying to do?

@ferristseng
Copy link
Owner

please correct me if I'm wrong, but with a 'static lifetime I think there's no way to do this.

Added an example of how to do this: https://github.com/ferristseng/rust-ipfs-api/blob/35d282f4cfb2cf083abff5efa60c3c916f1d13fa/ipfs-api-examples/examples/add_file_piped_from_command.rs

@raffomania
Copy link
Author

raffomania commented Dec 19, 2021

Thanks for following up! I'm not sure how you're able to call take without any arguments in that example, as the docs say it should take an u64 as a limit. Also, I don't understand how that example solves the lifetime problems I encountered, and at this point I don't remember the exact errors I found, so maybe I made an error unrelated to the lifetime constraints of add. I'll try to incorporate the example into my project and report back, however I'm not sure when I'll get around to that.

@mrd0ll4r
Copy link
Contributor

mrd0ll4r commented Sep 22, 2022

Reviving this: I'm trying to cat data from IPFS and re-feed it to add with a different hash function, both via the HTTP API.

In the optimal case I don't want to read all of this into memory and then re-add it. Best case scenario would be to plumb the output of cat directly into add_async_with_options.

The slightly-worse-but-probably-works-for-now solution is to read all of it into memory and then add it, something like this:

let cat_resp = client
                    .cat(cid)
                    .map_ok(|chunk| chunk.to_vec())
                    .try_concat()
                    .await
                    .context("unable to cat file")?;

let sha1_resp = client.add_async_with_options(cat_resp.as_slice(),opts).await?;

But that does not work:

error[E0597]: `cat_resp` does not live long enough
   --> src/bin/test-api.rs:198:63
    |
198 |                 let sha1_resp = client.add_async_with_options(cat_resp.as_slice(),opts).await?;
    |                                 ------------------------------^^^^^^^^^^^^^^^^^^^------
    |                                 |                             |
    |                                 |                             borrowed value does not live long enough
    |                                 argument requires that `cat_resp` is borrowed for `'static`
199 |             }
    |             - `cat_resp` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

Edit: Looking a bit, I don't think the multipart::Form stuff needs a static lifetime:

impl<'a> Form<'a> {
    pub fn add_async_reader<F, R>(&mut self, name: F, read: R)
    where
        F: Display,
        R: 'a + AsyncRead + Send + Sync + Unpin,
    {
// ...
    }

// ...
}

Edit2: It does work with add_with_options (without AsyncRead), wrapping the Vec<u8> in a Cursor... hmm.

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

4 participants