2020-04-17 12:11:25 +00:00
|
|
|
use anyhow::{Error};
|
2020-02-28 06:30:35 +00:00
|
|
|
use serde_json::Value;
|
2020-09-11 12:34:36 +00:00
|
|
|
use chrono::{Local, TimeZone, LocalResult};
|
2020-02-28 06:30:35 +00:00
|
|
|
|
|
|
|
pub fn strip_server_file_expenstion(name: &str) -> String {
|
|
|
|
|
|
|
|
if name.ends_with(".didx") || name.ends_with(".fidx") || name.ends_with(".blob") {
|
|
|
|
name[..name.len()-5].to_owned()
|
|
|
|
} else {
|
|
|
|
name.to_owned() // should not happen
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render_backup_file_list(files: &[String]) -> String {
|
|
|
|
let mut files: Vec<String> = files.iter()
|
|
|
|
.map(|v| strip_server_file_expenstion(&v))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
files.sort();
|
|
|
|
|
|
|
|
super::join(&files, ' ')
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render_epoch(value: &Value, _record: &Value) -> Result<String, Error> {
|
|
|
|
if value.is_null() { return Ok(String::new()); }
|
|
|
|
let text = match value.as_i64() {
|
|
|
|
Some(epoch) => {
|
2020-09-11 12:34:36 +00:00
|
|
|
match Local.timestamp_opt(epoch, 0) {
|
|
|
|
LocalResult::Single(epoch) => epoch.format("%c").to_string(),
|
|
|
|
_ => epoch.to_string(),
|
|
|
|
}
|
|
|
|
},
|
2020-02-28 06:30:35 +00:00
|
|
|
None => {
|
|
|
|
value.to_string()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok(text)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render_task_status(value: &Value, record: &Value) -> Result<String, Error> {
|
|
|
|
if record["endtime"].is_null() {
|
|
|
|
Ok(value.as_str().unwrap_or("running").to_string())
|
|
|
|
} else {
|
|
|
|
Ok(value.as_str().unwrap_or("unknown").to_string())
|
|
|
|
}
|
|
|
|
}
|
2020-05-01 14:08:15 +00:00
|
|
|
|
|
|
|
pub fn render_bool_with_default_true(value: &Value, _record: &Value) -> Result<String, Error> {
|
|
|
|
let value = value.as_bool().unwrap_or(true);
|
|
|
|
Ok((if value { "1" } else { "0" }).to_string())
|
|
|
|
}
|
2020-07-23 07:36:02 +00:00
|
|
|
|
|
|
|
pub struct HumanByte {
|
|
|
|
b: usize,
|
|
|
|
}
|
|
|
|
impl std::fmt::Display for HumanByte {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
if self.b < 1024 {
|
|
|
|
return write!(f, "{} B", self.b);
|
|
|
|
}
|
|
|
|
let kb: f64 = self.b as f64 / 1024.0;
|
|
|
|
if kb < 1024.0 {
|
|
|
|
return write!(f, "{:.2} KiB", kb);
|
|
|
|
}
|
|
|
|
let mb: f64 = kb / 1024.0;
|
|
|
|
if mb < 1024.0 {
|
|
|
|
return write!(f, "{:.2} MiB", mb);
|
|
|
|
}
|
|
|
|
let gb: f64 = mb / 1024.0;
|
|
|
|
if gb < 1024.0 {
|
|
|
|
return write!(f, "{:.2} GiB", gb);
|
|
|
|
}
|
|
|
|
let tb: f64 = gb / 1024.0;
|
|
|
|
if tb < 1024.0 {
|
|
|
|
return write!(f, "{:.2} TiB", tb);
|
|
|
|
}
|
|
|
|
let pb: f64 = tb / 1024.0;
|
|
|
|
return write!(f, "{:.2} PiB", pb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl From<usize> for HumanByte {
|
|
|
|
fn from(v: usize) -> Self {
|
|
|
|
HumanByte { b: v }
|
|
|
|
}
|
|
|
|
}
|
2020-08-25 12:18:48 +00:00
|
|
|
impl From<u64> for HumanByte {
|
|
|
|
fn from(v: u64) -> Self {
|
|
|
|
HumanByte { b: v as usize }
|
|
|
|
}
|
|
|
|
}
|
2020-07-23 07:36:02 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn correct_byte_convert() {
|
|
|
|
fn convert(b: usize) -> String {
|
|
|
|
HumanByte::from(b).to_string()
|
|
|
|
}
|
|
|
|
assert_eq!(convert(1023), "1023 B");
|
|
|
|
assert_eq!(convert(1<<10), "1.00 KiB");
|
|
|
|
assert_eq!(convert(1<<20), "1.00 MiB");
|
|
|
|
assert_eq!(convert((1<<30) + (103 * 1<<20)), "1.10 GiB");
|
|
|
|
assert_eq!(convert((2<<50) + (500 * 1<<40)), "2.49 PiB");
|
|
|
|
}
|