1
2use std::ffi::OsString;
3use std::path::PathBuf;
4use std::process::Command;
5
6use serde::{Serialize,Deserialize};
7#[allow(unused_imports)]
8use tracing::{info,debug,warn,error,trace,Level};
9use thiserror::Error;
10
11#[derive(Serialize,Deserialize)]
13pub struct CommandConfig {
14 program: OsString,
15 dir: Option<PathBuf>,
16 env_vars: Vec<(OsString,Option<OsString>)>,
17 args: Vec<OsString>,
18}
19
20impl From<Command> for CommandConfig {
21 fn from(command: Command) -> Self {
22 let program = command.get_program().into();
23 let dir = command.get_current_dir().map(|path| path.to_path_buf());
24 let env_vars = command.get_envs().map(|(key, value)| {
25 (key.to_os_string(), value.map(|value| value.to_os_string()))
26 }).collect();
27 let args = command.get_args().map(|value| value.to_os_string()).collect();
28 CommandConfig {
29 program,
30 dir,
31 env_vars,
32 args,
33 }
34 }
35}
36
37impl From<CommandConfig> for Command {
38 fn from(config: CommandConfig) -> Self {
39 let mut command = Command::new(config.program);
40 command.args(config.args);
41 for (key, value) in config.env_vars {
42 match value {
43 Some(value) => {
44 command.env(key,value);
45 },
46 None => {
47 command.env_remove(key);
48 }
49 }
50 }
51 match config.dir {
52 Some(dir) => {
53 command.current_dir(dir);
54 }
55 None => {},
56 };
57 command
58 }
59}
60
61#[allow(missing_docs)]
62impl CommandConfig {
63 pub fn encode(command: Command) -> Result<String,CommandConfigError> {
64 let config: CommandConfig = command.into();
65 let json = serde_json::to_string(&config)?;
66 Ok(hex::encode(json))
67 }
68
69 pub fn decode(hexcode: impl AsRef<[u8]>) -> Result<Command,CommandConfigError> {
70 let bytes = hex::decode(hexcode)?;
71 let json = String::from_utf8(bytes)?;
72 let config: CommandConfig = serde_json::from_str(&json)?;
73 Ok(config.into())
74 }
75}
76
77
78#[derive(Error,Debug)]
80#[allow(missing_docs)]
81pub enum CommandConfigError {
82 #[error("json (de)serialization error")]
83 SerdeJson(#[from] serde_json::Error),
84 #[error("hex (de/en)coding error")]
85 Hex(#[from] hex::FromHexError),
86 #[error("utf8 parsing error")]
87 Utf8(#[from] std::string::FromUtf8Error),
88}