use std::{fmt, io, pin::Pin, sync::Arc};
use bytes::Bytes;
use futures::stream::BoxStream;
use tokio::io::{AsyncBufRead, AsyncReadExt};
use crate::core::{client::Client, error::Result};
pub struct ExecResult {
pub(super) client: Arc<Client>,
pub(crate) id: String,
pub(super) stdout: BoxStream<'static, std::result::Result<Bytes, io::Error>>,
pub(super) stderr: BoxStream<'static, std::result::Result<Bytes, io::Error>>,
}
impl ExecResult {
pub async fn exit_code(&self) -> Result<Option<i64>> {
let res = self.client.inspect_exec(&self.id).await?;
Ok(res.exit_code)
}
pub fn stdout<'b>(&'b mut self) -> Pin<Box<dyn AsyncBufRead + Send + 'b>> {
Box::pin(tokio_util::io::StreamReader::new(&mut self.stdout))
}
pub fn stderr<'b>(&'b mut self) -> Pin<Box<dyn AsyncBufRead + Send + 'b>> {
Box::pin(tokio_util::io::StreamReader::new(&mut self.stderr))
}
pub async fn stdout_to_vec(&mut self) -> Result<Vec<u8>> {
let mut stdout = Vec::new();
self.stdout().read_to_end(&mut stdout).await?;
Ok(stdout)
}
pub async fn stderr_to_vec(&mut self) -> Result<Vec<u8>> {
let mut stderr = Vec::new();
self.stderr().read_to_end(&mut stderr).await?;
Ok(stderr)
}
}
impl fmt::Debug for ExecResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExecResult").field("id", &self.id).finish()
}
}