systemd_wake/
command.rs

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/// Non-runnable version of [`Command`] used for serialization.
12#[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/// Error type for CommandConfig.
79#[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}