mirror of
https://github.com/jht5945/rust_util.git
synced 2026-01-14 00:00:04 +08:00
Compare commits
20 Commits
8d4b8aa1e0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
254585bb90
|
|||
|
e13b2a3db4
|
|||
|
e2b258ca09
|
|||
|
4b596db8de
|
|||
|
af4b91d4e9
|
|||
|
c1ef4c4b53
|
|||
|
ca597cf0d6
|
|||
|
c56b7deaaf
|
|||
|
16e859c785
|
|||
|
29519b3a43
|
|||
|
32a2b529fd
|
|||
|
5cdad86ea6
|
|||
| 7e5bec260f | |||
|
30e9384505
|
|||
|
80ff02e6b8
|
|||
| 7aa8f4c43c | |||
| efbbf4261a | |||
| 568a2173d5 | |||
| c69cb1c35b | |||
| 019a410750 |
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rust_util"
|
name = "rust_util"
|
||||||
version = "0.6.37"
|
version = "0.6.51"
|
||||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Hatter's Rust Util"
|
description = "Hatter's Rust Util"
|
||||||
|
|||||||
1
_config.yml
Normal file
1
_config.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-cayman
|
||||||
@@ -13,6 +13,12 @@ impl Command for TestCommand {
|
|||||||
|
|
||||||
fn run(&self, _arg_matches: &ArgMatches, _: &ArgMatches) -> CommandError {
|
fn run(&self, _arg_matches: &ArgMatches, _: &ArgMatches) -> CommandError {
|
||||||
println!("hello test!");
|
println!("hello test!");
|
||||||
|
let a: Option<String> = None;
|
||||||
|
let b = move || -> rust_util::XResult<String> {
|
||||||
|
Ok(rust_util::opt_value_result!(a, "test: {}", 1))
|
||||||
|
};
|
||||||
|
let c = b();
|
||||||
|
println!("{:?}", c);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
#[macro_use] extern crate rust_util;
|
#[macro_use] extern crate rust_util;
|
||||||
|
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
use std::thread;
|
||||||
use rust_util::{XResult, SimpleError};
|
use rust_util::{XResult, SimpleError};
|
||||||
|
use rust_util::util_msg::{set_logger_sender, set_logger_std_out};
|
||||||
|
|
||||||
// cargo run --example log
|
// cargo run --example log
|
||||||
fn main() -> XResult<()> {
|
fn main() -> XResult<()> {
|
||||||
|
let (sender, receiver) = channel::<String>();
|
||||||
|
set_logger_sender(sender);
|
||||||
|
|
||||||
|
let _t = thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let msg = receiver.recv();
|
||||||
|
println!("[RECV]: {:?}", msg)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
std::env::set_var("LOGGER_LEVEL", "*");
|
std::env::set_var("LOGGER_LEVEL", "*");
|
||||||
println!(r##"env LOGGER_LEVEL set to:
|
println!(r##"env LOGGER_LEVEL set to:
|
||||||
debug or *
|
debug or *
|
||||||
@@ -20,6 +33,11 @@ error or ^"##);
|
|||||||
|
|
||||||
println!("{:?}", test_opt_result());
|
println!("{:?}", test_opt_result());
|
||||||
|
|
||||||
|
set_logger_std_out(false);
|
||||||
|
information!("Std err!");
|
||||||
|
warning!("Std err!");
|
||||||
|
set_logger_std_out(true);
|
||||||
|
|
||||||
simple_error!("helloworld {}", 1)
|
simple_error!("helloworld {}", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
src/lib.rs
19
src/lib.rs
@@ -40,6 +40,12 @@ pub mod util_runtime;
|
|||||||
#[macro_export] macro_rules! failure {
|
#[macro_export] macro_rules! failure {
|
||||||
($($arg:tt)+) => ( rust_util::util_msg::print_error(&format!($($arg)+)); )
|
($($arg:tt)+) => ( rust_util::util_msg::print_error(&format!($($arg)+)); )
|
||||||
}
|
}
|
||||||
|
#[macro_export] macro_rules! println_ex {
|
||||||
|
($($arg:tt)+) => ( rust_util::util_msg::print_ex(&format!($($arg)+), true); )
|
||||||
|
}
|
||||||
|
#[macro_export] macro_rules! print_ex {
|
||||||
|
($($arg:tt)+) => ( rust_util::util_msg::print_ex(&format!($($arg)+), false); )
|
||||||
|
}
|
||||||
#[macro_export] macro_rules! debugging {
|
#[macro_export] macro_rules! debugging {
|
||||||
($($arg:tt)+) => ( rust_util::util_msg::when(rust_util::util_msg::MessageType::DEBUG, || {
|
($($arg:tt)+) => ( rust_util::util_msg::when(rust_util::util_msg::MessageType::DEBUG, || {
|
||||||
rust_util::util_msg::print_debug(&format!($($arg)+))
|
rust_util::util_msg::print_debug(&format!($($arg)+))
|
||||||
@@ -48,7 +54,7 @@ pub mod util_runtime;
|
|||||||
#[macro_export] macro_rules! failure_and_exit {
|
#[macro_export] macro_rules! failure_and_exit {
|
||||||
($($arg:tt)+) => ( {
|
($($arg:tt)+) => ( {
|
||||||
rust_util::util_msg::print_error(&format!($($arg)+));
|
rust_util::util_msg::print_error(&format!($($arg)+));
|
||||||
rsut_util::util_runtime::register_callback();
|
rust_util::util_runtime::invoke_callbacks();
|
||||||
std::process::exit(-1);
|
std::process::exit(-1);
|
||||||
} )
|
} )
|
||||||
}
|
}
|
||||||
@@ -66,6 +72,17 @@ pub fn new_box_ioerror(m: &str) -> Box<dyn Error> {
|
|||||||
Box::new(IoError::new(ErrorKind::Other, m))
|
Box::new(IoError::new(ErrorKind::Other, m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! opt_value_result {
|
||||||
|
($ex: expr, $($arg:tt)+) => (
|
||||||
|
match $ex {
|
||||||
|
Some(o) => o,
|
||||||
|
None => return Err(rust_util::SimpleError::new(
|
||||||
|
format!("{}, file: {}, line: {}", format!($($arg)+), file!(), line!())
|
||||||
|
).into()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! opt_result {
|
#[macro_export] macro_rules! opt_result {
|
||||||
($ex: expr, $($arg:tt)+) => (
|
($ex: expr, $($arg:tt)+) => (
|
||||||
match $ex {
|
match $ex {
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
pub fn is_env_on(var: &str) -> bool {
|
pub fn is_env_on(var: &str) -> bool {
|
||||||
env::var(var).ok().map(|val| is_on(&val)).unwrap_or(false)
|
env_var(var).map(|val| is_on(&val)).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_env_off(var: &str) -> bool {
|
pub fn is_env_off(var: &str) -> bool {
|
||||||
env::var(var).ok().map(|val| is_off(&val)).unwrap_or(false)
|
env_var(var).map(|val| is_off(&val)).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_on(val: &str) -> bool {
|
pub fn is_on(val: &str) -> bool {
|
||||||
let lower_val = val.to_lowercase();
|
let lower_val = val.to_lowercase();
|
||||||
vec!["true", "yes", "1"].iter().any(|x| *x == lower_val)
|
["true", "yes", "1"].iter().any(|x| *x == lower_val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_off(val: &str) -> bool {
|
pub fn is_off(val: &str) -> bool {
|
||||||
let lower_val = val.to_lowercase();
|
let lower_val = val.to_lowercase();
|
||||||
vec!["false", "no", "0"].iter().any(|x| *x == lower_val)
|
["false", "no", "0"].iter().any(|x| *x == lower_val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn env_var(var: &str) -> Option<String> {
|
||||||
|
let var_from_env = env::var(var).ok();
|
||||||
|
if var_from_env.is_some() {
|
||||||
|
return var_from_env;
|
||||||
|
}
|
||||||
|
let var_content = crate::util_file::read_file_content(&format!("~/.config/envs/{}", var));
|
||||||
|
if let Ok(var_content) = var_content {
|
||||||
|
return Some(var_content.trim().to_string());
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ pub struct JoinFilesReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn open_file_as_lines(f: &str) -> XResult<Lines<BufReader<File>>> {
|
fn open_file_as_lines(f: &str) -> XResult<Lines<BufReader<File>>> {
|
||||||
let f = File::open(&f)?;
|
let f = File::open(f)?;
|
||||||
let br = BufReader::new(f);
|
let br = BufReader::new(f);
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
Ok(br.lines())
|
Ok(br.lines())
|
||||||
@@ -191,7 +191,7 @@ fn walk_dir_with_depth_check<FError, FProcess, FFilter>(depth: &mut u32, dir: &P
|
|||||||
let read_dir = match dir.read_dir() {
|
let read_dir = match dir.read_dir() {
|
||||||
Ok(rd) => rd,
|
Ok(rd) => rd,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
func_walk_error(&dir, Box::new(err));
|
func_walk_error(dir, Box::new(err));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -199,7 +199,7 @@ fn walk_dir_with_depth_check<FError, FProcess, FFilter>(depth: &mut u32, dir: &P
|
|||||||
let dir_entry = match dir_entry_item {
|
let dir_entry = match dir_entry_item {
|
||||||
Ok(item) => item,
|
Ok(item) => item,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
func_walk_error(&dir, Box::new(err));
|
func_walk_error(dir, Box::new(err));
|
||||||
continue; // Ok?
|
continue; // Ok?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -207,11 +207,11 @@ fn walk_dir_with_depth_check<FError, FProcess, FFilter>(depth: &mut u32, dir: &P
|
|||||||
let path_buf = dir_entry.path();
|
let path_buf = dir_entry.path();
|
||||||
let sub_dir = path_buf.as_path();
|
let sub_dir = path_buf.as_path();
|
||||||
if sub_dir.is_file() {
|
if sub_dir.is_file() {
|
||||||
func_process_file(&sub_dir);
|
func_process_file(sub_dir);
|
||||||
} else if sub_dir.is_dir() && func_filter_dir(&sub_dir) {
|
} else if sub_dir.is_dir() && func_filter_dir(sub_dir) {
|
||||||
*depth += 1;
|
*depth += 1;
|
||||||
if let Err(err) = walk_dir_with_depth_check(depth, &sub_dir, func_walk_error, func_process_file, func_filter_dir) {
|
if let Err(err) = walk_dir_with_depth_check(depth, sub_dir, func_walk_error, func_process_file, func_filter_dir) {
|
||||||
func_walk_error(&sub_dir, err);
|
func_walk_error(sub_dir, err);
|
||||||
}
|
}
|
||||||
*depth -= 1;
|
*depth -= 1;
|
||||||
} // should process else ? not file, dir
|
} // should process else ? not file, dir
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use crate::{XResult, util_msg, util_cmd};
|
|
||||||
|
use crate::{util_cmd, util_msg, XResult};
|
||||||
|
|
||||||
const LANG: &str = "LANG";
|
const LANG: &str = "LANG";
|
||||||
const EN_US: &str = "en_US";
|
const EN_US: &str = "en_US";
|
||||||
@@ -75,7 +76,7 @@ pub fn git_add(working_dir: Option<&str>, files: &[String]) {
|
|||||||
let mut cmd = new_git_command(working_dir);
|
let mut cmd = new_git_command(working_dir);
|
||||||
cmd.arg("add");
|
cmd.arg("add");
|
||||||
for f in files {
|
for f in files {
|
||||||
cmd.arg(&f);
|
cmd.arg(f);
|
||||||
}
|
}
|
||||||
util_msg::print_info(&format!("Exec: {:?}", cmd));
|
util_msg::print_info(&format!("Exec: {:?}", cmd));
|
||||||
if let Err(e) = util_cmd::run_command_and_wait(&mut cmd) {
|
if let Err(e) = util_cmd::run_command_and_wait(&mut cmd) {
|
||||||
@@ -89,7 +90,7 @@ pub fn git_commit(working_dir: Option<&str>, message: &str, files: &[String]) {
|
|||||||
cmd.arg("-m");
|
cmd.arg("-m");
|
||||||
cmd.arg(message);
|
cmd.arg(message);
|
||||||
for f in files {
|
for f in files {
|
||||||
cmd.arg(&f);
|
cmd.arg(f);
|
||||||
}
|
}
|
||||||
util_msg::print_info(&format!("Exec: {:?}", cmd));
|
util_msg::print_info(&format!("Exec: {:?}", cmd));
|
||||||
if let Err(e) = util_cmd::run_command_and_wait(&mut cmd) {
|
if let Err(e) = util_cmd::run_command_and_wait(&mut cmd) {
|
||||||
@@ -100,19 +101,19 @@ pub fn git_commit(working_dir: Option<&str>, message: &str, files: &[String]) {
|
|||||||
fn parse_git_status_change(git_status: &str) -> XResult<GitStatusChange> {
|
fn parse_git_status_change(git_status: &str) -> XResult<GitStatusChange> {
|
||||||
let mut git_status_change: GitStatusChange = Default::default();
|
let mut git_status_change: GitStatusChange = Default::default();
|
||||||
for ln in git_status.lines() {
|
for ln in git_status.lines() {
|
||||||
if ln.starts_with("\t") {
|
if ln.starts_with('\t') {
|
||||||
let ln = ln.trim();
|
let ln = ln.trim();
|
||||||
if ln.starts_with("new file:") {
|
if let Some(new_file) = ln.strip_prefix("new file:") {
|
||||||
let f = ln["new file:".len()..].trim();
|
let f = new_file.trim();
|
||||||
git_status_change.added.push(f.to_owned());
|
git_status_change.added.push(f.to_owned());
|
||||||
} else if ln.starts_with("deleted:") {
|
} else if let Some(deleted) = ln.strip_prefix("deleted:") {
|
||||||
let f = ln["deleted:".len()..].trim();
|
let f = deleted.trim();
|
||||||
git_status_change.deleted.push(f.to_owned());
|
git_status_change.deleted.push(f.to_owned());
|
||||||
} else if ln.starts_with("modified:") {
|
} else if let Some(modified) = ln.strip_prefix("modified:") {
|
||||||
let f = ln["modified:".len()..].trim();
|
let f = modified.trim();
|
||||||
git_status_change.modified.push(f.to_owned());
|
git_status_change.modified.push(f.to_owned());
|
||||||
} else if ln.starts_with("renamed:") {
|
} else if let Some(renamed) = ln.strip_prefix("renamed:") {
|
||||||
let f = ln["renamed:".len()..].trim();
|
let f = renamed.trim();
|
||||||
let mut fs = f.split("->");
|
let mut fs = f.split("->");
|
||||||
let fa = fs.next();
|
let fa = fs.next();
|
||||||
let fb = fs.next();
|
let fb = fs.next();
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use std::io::{self, Write, ErrorKind, prelude::*};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::time::{SystemTime, Duration};
|
use std::io::{self, ErrorKind, prelude::*, Write};
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
use crate::{SimpleError, XResult};
|
use crate::{SimpleError, XResult};
|
||||||
use crate::util_size;
|
|
||||||
use crate::util_msg;
|
|
||||||
use crate::util_file;
|
use crate::util_file;
|
||||||
|
use crate::util_msg;
|
||||||
|
use crate::util_size;
|
||||||
|
|
||||||
pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
|
pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ pub fn get_read_stdin_or_file(file: &str) -> XResult<Box<dyn Read>> {
|
|||||||
if file.is_empty() {
|
if file.is_empty() {
|
||||||
Ok(Box::new(io::stdin()))
|
Ok(Box::new(io::stdin()))
|
||||||
} else {
|
} else {
|
||||||
match File::open(&util_file::resolve_file_path(file)) {
|
match File::open(util_file::resolve_file_path(file)) {
|
||||||
Ok(f) => Ok(Box::new(f)),
|
Ok(f) => Ok(Box::new(f)),
|
||||||
Err(err) => Err(SimpleError::new(format!("Open file {}, erorr: {}", file, err)).into()),
|
Err(err) => Err(SimpleError::new(format!("Open file {}, erorr: {}", file, err)).into()),
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ pub fn print_status_last_line(head: &str, total: i64, written: i64, print_status
|
|||||||
}
|
}
|
||||||
let cost_as_secs = cost.as_secs();
|
let cost_as_secs = cost.as_secs();
|
||||||
if cost_as_secs > 0 {
|
if cost_as_secs > 0 {
|
||||||
download_speed = format!("{}/s", util_size::get_display_size((written / (cost_as_secs as i64)) as i64));
|
download_speed = format!("{}/s", util_size::get_display_size(written / (cost_as_secs as i64)));
|
||||||
}
|
}
|
||||||
if total > 0 {
|
if total > 0 {
|
||||||
util_msg::print_lastline(&format!("{}, Total: {}, Finished: {}, Speed: {}",
|
util_msg::print_lastline(&format!("{}, Total: {}, Finished: {}, Speed: {}",
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IS_ATTY: bool = is_atty();
|
pub static ref IS_ATTY: bool = is_atty();
|
||||||
static ref LOGGER_LEVEL: MessageType = get_logger_level();
|
static ref LOGGER_LEVEL: MessageType = get_logger_level();
|
||||||
|
static ref LOGGER_SENDER: Arc<RwLock<Option<Sender<String>>>> = Arc::new(RwLock::new(None));
|
||||||
|
static ref LOGGER_TO_STDOUT: Arc<RwLock<bool>> = Arc::new(RwLock::new(true));
|
||||||
static ref PRINT_MESSAGE_LOCK: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
|
static ref PRINT_MESSAGE_LOCK: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_logger_sender(sender: Sender<String>) {
|
||||||
|
let mut logger_sender_opt = LOGGER_SENDER.write().unwrap();
|
||||||
|
logger_sender_opt.replace(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_logger_std_out(is_std_out: bool) {
|
||||||
|
let mut std_out = LOGGER_TO_STDOUT.write().unwrap();
|
||||||
|
*std_out = is_std_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_logger_std_out() -> bool {
|
||||||
|
*LOGGER_TO_STDOUT.read().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum MessageType { DEBUG, INFO, OK, WARN, ERROR }
|
pub enum MessageType { DEBUG, INFO, OK, WARN, ERROR }
|
||||||
@@ -37,7 +54,7 @@ pub fn get_logger_level() -> MessageType {
|
|||||||
_ => {
|
_ => {
|
||||||
print_message_ex(Some(term::color::YELLOW), "[WARN ]", &format!("Unknown logger level: {}, set to default INFO", logger_level));
|
print_message_ex(Some(term::color::YELLOW), "[WARN ]", &format!("Unknown logger level: {}, set to default INFO", logger_level));
|
||||||
MessageType::INFO
|
MessageType::INFO
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MessageType::INFO
|
MessageType::INFO
|
||||||
@@ -45,11 +62,12 @@ pub fn get_logger_level() -> MessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_atty() -> bool {
|
pub fn is_atty() -> bool {
|
||||||
let stdout_fileno = unsafe { libc::isatty(libc::STDOUT_FILENO as i32) };
|
let stdout_fileno = unsafe { libc::isatty(libc::STDOUT_FILENO) };
|
||||||
stdout_fileno != 0
|
stdout_fileno != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_color(color: Option<term::color::Color>, is_bold: bool, m: &str) {
|
pub fn print_color(is_std_out: bool, color: Option<term::color::Color>, is_bold: bool, m: &str) {
|
||||||
|
if is_std_out {
|
||||||
match term::stdout() {
|
match term::stdout() {
|
||||||
Some(mut t) => {
|
Some(mut t) => {
|
||||||
if *IS_ATTY {
|
if *IS_ATTY {
|
||||||
@@ -64,27 +82,79 @@ pub fn print_color(color: Option<term::color::Color>, is_bold: bool, m: &str) {
|
|||||||
} else {
|
} else {
|
||||||
write!(t, "{}", m).ok();
|
write!(t, "{}", m).ok();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => print!("{}", m),
|
None => print!("{}", m),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
match term::stderr() {
|
||||||
|
Some(mut t) => {
|
||||||
|
if *IS_ATTY {
|
||||||
|
if let Some(c) = color {
|
||||||
|
t.fg(c).ok();
|
||||||
|
}
|
||||||
|
if is_bold {
|
||||||
|
t.attr(term::Attr::Bold).ok();
|
||||||
|
}
|
||||||
|
write!(t, "{}", m).ok();
|
||||||
|
t.reset().ok();
|
||||||
|
} else {
|
||||||
|
write!(t, "{}", m).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => eprint!("{}", m),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_color_and_flush(color: Option<term::color::Color>, is_bold: bool, m: &str) {
|
pub fn print_color_and_flush(color: Option<term::color::Color>, is_bold: bool, m: &str) {
|
||||||
print_color(color, is_bold, m);
|
print_color(true, color, is_bold, m);
|
||||||
flush_stdout();
|
flush_stdout();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_message_ex(color: Option<term::color::Color>, h: &str, message: &str) {
|
pub fn print_message_ex(color: Option<term::color::Color>, h: &str, message: &str) {
|
||||||
|
{
|
||||||
|
let logger_sender_opt = LOGGER_SENDER.read().unwrap();
|
||||||
|
if let Some(logger_sender) = &*logger_sender_opt {
|
||||||
|
logger_sender.send(format!("{} {}", h, message)).ok();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let is_std_out = get_logger_std_out();
|
||||||
let mut lock = PRINT_MESSAGE_LOCK.lock().unwrap();
|
let mut lock = PRINT_MESSAGE_LOCK.lock().unwrap();
|
||||||
print_color(color, true, h);
|
print_color(is_std_out, color, true, h);
|
||||||
|
if is_std_out {
|
||||||
println!(" {}", message);
|
println!(" {}", message);
|
||||||
|
} else {
|
||||||
|
eprintln!(" {}", message)
|
||||||
|
}
|
||||||
*lock = ();
|
*lock = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_ex(message: &str, new_line: bool) {
|
||||||
|
if get_logger_std_out() {
|
||||||
|
if new_line {
|
||||||
|
println!("{}", message)
|
||||||
|
} else {
|
||||||
|
print!("{}", message)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::collapsible_else_if)]
|
||||||
|
if new_line {
|
||||||
|
eprintln!("{}", message)
|
||||||
|
} else {
|
||||||
|
eprint!("{}", message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_ok(message: &str) { print_message(MessageType::OK, message); }
|
pub fn print_ok(message: &str) { print_message(MessageType::OK, message); }
|
||||||
|
|
||||||
pub fn print_warn(message: &str) { print_message(MessageType::WARN, message); }
|
pub fn print_warn(message: &str) { print_message(MessageType::WARN, message); }
|
||||||
|
|
||||||
pub fn print_error(message: &str) { print_message(MessageType::ERROR, message); }
|
pub fn print_error(message: &str) { print_message(MessageType::ERROR, message); }
|
||||||
|
|
||||||
pub fn print_info(message: &str) { print_message(MessageType::INFO, message); }
|
pub fn print_info(message: &str) { print_message(MessageType::INFO, message); }
|
||||||
|
|
||||||
pub fn print_debug(message: &str) { print_message(MessageType::DEBUG, message); }
|
pub fn print_debug(message: &str) { print_message(MessageType::DEBUG, message); }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -93,6 +163,10 @@ pub fn is_logger_level_enabled(mt: MessageType) -> bool {
|
|||||||
mt.get_u8_value() >= logger_level.get_u8_value()
|
mt.get_u8_value() >= logger_level.get_u8_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn when_debug<F>(f: F) where F: Fn() {
|
||||||
|
when(MessageType::DEBUG, f)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn when<F>(mt: MessageType, f: F) where F: Fn() {
|
pub fn when<F>(mt: MessageType, f: F) where F: Fn() {
|
||||||
if is_logger_level_enabled(mt) {
|
if is_logger_level_enabled(mt) {
|
||||||
f();
|
f();
|
||||||
@@ -151,10 +225,10 @@ pub fn get_term_width_message(message: &str, left: usize) -> String {
|
|||||||
return message.to_string();
|
return message.to_string();
|
||||||
}
|
}
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
s.push_str(&message[0..find_char_boundary(&message, w - 10 - 5 - left)]);
|
s.push_str(&message[0..find_char_boundary(message, w - 10 - 5 - left)]);
|
||||||
s.push_str("[...]");
|
s.push_str("[...]");
|
||||||
s.push_str(&message[find_char_boundary(&message, len - 10)..]);
|
s.push_str(&message[find_char_boundary(message, len - 10)..]);
|
||||||
s
|
s
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ pub struct IpAndIpMaskMatcher {
|
|||||||
ip_and_ip_mask_set: HashSet<u64>,
|
ip_and_ip_mask_set: HashSet<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for IpAndIpMaskMatcher {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IpAndIpMaskMatcher {
|
impl IpAndIpMaskMatcher {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
IpAndIpMaskMatcher {
|
IpAndIpMaskMatcher {
|
||||||
@@ -133,7 +139,7 @@ impl IpAddressMask {
|
|||||||
let socket_addr_v4_octets = socket_addr_v4.ip().octets();
|
let socket_addr_v4_octets = socket_addr_v4.ip().octets();
|
||||||
match self {
|
match self {
|
||||||
IpAddressMask::Ipv4(self_ipv4_octets, mask) => {
|
IpAddressMask::Ipv4(self_ipv4_octets, mask) => {
|
||||||
let self_ipv4_u32 = ipv4_to_u32(&self_ipv4_octets);
|
let self_ipv4_u32 = ipv4_to_u32(self_ipv4_octets);
|
||||||
let addr_ipv4_u32 = ipv4_to_u32(&socket_addr_v4_octets);
|
let addr_ipv4_u32 = ipv4_to_u32(&socket_addr_v4_octets);
|
||||||
let mask_u32 = ipv4_mask(*mask);
|
let mask_u32 = ipv4_mask(*mask);
|
||||||
self_ipv4_u32 & mask_u32 == addr_ipv4_u32 & mask_u32
|
self_ipv4_u32 & mask_u32 == addr_ipv4_u32 & mask_u32
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::iff;
|
use crate::iff;
|
||||||
|
|
||||||
pub fn is_macos() -> bool {
|
pub fn is_macos() -> bool {
|
||||||
@@ -19,7 +20,7 @@ pub fn get_user_home() -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_full_work_dir() -> Option<String> {
|
pub fn get_full_work_dir() -> Option<String> {
|
||||||
PathBuf::from(".").canonicalize().ok().map(|p| {
|
PathBuf::from(".").canonicalize().ok().and_then(|p| {
|
||||||
p.to_str().map(ToString::to_string)
|
p.to_str().map(ToString::to_string)
|
||||||
}).flatten()
|
})
|
||||||
}
|
}
|
||||||
@@ -27,17 +27,17 @@ pub fn parse_size(size: &str) -> XResult<i64> {
|
|||||||
|
|
||||||
pub fn get_display_size(size: i64) -> String {
|
pub fn get_display_size(size: i64) -> String {
|
||||||
if size < SIZE_KB {
|
if size < SIZE_KB {
|
||||||
size.to_string()
|
format!("{} {}", size, crate::iff!(size == 1, "byte", "bytes" ))
|
||||||
} else if size < SIZE_MB {
|
} else if size < SIZE_MB {
|
||||||
format!("{:.*}KB", 2, (size as f64) / SIZE_KB as f64)
|
format!("{:.*}KiB", 2, (size as f64) / SIZE_KB as f64)
|
||||||
} else if size < SIZE_GB {
|
} else if size < SIZE_GB {
|
||||||
format!("{:.*}MB", 2, (size as f64) / SIZE_MB as f64)
|
format!("{:.*}MiB", 2, (size as f64) / SIZE_MB as f64)
|
||||||
} else if size < SIZE_TB {
|
} else if size < SIZE_TB {
|
||||||
format!("{:.*}GB", 2, (size as f64) / SIZE_GB as f64)
|
format!("{:.*}GiB", 2, (size as f64) / SIZE_GB as f64)
|
||||||
} else if size < SIZE_PB {
|
} else if size < SIZE_PB {
|
||||||
format!("{:.*}TB", 2, (size as f64) / SIZE_TB as f64)
|
format!("{:.*}TiB", 2, (size as f64) / SIZE_TB as f64)
|
||||||
} else {
|
} else {
|
||||||
format!("{:.*}PB", 2, (size as f64) / SIZE_PB as f64)
|
format!("{:.*}PiB", 2, (size as f64) / SIZE_PB as f64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ fn test_parse_size() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_display_size() {
|
fn test_get_display_size() {
|
||||||
assert_eq!(get_display_size(0), "0");
|
assert_eq!(get_display_size(0), "0 bytes");
|
||||||
assert_eq!(get_display_size(111), "111");
|
assert_eq!(get_display_size(111), "111 bytes");
|
||||||
assert_eq!(get_display_size(1024), "1.00KB");
|
assert_eq!(get_display_size(1024), "1.00KiB");
|
||||||
assert_eq!(get_display_size(1024 * 1024), "1.00MB");
|
assert_eq!(get_display_size(1024 * 1024), "1.00MiB");
|
||||||
assert_eq!(get_display_size(1024 * 1024 * 1024), "1.00GB");
|
assert_eq!(get_display_size(1024 * 1024 * 1024), "1.00GiB");
|
||||||
assert_eq!(get_display_size(1024 * 1024 * 1024 * 1024), "1.00TB");
|
assert_eq!(get_display_size(1024 * 1024 * 1024 * 1024), "1.00TiB");
|
||||||
assert_eq!(get_display_size(1024 * 1024 * 1024 * 1024 * 1024), "1.00PB");
|
assert_eq!(get_display_size(1024 * 1024 * 1024 * 1024 * 1024), "1.00PiB");
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,6 @@
|
|||||||
|
|
||||||
/// Split string to lines, splited by '\r', '\n' or "\r\n"
|
/// Split string to lines, splited by '\r', '\n' or "\r\n"
|
||||||
pub fn read_str_to_lines(s: &str) -> Vec<String> {
|
pub fn read_str_to_lines(s: &str) -> Vec<String> {
|
||||||
s.lines().map(|ln| ln.to_owned()).collect()
|
s.lines().map(|ln| ln.to_owned()).collect()
|
||||||
// let mut r = vec![];
|
|
||||||
// let mut line = String::new();
|
|
||||||
// let mut cs = s.chars().peekable();
|
|
||||||
// while let Some(c) = cs.next() {
|
|
||||||
// if c == '\n' || c == '\r' {
|
|
||||||
// r.push(line.clone());
|
|
||||||
// line.clear();
|
|
||||||
// if c == '\r' {
|
|
||||||
// if let Some(nc) = cs.peek() {
|
|
||||||
// if *nc == '\n' {
|
|
||||||
// cs.next();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// line.push(c);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if !line.is_empty() {
|
|
||||||
// r.push(line);
|
|
||||||
// }
|
|
||||||
// r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_kv(s: &str, split: char) -> (String, String) {
|
pub fn split_kv(s: &str, split: char) -> (String, String) {
|
||||||
@@ -61,25 +38,30 @@ fn test_read_str_to_lines() {
|
|||||||
let s = "";
|
let s = "";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 0);
|
assert_eq!(lines.len(), 0);
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
let s = "\n";
|
let s = "\n";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 1);
|
assert_eq!(lines.len(), 1);
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
let s = "\r";
|
let s = "\r";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 1);
|
assert_eq!(lines.len(), 1);
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
let s = "\r\n";
|
let s = "\r\n";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 1);
|
assert_eq!(lines.len(), 1);
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
let s = "aa\r\nbb";
|
let s = "aa\r\nbb";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 2);
|
assert_eq!(lines.len(), 2);
|
||||||
assert_eq!(lines[0], "aa");
|
assert_eq!(lines[0], "aa");
|
||||||
assert_eq!(lines[1], "bb");
|
assert_eq!(lines[1], "bb");
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
let s = "aa\r\nbb\ncc";
|
let s = "aa\r\nbb\ncc";
|
||||||
let lines = read_str_to_lines(s);
|
let lines = read_str_to_lines(s);
|
||||||
assert_eq!(lines.len(), 3);
|
assert_eq!(lines.len(), 3);
|
||||||
|
|||||||
@@ -1,23 +1,58 @@
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
use crate::util_msg;
|
||||||
|
|
||||||
|
pub const STD_BLACK: &str = "\x1B[30m";
|
||||||
|
pub const STD_RED: &str = "\x1B[31m";
|
||||||
|
pub const STD_GREEN: &str = "\x1B[32m";
|
||||||
|
pub const STD_YELLOW: &str = "\x1B[33m";
|
||||||
|
pub const STD_BLUE: &str = "\x1B[34m";
|
||||||
|
pub const STD_MAGENTA: &str = "\x1B[35m"; // 品红色/洋红
|
||||||
|
pub const STD_CYAN: &str = "\x1B[36m"; // 青色
|
||||||
|
pub const STD_WHITE: &str = "\x1B[37m";
|
||||||
|
|
||||||
|
pub const BLACK: &str = "\x1B[90m";
|
||||||
pub const RED: &str = "\x1B[91m";
|
pub const RED: &str = "\x1B[91m";
|
||||||
pub const GREEN: &str = "\x1B[92m";
|
pub const GREEN: &str = "\x1B[92m";
|
||||||
pub const YELLOW: &str = "\x1B[93m";
|
pub const YELLOW: &str = "\x1B[93m";
|
||||||
|
pub const BLUE: &str = "\x1B[94m";
|
||||||
|
pub const MAGENTA: &str = "\x1B[95m";
|
||||||
|
pub const CYAN: &str = "\x1B[96m";
|
||||||
|
pub const WHITE: &str = "\x1B[97m";
|
||||||
|
|
||||||
|
pub const BG_STD_BLACK: &str = "\x1B[40m";
|
||||||
|
pub const BG_STD_RED: &str = "\x1B[41m";
|
||||||
|
pub const BG_STD_GREEN: &str = "\x1B[42m";
|
||||||
|
pub const BG_STD_YELLOW: &str = "\x1B[43m";
|
||||||
|
pub const BG_STD_BLUE: &str = "\x1B[44m";
|
||||||
|
pub const BG_STD_MAGENTA: &str = "\x1B[45m";
|
||||||
|
pub const BG_STD_CYAN: &str = "\x1B[46m";
|
||||||
|
pub const BG_STD_WHITE: &str = "\x1B[47m";
|
||||||
|
|
||||||
|
pub const BG_BLACK: &str = "\x1B[100m";
|
||||||
|
pub const BG_RED: &str = "\x1B[101m";
|
||||||
|
pub const BG_GREEN: &str = "\x1B[102m";
|
||||||
|
pub const BG_YELLOW: &str = "\x1B[103m";
|
||||||
|
pub const BG_BLUE: &str = "\x1B[104m";
|
||||||
|
pub const BG_MAGENTA: &str = "\x1B[105m";
|
||||||
|
pub const BG_CYAN: &str = "\x1B[106m";
|
||||||
|
pub const BG_WHITE: &str = "\x1B[107m";
|
||||||
|
|
||||||
pub const BOLD: &str = "\x1B[1m";
|
pub const BOLD: &str = "\x1B[1m";
|
||||||
pub const UNDER: &str = "\x1B[4m";
|
pub const UNDER: &str = "\x1B[4m";
|
||||||
pub const END: &str = "\x1B[0m";
|
pub const END: &str = "\x1B[0m";
|
||||||
|
|
||||||
pub fn read_yes_no(hint: &str) -> bool {
|
pub fn read_yes_no(hint: &str) -> bool {
|
||||||
loop {
|
loop {
|
||||||
print!("{} (Yes/No): ", hint);
|
util_msg::print_ex(&format!("{} (Yes/No): ", hint), false);
|
||||||
io::stdout().flush().ok();
|
io::stdout().flush().ok();
|
||||||
let mut buff = String::new();
|
let mut buff = String::new();
|
||||||
let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin");
|
let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin");
|
||||||
let buff = buff.trim().to_lowercase();
|
let buff = buff.trim().to_lowercase();
|
||||||
if vec!["y", "yes"].contains(&buff.as_str()) {
|
if ["y", "yes"].contains(&buff.as_str()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if vec!["n", "no"].contains(&buff.as_str()) {
|
if ["n", "no"].contains(&buff.as_str()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,44 @@
|
|||||||
use std::time::{SystemTime, Duration};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
|
pub trait UnixEpochTime {
|
||||||
|
fn to_secs(&self) -> Option<u64>;
|
||||||
|
fn to_millis(&self) -> Option<u64>;
|
||||||
|
fn from_secs(secs: u64) -> Self;
|
||||||
|
fn from_millis(millis: u64) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnixEpochTime for SystemTime {
|
||||||
|
fn to_secs(&self) -> Option<u64> {
|
||||||
|
self.duration_since(SystemTime::UNIX_EPOCH).ok().map(|d| d.as_secs())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_millis(&self) -> Option<u64> {
|
||||||
|
self.duration_since(SystemTime::UNIX_EPOCH).ok().map(|d| d.as_millis() as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_secs(secs: u64) -> Self {
|
||||||
|
SystemTime::UNIX_EPOCH + Duration::from_secs(secs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_millis(millis: u64) -> Self {
|
||||||
|
SystemTime::UNIX_EPOCH + Duration::from_millis(millis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_current_secs() -> u64 {
|
pub fn get_current_secs() -> u64 {
|
||||||
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0 /* SHOULD NOT HAPPEN */)
|
get_secs(&SystemTime::now())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_millis() -> u128 {
|
pub fn get_current_millis() -> u128 {
|
||||||
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_millis()).unwrap_or(0 /* SHOULD NOT HAPPEN */)
|
get_millis(&SystemTime::now())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_secs(system_time: &SystemTime) -> u64 {
|
||||||
|
system_time.duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0 /* SHOULD NOT HAPPEN */)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_millis(system_time: &SystemTime) -> u128 {
|
||||||
|
system_time.duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_millis()).unwrap_or(0 /* SHOULD NOT HAPPEN */)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_duration(t: &str) -> Option<Duration> {
|
pub fn parse_duration(t: &str) -> Option<Duration> {
|
||||||
@@ -26,12 +59,12 @@ pub fn parse_duration(t: &str) -> Option<Duration> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_current_secs() {
|
fn test_get_current_secs() {
|
||||||
assert!(get_current_secs() != 0);
|
assert_ne!(get_current_secs(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_current_millis() {
|
fn test_get_current_millis() {
|
||||||
assert!(get_current_millis() != 0);
|
assert_ne!(get_current_millis(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -49,3 +82,14 @@ fn test_parse_duration() {
|
|||||||
assert_eq!(Duration::from_millis(1800000), parse_duration("0.5h").unwrap());
|
assert_eq!(Duration::from_millis(1800000), parse_duration("0.5h").unwrap());
|
||||||
assert_eq!(Duration::from_millis(24 * 3600000), parse_duration("1d").unwrap());
|
assert_eq!(Duration::from_millis(24 * 3600000), parse_duration("1d").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unix_epoch() {
|
||||||
|
let t = SystemTime::now();
|
||||||
|
let s = t.to_secs().unwrap();
|
||||||
|
let m = t.to_millis().unwrap();
|
||||||
|
let t2 = SystemTime::from_secs(s);
|
||||||
|
let t3 = SystemTime::from_millis(m);
|
||||||
|
assert_eq!(get_secs(&t), get_secs(&t2));
|
||||||
|
assert_eq!(get_millis(&t), get_millis(&t3));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user