You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: task.rs
    path of file: ./repos/stewardx/src/tasks/cmd_async
    
    the code of the file until where you have to start completion: use async_trait::async_trait;
use futures::StreamExt;
use serde::{Deserialize, Serialize};
use tracing::{instrument, error};
use std::process::Stdio;
use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::{
    io::{AsyncBufReadExt, BufReader},
    process::Child,
};
use tokio_stream::wrappers::LinesStream;
use uuid::Uuid;

use crate::{
    models::TaskError,
    traits::{BoxedStream, Executable, FromJson, GetSerdeFromProps},
};

#[derive(Debug, Serialize, Deserialize)]
pub struct CmdTask {
    pub id: Uuid,
    pub command: Box<String>,
    #[serde(skip)]
    child_handle: Arc<Mutex<Option<Child>>>,
}

impl CmdTask {
    pub fn new(id: Uuid, command: Box<String>) -> Self {
        let id_literal = id.to_string();
        let cmd_literal = command.to_string();
        tracing::info_span!(
            "Creating a new CmdTask",
            id = %id_literal,
            command = %cmd_literal
        );
        Self {
            id,
            command,
         
    
    async fn exec(&mut self) -> Result<BoxedStream, TaskError> {
        let (prog, args) = CmdTask::parse_cmd(&self.id, &self.command).unwrap();
        let mut cmd = tokio::process::Command::new(prog);
        for arg in args {
            cmd.arg(arg);
        }
        cmd.stdout(Stdio::piped());
        let child = match cmd.spawn() {
            Ok(c) => c,
            Err(e) => {
                error!("Execution failed, error while trying to spawn the command: {}", e);
                panic!("{}", e.to_string());
                // return Err(TaskError::TaskExecution(self.get_id(), e.to_string()));
            }
        };
        self.child_handle = Arc::new(Mutex::new(Some(child)));
        let child = self.child_handle.clone();
        let mut child = child.lock().await;
        let child = child.as_mut().unwrap();
        let child_out = &mut child.stdout;
        let stdout = match child_out.take() {
            Some(s) => s,
            None => {
                error!("Couldn't get stdout handle of cmd task.");
                return Ok(Box::new(tokio_stream::empty()));
            }
        };
        let reader = BufReader::new(stdout);
        let lines = reader.lines();
        let stream = LinesStream::new(lines);
        let stream = stream.map(|l| l.unwrap());
        Ok(Box::new(stream))
    }