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;
6
7api_unit_enum!(
8 pub enum HostLogTarget {
10 Stderr,
12 Stdout,
13 Debug,
15 Error,
16 Trace,
17 Warn,
18 #[default]
19 Tracing,
20 }
21);
22
23api_struct!(
24 #[derive(Setters)]
26 #[serde(default)]
27 pub struct HostLogInput {
28 pub data: FxHashMap<String, serde_json::Value>,
29
30 #[setters(into)]
31 pub message: String,
32
33 pub target: HostLogTarget,
34 }
35);
36
37impl HostLogInput {
38 pub fn new(message: impl AsRef<str>) -> Self {
40 Self {
41 message: message.as_ref().to_owned(),
42 ..Default::default()
43 }
44 }
45}
46
47impl From<&str> for HostLogInput {
48 fn from(message: &str) -> Self {
49 HostLogInput::new(message)
50 }
51}
52
53impl From<String> for HostLogInput {
54 fn from(message: String) -> Self {
55 HostLogInput::new(message)
56 }
57}
58
59api_struct!(
60 #[derive(Setters)]
62 #[serde(default)]
63 pub struct ExecCommandInput {
64 #[setters(into)]
67 pub command: String,
68
69 #[serde(skip_serializing_if = "Vec::is_empty")]
71 pub args: Vec<String>,
72
73 #[serde(skip_serializing_if = "FxHashMap::is_empty")]
82 pub env: FxHashMap<String, String>,
83
84 #[setters(skip)]
86 #[doc(hidden)]
87 pub set_executable: bool,
88
89 #[setters(into, strip_option)]
92 pub shell: Option<String>,
93
94 #[setters(bool)]
96 pub stream: bool,
97
98 #[setters(strip_option)]
100 #[serde(alias = "working_dir", skip_serializing_if = "Option::is_none")]
101 pub cwd: Option<VirtualPath>,
102 }
103);
104
105impl ExecCommandInput {
106 pub fn new<C, I, V>(command: C, args: I) -> ExecCommandInput
108 where
109 C: AsRef<str>,
110 I: IntoIterator<Item = V>,
111 V: AsRef<str>,
112 {
113 let mut input = Self::pipe(command, args);
114 input.stream = true;
115 input
116 }
117
118 pub fn pipe<C, I, V>(command: C, args: I) -> ExecCommandInput
120 where
121 C: AsRef<str>,
122 I: IntoIterator<Item = V>,
123 V: AsRef<str>,
124 {
125 ExecCommandInput {
126 command: command.as_ref().to_string(),
127 args: args.into_iter().map(|a| a.as_ref().to_owned()).collect(),
128 ..ExecCommandInput::default()
129 }
130 }
131
132 pub fn inherit<C, I, V>(command: C, args: I) -> ExecCommandInput
134 where
135 C: AsRef<str>,
136 I: IntoIterator<Item = V>,
137 V: AsRef<str>,
138 {
139 Self::new(command, args)
140 }
141}
142
143api_struct!(
144 #[serde(default)]
146 pub struct ExecCommandOutput {
147 pub command: String,
148 pub exit_code: i32,
149 pub stderr: String,
150 pub stdout: String,
151 }
152);
153
154impl ExecCommandOutput {
155 pub fn get_output(&self) -> String {
156 let mut out = String::new();
157 out.push_str(self.stdout.trim());
158
159 if !self.stderr.is_empty() {
160 if !out.is_empty() {
161 out.push(' ');
162 }
163
164 out.push_str(self.stderr.trim());
165 }
166
167 out
168 }
169}
170
171api_struct!(
172 #[derive(Setters)]
174 pub struct SendRequestInput {
175 #[setters(into)]
177 pub url: String,
178
179 #[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
181 pub headers: FxHashMap<String, String>,
182 }
183);
184
185impl SendRequestInput {
186 pub fn new(url: impl AsRef<str>) -> Self {
188 Self {
189 url: url.as_ref().to_owned(),
190 ..Default::default()
191 }
192 }
193}
194
195impl From<&str> for SendRequestInput {
196 fn from(url: &str) -> Self {
197 SendRequestInput::new(url)
198 }
199}
200
201impl From<String> for SendRequestInput {
202 fn from(url: String) -> Self {
203 SendRequestInput::new(url)
204 }
205}
206
207api_struct!(
208 pub struct SendRequestOutput {
210 pub body: Vec<u8>,
211 pub body_length: u64,
212 pub body_offset: u64,
213 pub status: u16,
214 }
215);
216
217impl SendRequestOutput {
218 pub fn json<T: DeserializeOwned>(self) -> AnyResult<T> {
220 Ok(serde_json::from_slice(&self.body)?)
221 }
222
223 pub fn text(self) -> AnyResult<String> {
225 Ok(String::from_utf8(self.body)?)
226 }
227}