RON database manager
1mod args;
2use args::{CLIArgs, Command};
3use clap::Parser;
4use ron::error::Error;
5use ron::error::SpannedError;
6use ron::ser;
7use ron::ser::PrettyConfig;
8use std::{collections::HashMap, fs, io, path::PathBuf};
9
10/* === Types === */
11enum QueryError {
12 ParseError(String),
13 FileMissing(PathBuf),
14 KeyMissing(String),
15 IOError(io::Error),
16}
17
18impl From<SpannedError> for QueryError {
19 fn from(e: SpannedError) -> Self {
20 QueryError::ParseError(format!(
21 "Parse error at position: {}. In code: {}",
22 e.position, e.code
23 ))
24 }
25}
26
27impl From<Error> for QueryError {
28 fn from(e: Error) -> Self {
29 QueryError::ParseError(format!(
30 "Parse error: {}",
31 match e {
32 Error::Message(string) => string,
33 _ => "".to_string(),
34 }
35 ))
36 }
37}
38
39impl QueryError {
40 fn display(&self) {
41 match self {
42 QueryError::ParseError(string) => eprintln!("{string}"),
43 QueryError::FileMissing(path) => eprintln!("File missing: {}", path.display()),
44 QueryError::IOError(err) => eprintln!("{err}"),
45 QueryError::KeyMissing(key) => eprintln!("The following key was not found: {key}"),
46 }
47 }
48}
49
50type RonMap = HashMap<String, String>;
51
52/* === Functions === */
53
54#[warn(clippy::pedantic, clippy::unwrap_used, clippy::perf)]
55pub fn handle_query(config: PathBuf) {
56 match check_config(config.clone()) {
57 Ok(ron_map) => match query_resources(ron_map, config) {
58 Ok(string) => println!("{string}"),
59 Err(e) => e.display(),
60 },
61 Err(e) => e.display(),
62 }
63}
64
65#[warn(clippy::pedantic, clippy::unwrap_used, clippy::perf)]
66fn check_config(config: PathBuf) -> Result<RonMap, QueryError> {
67 match config.try_exists() {
68 Ok(exists) => {
69 if exists {
70 let contents =
71 fs::read_to_string(config).expect("Query exists and has proper permissions.");
72 Ok(ron::from_str(&contents)?)
73 } else {
74 Err(QueryError::FileMissing(config))
75 }
76 }
77 Err(e) => Err(QueryError::IOError(e)),
78 }
79}
80
81#[warn(clippy::pedantic, clippy::unwrap_used, clippy::perf)]
82fn query_resources(mut map: RonMap, config: PathBuf) -> Result<String, QueryError> {
83 let args = CLIArgs::parse();
84
85 match args.command {
86 Command::All => Ok(ser::to_string_pretty(&map, PrettyConfig::default())?),
87 Command::Get(key) => match map.get_key_value(&key.key) {
88 Some(entry) => Ok(entry.1.to_string()),
89 None => Err(QueryError::KeyMissing(key.key)),
90 },
91 Command::Set(key_val) => {
92 let key = key_val.key;
93 let value = key_val.value;
94 map.insert(key.clone(), value.clone());
95 let pretty = ser::to_string_pretty(&map, PrettyConfig::default())?;
96
97 match fs::write(config, pretty) {
98 Ok(()) => Ok(format!("\"{key}\": \"{value}\"")),
99 Err(e) => Err(QueryError::IOError(e)),
100 }
101 }
102 }
103}