firetrap icon indicating copy to clipboard operation
firetrap copied to clipboard

Example with rusoto

Open alu opened this issue 7 years ago • 4 comments

I am in creating ftp server with rusto.

get_object() function of rusto returns content body as ByteStream, so i want to return it as stream in get() function. The function returns impl trait, but StorageBackend requires associate type File, so I can't these types be mached.

Can I get several examples or hints?

Thanks ;D

alu avatar Jan 04 '19 02:01 alu

Thanks for your interest in firetrap!

It's not entirely clear to me what you're trying to do, but I'll try to help anyway.

If you're interested in writing your own StorageBackend, you can do this by using ByteStream directly as the associated type.

If you want to use the existing Filesystem backend, you could probably wrap around the tokio::fs::File that it uses, and create a ByteStream from it.

Does this help you achieve what you want?

koenw avatar Jan 17 '19 12:01 koenw

Thank you for reply!

If you're interested in writing your own StorageBackend, you can do this by using ByteStream directly as the associated type.

We can't specify ByteStream to File association type because Byte Stream have not implemented AsyncRead.

alu avatar Jan 18 '19 00:01 alu

We can't specify ByteStream to File association type because Byte Stream have not implemented AsyncRead.

Hmm, to be honest I'm not sure what the best approach is then. The way the StorageBackend is used now, it really needs AsyncRead (by design, or the threads could block). Perhaps you could somehow write an Async wrapper around the sync Bytestream, but I'm not really sure how I would go around doing that. Perhaps you could look at some examples from how the standard library implements Async types on top of Sync types?

koenw avatar Feb 14 '19 17:02 koenw

My example is here.

fn get<P: AsRef<Path>>(
    &self,
    path: P,
) -> Box<Future<Item = Self::File, Error = Self::Error> + Send> {
    let client = Arc::clone(&self.client);
    let bucket = "xxxx";

    let future = future::result(self.key(path))
        .and_then(move |key| {
            client
                .get_object(rusoto_s3::GetObjectRequest {
                    bucket: bucket.into(),
                    key: key,
                    ..Default::default()
                })
                .map_err(|_| ErrorKind::Unknown)
        })
        .and_then(|object| {
            let body = object
                .body
                .unwrap_or_else(|| rusoto_core::ByteStream::from(vec![]));

            tokio::codec::FramedRead::new(
                body.into_async_read(),
                tokio::codec::BytesCodec::new(),
            )
            .concat2()
            .map_err(|_| ErrorKind::Unknown)
        })
        .map(|body| std::io::Cursor::new(body.to_vec()));

    Box::new(future)
}

I convert into std::io::Cursor from ByteStream because Cursor have implimented AsyncRead. ByteStream -> tokio::codec::FramedRead -> BytesMut -> Vec<u8> -> Cursor.

But we will lost advantage async programing when we convert into BytesMut.

alu avatar Feb 15 '19 02:02 alu