warpgate_api/
host_funcs.rs1use crate::virtual_path::VirtualPath;
2use crate::{AnyResult, api_struct, api_unit_enum};
3use derive_setters::Setters;
4use rustc_hash::FxHashMap;
5use serde::de::DeserializeOwned;
6use std::path::PathBuf;
7
8api_unit_enum!(
9 pub enum HostLogTarget {
11 Stderr,
13
14 Stdout,
16
17 Error,
19
20 Warn,
22
23 Debug,
25
26 #[default]
28 Trace,
29 }
30);
31
32api_struct!(
33 #[derive(Setters)]
35 #[serde(default)]
36 pub struct HostLogInput {
37 pub data: FxHashMap<String, serde_json::Value>,
39
40 #[setters(into)]
42 pub message: String,
43
44 pub target: HostLogTarget,
46 }
47);
48
49impl HostLogInput {
50 pub fn new(message: impl AsRef<str>) -> Self {
52 Self {
53 message: message.as_ref().to_owned(),
54 ..Default::default()
55 }
56 }
57}
58
59impl From<&str> for HostLogInput {
60 fn from(message: &str) -> Self {
61 HostLogInput::new(message)
62 }
63}
64
65impl From<String> for HostLogInput {
66 fn from(message: String) -> Self {
67 HostLogInput::new(message)
68 }
69}
70
71api_struct!(
72 #[derive(Setters)]
74 #[serde(default)]
75 pub struct ExecCommandInput {
76 #[setters(into)]
79 pub command: String,
80
81 #[serde(skip_serializing_if = "Vec::is_empty")]
83 pub args: Vec<String>,
84
85 #[setters(strip_option)]
87 #[serde(alias = "working_dir", skip_serializing_if = "Option::is_none")]
88 pub cwd: Option<VirtualPath>,
89
90 #[serde(skip_serializing_if = "FxHashMap::is_empty")]
99 pub env: FxHashMap<String, String>,
100
101 #[serde(skip_serializing_if = "Vec::is_empty")]
104 pub paths: Vec<PathBuf>,
105
106 #[setters(skip)]
108 #[doc(hidden)]
109 pub set_executable: bool,
110
111 #[setters(into, strip_option)]
113 pub shell: Option<String>,
114
115 #[setters(bool)]
117 pub stream: bool,
118 }
119);
120
121impl ExecCommandInput {
122 pub fn new<C, I, V>(command: C, args: I) -> ExecCommandInput
124 where
125 C: AsRef<str>,
126 I: IntoIterator<Item = V>,
127 V: AsRef<str>,
128 {
129 let mut input = Self::pipe(command, args);
130 input.stream = true;
131 input
132 }
133
134 pub fn pipe<C, I, V>(command: C, args: I) -> ExecCommandInput
136 where
137 C: AsRef<str>,
138 I: IntoIterator<Item = V>,
139 V: AsRef<str>,
140 {
141 ExecCommandInput {
142 command: command.as_ref().to_string(),
143 args: args
144 .into_iter()
145 .map(|arg| arg.as_ref().to_owned())
146 .collect(),
147 ..Default::default()
148 }
149 }
150
151 pub fn inherit<C, I, V>(command: C, args: I) -> ExecCommandInput
153 where
154 C: AsRef<str>,
155 I: IntoIterator<Item = V>,
156 V: AsRef<str>,
157 {
158 Self::new(command, args)
159 }
160}
161
162api_struct!(
163 #[serde(default)]
165 pub struct ExecCommandOutput {
166 pub command: String,
168
169 pub exit_code: i32,
171
172 pub stderr: String,
174
175 pub stdout: String,
177
178 pub streamed: bool,
180 }
181);
182
183impl ExecCommandOutput {
184 pub fn get_output(&self) -> String {
186 let mut out = String::new();
187 out.push_str(self.stdout.trim());
188
189 if !self.stderr.is_empty() {
190 if !out.is_empty() {
191 out.push(' ');
192 }
193
194 out.push_str(self.stderr.trim());
195 }
196
197 out
198 }
199}
200
201api_struct!(
202 #[derive(Setters)]
204 pub struct SendRequestInput {
205 #[setters(into)]
207 pub url: String,
208
209 #[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
211 pub headers: FxHashMap<String, String>,
212 }
213);
214
215impl SendRequestInput {
216 pub fn new(url: impl AsRef<str>) -> Self {
218 Self {
219 url: url.as_ref().to_owned(),
220 ..Default::default()
221 }
222 }
223}
224
225impl From<&str> for SendRequestInput {
226 fn from(url: &str) -> Self {
227 SendRequestInput::new(url)
228 }
229}
230
231impl From<String> for SendRequestInput {
232 fn from(url: String) -> Self {
233 SendRequestInput::new(url)
234 }
235}
236
237api_struct!(
238 pub struct SendRequestOutput {
240 pub body: Vec<u8>,
243
244 pub body_length: u64,
246
247 pub body_offset: u64,
249
250 pub status: u16,
252 }
253);
254
255impl SendRequestOutput {
256 pub fn json<T: DeserializeOwned>(self) -> AnyResult<T> {
258 Ok(serde_json::from_slice(&self.body)?)
259 }
260
261 pub fn text(self) -> AnyResult<String> {
263 Ok(String::from_utf8(self.body)?)
264 }
265}