pub(crate) fn create_and_start(
        docker: &'docker Docker,
        container_id: &str,
        opts: &ExecContainerOptions,
    ) -> impl Stream<Item = Result<tty::TtyChunk>> + Unpin + 'docker {
        #[derive(serde::Deserialize)]
        #[serde(rename_all = "PascalCase")]
        struct Response {
            id: String,
        }

        // To not tie the lifetime of `opts` to the stream, we do the serializing work outside of
        // the stream. But for backwards compatability, we have to return the error inside of the
        // stream.
        let body_result = opts.serialize();

        // To not tie the lifetime of `container_id` to the stream, we convert it to an (owned)
        // endpoint outside of the stream.
        let container_endpoint = format!("/containers/{}/exec", container_id);

        Box::pin(
            async move {
                // Bubble up the error inside the stream for backwards compatability
                let body: Body = body_result?.into();

                let exec_id = docker
                    .post_json(&container_endpoint, Some((body, mime::APPLICATION_JSON)))
                    .await
                    .map(|resp: Response| resp.id)?;

                let stream = Box::pin(docker.stream_post(
                    format!("/exec/{}/start", exec_id),
                    Some(("{}".into(), mime::APPLICATION_JSON)),
                    None::<iter::Empty<_>>,
                ));

                Ok(tty::decode(stream))
            }
            .try_flatten_stream(),
        )
    }
// This exists for Container::exec()
//
// We need to combine `Exec::create` and `Exec::start` into one method because otherwise you
// needlessly tie the Stream to the lifetime of `container_id` and `opts`. This is because
// `Exec::create` is async so it must occur inside of the `async move` block. However, this
// means that `container_id` and `opts` are both expected to be alive in the returned stream
// because we can't do the work of creating an endpoint from `container_id` or serializing
// `opts`. By doing this work outside of the stream, we get owned values that we can then move
// into the stream and have the lifetimes work out as you would expect.
//
// Yes, it is sad that we can't do the easy method and thus have some duplicated code.


Yes, it is sad that we can't do the easy method and thus have some duplicated code.
Yes it is sad that we can ' t do the easy method and thus have some duplicated code .
pub(crate) fn create_and_start(
        docker: &'docker Docker,
        container_id: &str,
        opts: &ExecContainerOptions,
    ) -> impl Stream<Item = Result<tty::TtyChunk>> + Unpin + 'docker {
        #[derive(serde::Deserialize)]
        #[serde(rename_all = "PascalCase")]
        struct Response {
            id: String,
        }
        // To not tie the lifetime of `opts` to the stream, we do the serializing work outside of
        // the stream. But for backwards compatability, we have to return the error inside of the
        // stream.
        let body_result = opts.serialize();
        // To not tie the lifetime of `container_id` to the stream, we convert it to an (owned)
        // endpoint outside of the stream.
        let container_endpoint = format!("/containers/{}/exec", container_id);
        Box::pin(
            async move {
                // Bubble up the error inside the stream for backwards compatability
                let body: Body = body_result?.into();
                let exec_id = docker
                    .post_json(&container_endpoint, Some((body, mime::APPLICATION_JSON)))
                    .await
                    .map(|resp: Response| resp.id)?;
                let stream = Box::pin(docker.stream_post(
                    format!("/exec/{}/start", exec_id),
                    Some(("{}".into(), mime::APPLICATION_JSON)),
                    None::<iter::Empty<_>>,
                ));
                Ok(tty::decode(stream))
            }
            .try_flatten_stream(),
        )
    }
pub ( crate ) fn create_and_start ( docker : & ' docker Docker , container_id : & str , opts : & ExecContainerOptions , ) -> impl Stream < Item = Result < tty :: TtyChunk > > + Unpin + ' docker { # [ derive ( serde Deserialize ) ] # [ serde ( rename_all " " ) ] struct Response { id : String , } // To not tie the lifetime of `opts` to the stream, we do the serializing work outside of // the stream. But for backwards compatability, we have to return the error inside of the // stream. let body_result = opts . serialize ( ) ; // To not tie the lifetime of `container_id` to the stream, we convert it to an (owned) // endpoint outside of the stream. let container_endpoint = format ! ( " " container_id ) ; Box :: pin ( async move { // Bubble up the error inside the stream for backwards compatability let body : Body = body_result ? . into ( ) ; let exec_id = docker . post_json ( & container_endpoint , Some ( ( body , mime :: APPLICATION_JSON ) ) ) . await . map ( | resp : Response | resp . id ) ? ; let stream = Box :: pin ( docker . stream_post ( format ! ( " " exec_id ) , Some ( ( " " . into ( ) , mime :: APPLICATION_JSON ) ) , None :: < iter :: Empty < _ > > , ) ) ; Ok ( tty :: decode ( stream ) ) } . try_flatten_stream ( ) , ) }
This exists for Container::exec()
We need to combine `Exec::create` and `Exec::start` into one method because otherwise you
needlessly tie the Stream to the lifetime of `container_id` and `opts`.
This exists for Container :: exec () We need to combine ` Exec :: create ` and ` Exec :: start ` into one method because otherwise you needlessly tie the Stream to the lifetime of ` container_id ` and ` opts ` .
docker
&'docker Docker
container_id
&str
opts
&ExecContainerOptions
docker
&'docker Docker
container_id
&str
opts
&ExecContainerOptions