warpgate_api/
host_funcs.rs1use crate::virtual_path::VirtualPath;
2use crate::{AnyResult, api_struct, api_unit_enum};
3use rustc_hash::FxHashMap;
4use serde::de::DeserializeOwned;
5
6api_unit_enum!(
7 pub enum HostLogTarget {
9 Stderr,
11 Stdout,
12 Debug,
14 Error,
15 Trace,
16 Warn,
17 #[default]
18 Tracing,
19 }
20);
21
22api_struct!(
23 pub struct HostLogInput {
25 #[serde(default)]
26 pub data: FxHashMap<String, serde_json::Value>,
27
28 pub message: String,
29
30 #[serde(default)]
31 pub target: HostLogTarget,
32 }
33);
34
35impl HostLogInput {
36 pub fn new(message: impl AsRef<str>) -> Self {
38 Self {
39 message: message.as_ref().to_owned(),
40 ..Default::default()
41 }
42 }
43}
44
45impl From<&str> for HostLogInput {
46 fn from(message: &str) -> Self {
47 HostLogInput::new(message)
48 }
49}
50
51impl From<String> for HostLogInput {
52 fn from(message: String) -> Self {
53 HostLogInput::new(message)
54 }
55}
56
57api_struct!(
58 #[serde(default)]
60 pub struct ExecCommandInput {
61 pub command: String,
63
64 #[serde(skip_serializing_if = "Vec::is_empty")]
66 pub args: Vec<String>,
67
68 #[serde(skip_serializing_if = "FxHashMap::is_empty")]
70 pub env: FxHashMap<String, String>,
71
72 #[doc(hidden)]
74 pub set_executable: bool,
75
76 pub stream: bool,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub working_dir: Option<VirtualPath>,
82 }
83);
84
85impl ExecCommandInput {
86 pub fn pipe<C, I, V>(command: C, args: I) -> ExecCommandInput
88 where
89 C: AsRef<str>,
90 I: IntoIterator<Item = V>,
91 V: AsRef<str>,
92 {
93 ExecCommandInput {
94 command: command.as_ref().to_string(),
95 args: args.into_iter().map(|a| a.as_ref().to_owned()).collect(),
96 ..ExecCommandInput::default()
97 }
98 }
99
100 pub fn inherit<C, I, V>(command: C, args: I) -> ExecCommandInput
102 where
103 C: AsRef<str>,
104 I: IntoIterator<Item = V>,
105 V: AsRef<str>,
106 {
107 let mut input = Self::pipe(command, args);
108 input.stream = true;
109 input
110 }
111}
112
113api_struct!(
114 #[serde(default)]
116 pub struct ExecCommandOutput {
117 pub command: String,
118 pub exit_code: i32,
119 pub stderr: String,
120 pub stdout: String,
121 }
122);
123
124impl ExecCommandOutput {
125 pub fn get_output(&self) -> String {
126 let mut out = String::new();
127 out.push_str(self.stdout.trim());
128
129 if !self.stderr.is_empty() {
130 if !out.is_empty() {
131 out.push(' ');
132 }
133
134 out.push_str(self.stderr.trim());
135 }
136
137 out
138 }
139}
140
141api_struct!(
142 pub struct SendRequestInput {
144 pub url: String,
146 }
147);
148
149impl SendRequestInput {
150 pub fn new(url: impl AsRef<str>) -> Self {
152 Self {
153 url: url.as_ref().to_owned(),
154 }
155 }
156}
157
158impl From<&str> for SendRequestInput {
159 fn from(url: &str) -> Self {
160 SendRequestInput::new(url)
161 }
162}
163
164impl From<String> for SendRequestInput {
165 fn from(url: String) -> Self {
166 SendRequestInput::new(url)
167 }
168}
169
170api_struct!(
171 pub struct SendRequestOutput {
173 pub body: Vec<u8>,
174 pub body_length: u64,
175 pub body_offset: u64,
176 pub status: u16,
177 }
178);
179
180impl SendRequestOutput {
181 pub fn json<T: DeserializeOwned>(self) -> AnyResult<T> {
183 Ok(serde_json::from_slice(&self.body)?)
184 }
185
186 pub fn text(self) -> AnyResult<String> {
188 Ok(String::from_utf8(self.body)?)
189 }
190}