use humansize::{BINARY, FormatSizeOptions}; use log::debug; use prettytable::format::TableFormat; use regex::Regex; use std::collections::HashMap; use std::env; use rusqlite::Connection; use crate::db::Item; use crate::db::Meta; use crate::db::store_meta; use crate::digest_engine::DigestType; use crate::digest_engine::get_digest_type_meta; pub fn get_meta_from_env() -> HashMap { debug!("MAIN: Getting meta from KEEP_META_*"); let re = Regex::new(r"^KEEP_META_(.+)$").unwrap(); let mut meta_env: HashMap = HashMap::new(); for (key, value) in env::vars() { if let Some(meta_name_caps) = re.captures(key.as_str()) { let name = String::from(meta_name_caps.get(1).unwrap().as_str()); debug!("MAIN: Found meta: {}={}", name.clone(), value.clone()); meta_env.insert(name, value.clone()); } } meta_env } pub fn format_size_human_readable(size: u64) -> String { let options = FormatSizeOptions::from(BINARY).decimal_places(1); humansize::format_size(size, options) } pub fn format_size(size: u64, human_readable: bool) -> String { match human_readable { true => format_size_human_readable(size), false => size.to_string(), } } pub fn string_column(s: String, column_width: usize) -> String { if column_width > 0 { match s.char_indices().nth(column_width) { None => s.to_string(), Some((idx, _)) => s[..idx].to_string(), } } else { s.to_string() } } pub fn size_column(size: u64, human_readable: bool, column_width: usize) -> String { string_column(format_size(size, human_readable), column_width) } #[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString)] #[strum(ascii_case_insensitive)] pub enum ColumnType { Id, Time, Size, Compression, DigestType, DigestValue, FileSize, FilePath, Tags, Meta, } impl ColumnType { /// Returns a Result with error message if the string is not a valid ColumnType pub fn from_str(s: &str) -> anyhow::Result { Ok(Self::try_from(s)?) } } // impl TryFrom<&str> for ColumnType is already implemented by strum_macros // so we remove this conflicting implementation pub fn get_format_box_chars_no_border_line_separator() -> TableFormat { prettytable::format::FormatBuilder::new() .column_separator('│') .borders('│') .separators( &[prettytable::format::LinePosition::Top], prettytable::format::LineSeparator::new('─', '┬', '┌', '┐'), ) .separators( &[prettytable::format::LinePosition::Title], prettytable::format::LineSeparator::new('─', '┼', '├', '┤'), ) .separators( &[prettytable::format::LinePosition::Bottom], prettytable::format::LineSeparator::new('─', '┴', '└', '┘'), ) .padding(1, 1) .build() } pub fn store_item_digest_value( conn: &mut Connection, item: Item, digest_type: DigestType, digest_value: String, ) -> Result<(), rusqlite::Error> { // Save digest to meta let digest_meta_name = get_digest_type_meta(digest_type); let digest_meta = Meta { id: item.id.unwrap(), name: digest_meta_name, value: digest_value, }; store_meta(conn, digest_meta)?; Ok(()) }