You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
2.7 KiB

3 years ago
use serde::de::DeserializeOwned;
use serde_json::{from_slice, Value};
use std::fmt::{Debug, Display};
use std::process::{Command, Output};
use u_lib::{conv::bytes_to_string, proc_output::ProcOutput, types::PanelResult};
const PANEL_BINARY: &str = "/u_panel";
pub struct Panel;
impl Panel {
fn run(args: &[&str]) -> Output {
Command::new(PANEL_BINARY).args(args).output().unwrap()
}
pub fn output_argv<T: DeserializeOwned>(argv: &[&str]) -> PanelResult<T> {
let result = Self::run(argv);
let output = ProcOutput::from_output(&result);
match from_slice(output.get_stdout()) {
Ok(r) => r,
Err(e) => {
eprintln!(
"Failed to decode panel response: ###'{}'###",
bytes_to_string(output.get_stdout())
);
panic!("{e}")
}
}
}
pub fn output<T: DeserializeOwned + Debug>(args: impl IntoArgs) -> PanelResult<T> {
eprintln!(">>> {PANEL_BINARY} {}", args.display());
let splitted = args.into_args();
let result = Self::output_argv(
splitted
.iter()
.map(|s| s.as_ref())
.collect::<Vec<&str>>()
.as_ref(),
);
match &result {
PanelResult::Ok(r) => eprintln!("+<< {r:?}"),
PanelResult::Err(e) => eprintln!("!<< {e:?}"),
}
result
}
fn status_is_ok<T: DeserializeOwned + Debug>(data: PanelResult<T>) -> T {
match data {
PanelResult::Ok(r) => r,
PanelResult::Err(e) => panic!("Panel failed: {e}"),
3 years ago
}
}
pub fn check_status(args: impl IntoArgs) {
let result: PanelResult<Value> = Self::output(args);
3 years ago
Self::status_is_ok(result);
}
pub fn check_output<T: DeserializeOwned + Debug>(args: impl IntoArgs) -> T {
let result = Self::output(args);
3 years ago
Self::status_is_ok(result)
}
}
pub trait IntoArgs {
fn into_args(self) -> Vec<String>;
fn display(&self) -> String;
}
impl IntoArgs for String {
fn into_args(self) -> Vec<String> {
<Self as AsRef<str>>::as_ref(&self).into_args()
}
fn display(&self) -> String {
self.clone()
}
}
impl IntoArgs for &str {
fn into_args(self) -> Vec<String> {
shlex::split(self.as_ref()).unwrap()
}
fn display(&self) -> String {
self.to_string()
}
}
impl<S, const N: usize> IntoArgs for [S; N]
where
S: Display,
{
fn into_args(self) -> Vec<String> {
self.into_iter().map(|s| s.to_string()).collect()
}
fn display(&self) -> String {
self.iter()
.map(|s| format!(r#""{s}""#))
.collect::<Vec<String>>()
.join(" ")
}
}