add ll and lu commands to show table sizes

This commit is contained in:
Alex 2021-11-04 10:11:15 +01:00
parent da95f014a2
commit 927a369036
No known key found for this signature in database
GPG Key ID: EDABF9711E244EB1
4 changed files with 72 additions and 22 deletions

7
Cargo.lock generated
View File

@ -195,6 +195,12 @@ dependencies = [
"itertools", "itertools",
] ]
[[package]]
name = "humansize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -425,6 +431,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"hexdump", "hexdump",
"humansize",
"rustyline", "rustyline",
"sled", "sled",
"structopt", "structopt",

View File

@ -14,3 +14,4 @@ structopt = { version = "0.3", default-features = false }
hexdump = "0.1" hexdump = "0.1"
utf-8 = "0.7" utf-8 = "0.7"
anyhow = "1.0" anyhow = "1.0"
humansize = "1.1"

1
rustfmt.toml Normal file
View File

@ -0,0 +1 @@
hard_tabs = true

View File

@ -1,8 +1,10 @@
use std::path::PathBuf;
use std::ops::Deref; use std::ops::Deref;
use std::path::PathBuf;
use anyhow::Result; use anyhow::Result;
use humansize::{file_size_opts, FileSize};
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use rustyline::Editor; use rustyline::Editor;
@ -14,7 +16,7 @@ use sled::IVec;
#[structopt(name = "sledcli")] #[structopt(name = "sledcli")]
struct Opt { struct Opt {
/// Path to Sled database /// Path to Sled database
#[structopt(name="path")] #[structopt(name = "path")]
path: PathBuf, path: PathBuf,
} }
@ -45,38 +47,45 @@ fn main() {
}; };
let mut readline = Editor::<()>::new(); let mut readline = Editor::<()>::new();
loop { loop {
let lineread = readline.readline(&format!("{}> ", try_string(&state.tree.name()))); let prefix = match state.displaymode {
match lineread { DisplayMode::HexDump => "hex",
Ok(line) => { DisplayMode::TryString => "str",
readline.add_history_entry(line.as_str()); DisplayMode::Mixed => "mix",
};
let prompt = format!("[{}] {}> ", prefix, try_string(&state.tree.name()));
let lineread = readline.readline(&prompt);
match lineread {
Ok(line) => {
readline.add_history_entry(line.as_str());
if let Err(e) = do_command(&line, &mut state) { if let Err(e) = do_command(&line, &mut state) {
println!("Error: {}", e); println!("Error: {}", e);
} }
}, }
Err(ReadlineError::Interrupted) => { Err(ReadlineError::Interrupted) => {
println!("^C"); println!("^C");
continue; continue;
}, }
Err(ReadlineError::Eof) => { Err(ReadlineError::Eof) => break,
break Err(err) => {
}, println!("Readline error: {:?}", err);
Err(err) => { break;
println!("Readline error: {:?}", err); }
break }
} }
}
}
} }
fn try_string(input: &sled::IVec) -> String { fn try_string(input: &sled::IVec) -> String {
let mut string = String::new(); let mut string = String::new();
utf8::LossyDecoder::new(|s| string.push_str(s)).feed(input); utf8::LossyDecoder::new(|s| string.push_str(s)).feed(input);
string string
} }
fn do_command(line: &str, state: &mut State) -> Result<()> { fn do_command(line: &str, state: &mut State) -> Result<()> {
let parts = line.split(' ').filter(|part| part.len() > 0).collect::<Vec<_>>(); let parts = line
.split(' ')
.filter(|part| part.len() > 0)
.collect::<Vec<_>>();
if parts.is_empty() { if parts.is_empty() {
return Ok(()); return Ok(());
} }
@ -89,8 +98,40 @@ fn do_command(line: &str, state: &mut State) -> Result<()> {
println!("{}", try_string(&name)); println!("{}", try_string(&name));
} }
} }
["ll"] => {
let mut names = state.db.tree_names();
names.sort();
for name in names {
let nent = state.db.open_tree(&name)?.len();
println!("{:8} {}", nent, try_string(&name));
}
}
["lu"] => {
let mut names = state.db.tree_names();
names.sort();
for name in names {
let tree = state.db.open_tree(&name)?;
let nent = tree.len();
let mut size = 0;
for ent in tree.iter() {
let (k, v) = ent?;
size += k.len() + v.len();
}
println!(
"{:8} {:>12} {}",
nent,
size.file_size(file_size_opts::CONVENTIONAL).unwrap(),
try_string(&name)
);
}
}
["cd", treename] => { ["cd", treename] => {
if state.db.tree_names().iter().any(|t| t == treename.as_bytes()) { if state
.db
.tree_names()
.iter()
.any(|t| t == treename.as_bytes())
{
state.tree = state.db.open_tree(treename.as_bytes())?; state.tree = state.db.open_tree(treename.as_bytes())?;
} else { } else {
println!("Tree {} does not exist", treename); println!("Tree {} does not exist", treename);