made the code so much more readable

This commit is contained in:
Emma Tebibyte 2023-02-25 21:00:36 -05:00
parent 35401c4bbc
commit 7157c70b1f
5 changed files with 364 additions and 124 deletions

View File

@ -1,10 +0,0 @@
[unstable]
build-std = [ "std", "panic_abort" ]
build-std-features = [ "panic_immediate_abort" ]
[profile.release]
strip = true # strip symbols from the binary
opt-level = "z" # optimize for size
lto = true # link time optimization
codegen-units = 1 # decrease parallelization
panic = "abort"

217
Cargo.lock generated
View File

@ -3,16 +3,83 @@
version = 3
[[package]]
name = "exit-no-std"
version = "0.1.3"
name = "bindgen"
version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a608ccc67fac78c1916aa88ad75d6f6a3e353521844abce906c22a45d161d99"
checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885"
dependencies = [
"libc",
"pc-ints",
"winapi",
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.138"
@ -20,10 +87,96 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "pc-ints"
version = "0.1.4"
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422b0cc3a966f6e0987d2f948c234585bd917a1f16df1470e60c56ad6de2c085"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "serde"
@ -31,12 +184,29 @@ version = "1.0.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tomcat"
version = "0.0.1"
dependencies = [
"exit-no-std",
"toml",
"yacexits",
]
[[package]]
@ -48,6 +218,23 @@ dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -69,3 +256,13 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yacexits"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3afbe270dff95fe94b3a55c7e2dce91457a89b2b0dc6013814bba9806d099be"
dependencies = [
"bindgen",
"libc",
]

View File

@ -6,5 +6,5 @@ license = "AGPL-3.0-or-later"
authors = [ "Emma Tebibyte <emma@tebibyte.media>" ]
[dependencies]
exit-no-std = "0.1.3"
toml = "0.5.9"
yacexits = "0.1.2"

View File

@ -1,2 +0,0 @@
[toolchain]
channel = "nightly"

View File

@ -1,12 +1,13 @@
// Copyright (c) 2022 Emma Tebibyte
// SPDX-License-Identifier: AGPL-3.0-or-later
/* Tomcat is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
/*
* Copyright (c) 2022 Emma Tebibyte
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Tomcat is distributed in the hope that it will be useful, but WITHOUT
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
@ -15,119 +16,173 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use exit_no_std::exit;
use std::str::FromStr;
use std::{
env,
fs::File,
io::{
Read,
stdin,
},
iter::Peekable,
path::Path,
str::FromStr,
};
use toml::Value;
use yacexits::*;
fn parse_toml(
mut root: Value,
mut tabkey: Peekable<std::slice::Iter<'_, &str>>,
index: Option<usize>,
) -> Result<String, (String, u32)> {
let mut out = String::new();
while let Some(item) = tabkey.next() {
let value = match root.get(item) {
Some(val) => val,
None => {
return Err((format!("{}: No such table or key.", item), EX_DATAERR));
},
};
match value {
Value::Table(table) => {
match tabkey.peek() {
Some(_) => {
root = toml::Value::Table(table.to_owned());
continue;
},
None => {}, // out.push_str(table.as_str()),
};
},
_ => {
match tabkey.peek() {
Some(_) => {
return Err((format!("{}: Not a table.", item), EX_DATAERR));
},
None => {},
};
},
};
match value {
// TODO: Implement other type parsing
Value::Array(array) => {
let element: String;
match index {
Some(i) => {
element = match array.get(i) {
Some(element) => {
match element.as_str() {
Some(val) => val.to_owned(),
None => {
return Err((
format!("{:?}: No value at given key.", index),
EX_DATAERR
));
},
}
},
None => {
return Err(
(format!("{:?}: No value at given index.", i), EX_DATAERR)
);
},
};
},
None => element = format!("{:?}", array),
};
out.push_str(&element);
},
Value::Boolean(_boolean) => {},
Value::Datetime(_datetime) => {},
Value::Float(_float) => {},
Value::Integer(_int) => {},
Value::String(string) => out.push_str(string.as_str()),
_ => return Err((format!("{:?}: No such key.", item), EX_DATAERR)),
};
}
Ok(out)
}
fn main() {
let mut arguments: Vec<String> = env::args().collect();
let argv0 = arguments.remove(0);
if arguments.is_empty() {
eprintln!("Usage: {} [table...].[value[index]] [file...]", argv0);
let argv: Vec<String> = env::args().collect();
if argv.len() <= 1 {
eprintln!("Usage: {} [table...].[value[index]] [file...]", argv[0]);
exit(64); // sysexits(3) EX_USAGE
}
let input = &arguments[1];
let mut content = String::new();
let input = match argv.get(2) {
Some(val) => val,
None => {
eprintln!("Usage: {} [table...].[value[index]] [file...]", argv[0]);
exit(EX_USAGE);
},
};
let mut content = Vec::new();
let file = Path::new(&input);
if file.is_file() {
File::open(file).unwrap().read_to_string(&mut content).unwrap();
} else { content = input.to_string(); }
let mut tabkey: Vec<&str> = arguments[0].split(".").collect();
if input == &"-" {
match stdin().lock().read_to_end(&mut content) {
Ok(_) => {},
Err(_) => {
eprintln!("{}: Could not read from standard input.", argv[0]);
exit(EX_OSERR);
},
};
} else {
match File::open(file).unwrap().read_to_end(&mut content) {
Ok(_) => {},
Err(_) => {
eprintln!("{}: {:?}: No such file or directory.", argv[0], file);
exit(EX_UNAVAILABLE);
},
};
}
let mut tabkey: Vec<&str> = argv[1].split(".").collect();
let mut indexvec = Vec::new();
let mut index: usize = 0;
let mut index: Option<usize> = None;
match tabkey.iter().skip(1).peekable().peek() {
Some(_) => {
indexvec = tabkey[1].split(&['[', ']'][..]).collect();
tabkey[1] = indexvec.remove(0);
if ! indexvec.is_empty() {
let istr = indexvec.remove(0);
match usize::from_str(istr) {
Ok(i) => index = i,
Err(_) => {
eprintln!("{}: {}: Cannot index by given value.", argv0, istr);
exit(64); // sysexits(3) EX_USAGE
},
};
}
},
None => {},
};
let mut root = content.parse::<Value>().unwrap();
let mut out = String::new();
let mut valiter = tabkey.iter().peekable();
while let Some(item) = valiter.next() {
match root.get(item) {
Some(value) => {
match value {
// TODO: Implement other type parsing
Value::Array(array) => {
match valiter.peek() {
Some(_) => {
eprintln!("{}: {}: Not a table.", argv0, item);
exit(65); // sysexits(3) EX_DATAERR
},
None => {
match array.get(index) {
Some(element) => {
match element.as_str() {
Some(val) => out.push_str(val),
None => {
eprintln!(
"{}: {:?}: No value at given index.", argv0, index
);
exit(65); // sysexits(3) EX_DATAERR
},
};
},
None => {
eprintln!(
"{}: {:?}: No value at given index.", argv0, index
);
exit(65); // sysexits(3) EX_DATAERR
},
};
},
};
},
Value::Boolean(_boolean) => {},
Value::Datetime(_datetime) => {},
Value::Float(_float) => {},
Value::Integer(_int) => {},
Value::String(string) => {
match valiter.peek() {
Some(_) => {
eprintln!("{}: {}: Not a table.", argv0, item);
exit(65); // sysexits(3) EX_DATAERR
},
None => out.push_str(string.as_str()),
};
},
Value::Table(table) => {
match valiter.peek() {
Some(_) => {
root = toml::Value::Table(table.to_owned());
},
None => {}, // out.push_str(table.as_str()),
};
},
};
},
None => {
eprintln!("{}: {}: No such table or key.", argv0, item);
exit(65); // sysexits(3) EX_DATAERR
if ! indexvec.is_empty() {
let istr = indexvec.remove(0);
match usize::from_str(istr) {
Ok(i) => index = Some(i),
Err(_) => {
eprintln!("{}: {}: Cannot index by given value.", argv[0], istr);
exit(EX_USAGE);
},
};
}
println!("{}", out);
let root = match String::from_utf8(content).unwrap().parse::<Value>() {
Ok(toml) => toml,
Err(_) => {
eprintln!("{}: Unable to parse TOML.", argv[0]);
exit(EX_DATAERR);
},
};
let valiter = tabkey.iter().peekable();
println!(
"{}",
match parse_toml(root, valiter, index) {
Ok(val) => val,
Err((err, code)) => {
eprintln!("{}: {}", argv[0], err);
exit(code);
},
},
);
}