1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::{json_enum, json_struct};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

json_enum!(
    /// Target where host logs should be written to.
    #[derive(Default)]
    #[serde(rename_all = "lowercase")]
    pub enum HostLogTarget {
        Stderr,
        Stdout,
        #[default]
        Tracing,
    }
);

json_enum!(
    /// Input passed to the `host_log` host function.
    #[serde(untagged)]
    pub enum HostLogInput {
        Message(String),
        TargetedMessage {
            message: String,
            target: HostLogTarget,
        },
        Fields {
            data: HashMap<String, serde_json::Value>,
            message: String,
        },
    }
);

impl From<&str> for HostLogInput {
    fn from(message: &str) -> Self {
        HostLogInput::Message(message.to_owned())
    }
}

impl From<String> for HostLogInput {
    fn from(message: String) -> Self {
        HostLogInput::Message(message)
    }
}

json_struct!(
    /// Input passed to the `exec_command` host function.
    pub struct ExecCommandInput {
        /// Arguments to pass to the command.
        pub args: Vec<String>,

        /// The command to execute.
        pub command: String,

        /// Environment variables to pass to the command.
        pub env_vars: HashMap<String, String>,

        /// Mark the command as executable before executing.
        #[doc(hidden)]
        pub set_executable: bool,

        /// Stream the output instead of capturing it.
        pub stream: bool,
    }
);

impl ExecCommandInput {
    /// Create a new command that pipes and captures the output.
    pub fn pipe<C, I, V>(command: C, args: I) -> ExecCommandInput
    where
        C: AsRef<str>,
        I: IntoIterator<Item = V>,
        V: AsRef<str>,
    {
        ExecCommandInput {
            command: command.as_ref().to_string(),
            args: args.into_iter().map(|a| a.as_ref().to_owned()).collect(),
            ..ExecCommandInput::default()
        }
    }

    /// Create a new command that inherits and streams the output.
    pub fn inherit<C, I, V>(command: C, args: I) -> ExecCommandInput
    where
        C: AsRef<str>,
        I: IntoIterator<Item = V>,
        V: AsRef<str>,
    {
        let mut input = Self::pipe(command, args);
        input.stream = true;
        input
    }
}

json_struct!(
    /// Output returned from the `exec_command` host function.
    pub struct ExecCommandOutput {
        pub command: String,
        pub exit_code: i32,
        pub stderr: String,
        pub stdout: String,
    }
);