pub mod cache;
pub mod check;
pub mod claim;
pub mod lookup;
pub mod resolve;
pub mod scan;
pub mod search;
pub mod verify;
use std::io::Read;
use aspero_core::{ProviderId, Usage};
use aspero_engine::EngineError;
use serde_json::Value;
use crate::args::Format;
use crate::exit::Exit;
#[derive(Debug)]
pub struct Failure {
pub exit: Exit,
pub message: String,
}
impl Failure {
pub fn usage(message: impl Into<String>) -> Self {
Failure {
exit: Exit::Usage,
message: message.into(),
}
}
}
impl From<EngineError> for Failure {
fn from(e: EngineError) -> Self {
Failure {
exit: Exit::from_category(e.category()),
message: e.to_string(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Out {
pub format: Format,
pub full: bool,
pub abstracts: bool,
}
pub fn read_stdin() -> Result<String, Failure> {
let mut buf = String::new();
std::io::stdin()
.read_to_string(&mut buf)
.map_err(|e| Failure::usage(format!("could not read stdin: {e}")))?;
Ok(buf)
}
pub fn shell_quote(s: &str) -> String {
let plain = |c: char| c.is_ascii_alphanumeric() || "-_./:=+,@%".contains(c);
if !s.is_empty() && s.chars().all(plain) {
s.to_owned()
} else {
format!("'{}'", s.replace('\'', r"'\''"))
}
}
pub fn print(value: &Value) {
println!(
"{}",
serde_json::to_string_pretty(value).expect("JSON values serialise")
);
}
pub fn merged(mut base: Value, extra: Value) -> Value {
if let (Value::Object(b), Value::Object(e)) = (&mut base, extra) {
b.extend(e);
}
base
}
pub fn print_line(value: &Value) {
println!("{value}");
}
pub fn merge_usage(totals: &mut Vec<(ProviderId, Usage)>, provider: &ProviderId, usage: Usage) {
match totals.iter_mut().find(|(p, _)| p == provider) {
Some((_, total)) => *total = total.then(usage),
None => totals.push((provider.clone(), usage)),
}
}