Cannot move out from a shared reference

I am trying to iterate over a bunch of S3 files and process those. Not sure how to work with ByteStream because it seems I cannot use the collect() method on it due to the following error.

What am I missing?

async fn read_files(
    s3_client: S3Client,
    s3_bucket: &str,
    s3_prefixes: Vec<String>,
) -> Result<String, BoxedErr> {
    let futures = s3_prefixes.iter().map(|prefix| async {

    let objects: Vec<Result<GetObjectOutput, SdkError<GetObjectError>>> = join_all(futures).await;

    let byte_streams: Vec<&ByteStream> = objects
        .filter(|y| y.is_ok())
        .map(|x| x.as_ref().unwrap().body())

    let bytes = byte_streams
        .map(|x| async { x.collect()|data| data.into_bytes()) })


The error:

Result<String, Box<dyn Error + Send + Sync, Global>>
Go to Result | String | Box | Error | Global

cannot move out of `**x` which is behind a shared reference
move occurs because `**x` has type `ByteStream`, which does not implement the `Copy` traitrustcClick for full compiler diagnostic, 28): `**x` moved due to this method call, 26): this function takes ownership of the receiver `self`, which moves `**x`

Don't copy error messages from IDEs. Use cargo check in the terminal and copy from there. Much more readable and useful to people trying to answer your questions :wink:


[T]::iter creates an implementation of Iterator<Item = &T>, hence x is borrowed. This becomes a problem when you try to move x by consuming it. You want to use Vec::into_iter here instead.


Thanks for the suggestions.

    let byte_streams: Vec<GetObjectOutput> = objects
        .filter(|y| y.is_ok())
        .map(|x| x.unwrap())

    let bytes = byte_streams
        .map(|x| x.body().into_inner())
        //.map(|x| async move { x.body().collect()|data| data.into_bytes()) })
error[E0507]: cannot move out of a shared reference
   --> src/
167 |         .map(|x| x.body().into_inner())
    |                  ^^^^^^^^^------------
    |                  |        |
    |                  |        value moved due to this method call
    |                  move occurs because value has type `aws_sdk_s3::types::ByteStream`, which does not implement the `Copy` trait
note: this function takes ownership of the receiver `self`, which moves value
   --> /Users/l1x/.cargo/registry/src/
280 |     pub fn into_inner(self) -> SdkBody {
    |                       ^^^^

For more information about this error, try `rustc --explain E0507`.
warning: `convert-logs-to-parquet` (bin "convert-logs-to-parquet") generated 2 warnings
error: could not compile `convert-logs-to-parquet` due to previous error; 2 warnings emitted

Based on the discussion and the rustc recommendation it try to use into_inner() without success.

I am going to use that going forward. Thanks.

Finally I figured out that using x.body instead of x.body() works. This is the internal details of this lib that was hard to understand at first.