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.
115 lines
3.0 KiB
115 lines
3.0 KiB
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) |
|
.env("RUST_LOG", "u_lib=debug") |
|
.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); |
|
|
|
let stderr = output.get_stderr(); |
|
if !stderr.is_empty() { |
|
println!("\n{}\n", String::from_utf8_lossy(stderr)); |
|
} |
|
|
|
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}"), |
|
} |
|
} |
|
|
|
pub fn check_status(args: impl IntoArgs) { |
|
let result: PanelResult<Value> = Self::output(args); |
|
Self::status_is_ok(result); |
|
} |
|
|
|
pub fn check_output<T: DeserializeOwned + Debug>(args: impl IntoArgs) -> T { |
|
let result = Self::output(args); |
|
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_str().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(" ") |
|
} |
|
}
|
|
|