Unverified Commit e6ef4fed authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

improve ByteStream docs & add pub use (#443)

* improve ByteStream docs & add pub use

This commit attempts to improve the discoverability and useability of `ByteStream`:
1. Adds pub use for bytestream. This is currently added to all crates. At some point in the future, we may wish to prune this
to crates that actually use it, but as it doesn't actually add an additional dependency, there isn't currently any harm.
SdkBody is explicitly _not_ pub use'd. Generally, people shouldn't need to use `SdkBody` directly.

2. Clarifies, adds examples, and generally increases the scope of the `ByteStream` documentation.

* Update rust-runtime/smithy-http/src/byte_stream.rs
parent 8c1f763d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@ edition = "2018"

[dependencies]
s3 = { package = "aws-sdk-s3", path = "../../build/aws-sdk/s3" }
smithy-http = { path = "../../build/aws-sdk/smithy-http" }
tokio = { version = "1", features = ["full"] }
tracing-subscriber = "0.2.18"

+1 −1
Original line number Diff line number Diff line
use s3::ByteStream;
use s3::Region;
use smithy_http::byte_stream::ByteStream;
use std::error::Error;
use std::path::Path;
use tracing_subscriber::fmt::format::FmtSpan;
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ import software.amazon.smithy.rust.codegen.smithy.generators.LibRsSection
fun pubUseTypes(runtimeConfig: RuntimeConfig) = listOf(
    RuntimeType.Blob(runtimeConfig),
    CargoDependency.SmithyHttp(runtimeConfig).asType().member("result::SdkError"),
    CargoDependency.SmithyHttp(runtimeConfig).asType().member("byte_stream::ByteStream"),
)

class SmithyTypesPubUseGenerator(private val runtimeConfig: RuntimeConfig) : LibRsCustomization() {
+8 −0
Original line number Diff line number Diff line
@@ -77,6 +77,14 @@ impl SdkBody {
        }
    }

    /// Construct an explicitly retryable SDK body
    ///
    /// ## NOTE: This is probably not what you want
    ///
    /// All bodies constructed from in-memory data (`String`, `Vec<u8>`, `Bytes`, etc.) will be
    /// retryable out of the box. If you want to read data from a file, you should use
    /// [`ByteStream::from_path`](crate::byte_stream::ByteStream::from_path). This function is only necessary when you
    /// need to enable retries for your own streaming container.
    pub fn retryable(f: impl Fn() -> SdkBody + Send + Sync + 'static) -> Self {
        let initial = f();
        SdkBody {
+40 −1
Original line number Diff line number Diff line
@@ -110,6 +110,8 @@ mod bytestream_util;
///
/// `ByteStream` wraps a stream of binary data for ease of use.
///
/// ## Getting data out of a `ByteStream`
///
/// `ByteStream` provides two primary mechanisms for accessing the data:
/// 1. With `.collect()`:
/// [`.collect()`](crate::byte_stream::ByteStream::collect) reads the complete ByteStream into memory and stores it in `AggregatedBytes`,
@@ -144,7 +146,7 @@ mod bytestream_util;
///     use tokio_stream::StreamExt;
///
///     async fn example() -> Result<(), Error> {
///        let mut stream = ByteStream::new(SdkBody::from("hello! This is some data"));
///        let mut stream = ByteStream::from(vec![1, 2, 3, 4, 5, 99]);
///        let mut digest = crc32::Digest::new();
///        while let Some(bytes) = stream.try_next().await? {
///            digest.write(&bytes);
@@ -154,6 +156,38 @@ mod bytestream_util;
///     }
///     ```
///
/// ## Getting data into a ByteStream
/// ByteStreams can be created in one of three ways:
/// 1. **From in-memory binary data**: ByteStreams created from in-memory data are always retryable. Data
/// will be converted into `Bytes` enabling a cheap clone during retries.
///     ```rust
///     use bytes::Bytes;
///     use smithy_http::byte_stream::ByteStream;
///     let stream = ByteStream::from(vec![1,2,3]);
///     let stream = ByteStream::from(Bytes::from_static(b"hello!"));
///     ```
///
/// 2. **From a file**: ByteStreams created from a path can be retried. A new file descriptor will be opened if a retry occurs.
///     ```rust
///     use smithy_http::byte_stream::ByteStream;
///     let stream = ByteStream::from_path("big_file.csv");
///     ```
///
/// 3. **From an `SdkBody` directly**: For more advanced / custom use cases, a ByteStream can be created directly
/// from an SdkBody. **When created from an SdkBody, care must be taken to ensure retriability.** An SdkBody is retryable
/// when constructured from in-memory data or when using [`SdkBody::retryable`](crate::body::SdkBody::retryable).
///     ```rust
///     use smithy_http::byte_stream::ByteStream;
///     use smithy_http::body::SdkBody;
///     use bytes::Bytes;
///     let (mut tx, channel_body) = hyper::Body::channel();
///     // this will not be retryable because the SDK has no way to replay this stream
///     let stream = ByteStream::new(SdkBody::from(channel_body));
///     tx.send_data(Bytes::from_static(b"hello world!"));
///     tx.send_data(Bytes::from_static(b"hello again!"));
///     // NOTE! You must ensure that `tx` is dropped to ensure that EOF is sent
///     ```
///
#[pin_project]
#[derive(Debug)]
pub struct ByteStream(#[pin] Inner<SdkBody>);
@@ -264,12 +298,17 @@ impl From<SdkBody> for ByteStream {
    }
}

/// Construct a retryable ByteStream from [`bytes::Bytes`](bytes::Bytes)
impl From<Bytes> for ByteStream {
    fn from(input: Bytes) -> Self {
        ByteStream::new(SdkBody::from(input))
    }
}

/// Construct a retryable ByteStream from a `Vec<u8>`.
///
/// This will convert the `Vec<u8>` into [`bytes::Bytes`](bytes::Bytes) to enable efficient
/// retries.
impl From<Vec<u8>> for ByteStream {
    fn from(input: Vec<u8>) -> Self {
        Self::from(Bytes::from(input))