4 pub fn strip_server_file_extension(name
: &str) -> String
{
5 if name
.ends_with(".didx") || name
.ends_with(".fidx") || name
.ends_with(".blob") {
6 name
[..name
.len()-5].to_owned()
8 name
.to_owned() // should not happen
12 pub fn render_backup_file_list(files
: &[String
]) -> String
{
13 let mut files
: Vec
<String
> = files
.iter()
14 .map(|v
| strip_server_file_extension(&v
))
19 crate::str::join(&files
, ' '
)
22 pub fn render_epoch(value
: &Value
, _record
: &Value
) -> Result
<String
, Error
> {
23 if value
.is_null() { return Ok(String::new()); }
24 let text
= match value
.as_i64() {
26 if let Ok(epoch_string
) = proxmox
::tools
::time
::strftime_local("%c", epoch
as i64) {
39 pub fn render_task_status(value
: &Value
, record
: &Value
) -> Result
<String
, Error
> {
40 if record
["endtime"].is_null() {
41 Ok(value
.as_str().unwrap_or("running").to_string())
43 Ok(value
.as_str().unwrap_or("unknown").to_string())
47 pub fn render_bool_with_default_true(value
: &Value
, _record
: &Value
) -> Result
<String
, Error
> {
48 let value
= value
.as_bool().unwrap_or(true);
49 Ok((if value { "1" }
else { "0" }
).to_string())
52 pub fn render_bytes_human_readable(value
: &Value
, _record
: &Value
) -> Result
<String
, Error
> {
53 if value
.is_null() { return Ok(String::new()); }
54 let text
= match value
.as_u64() {
56 HumanByte
::from(bytes
).to_string()
65 pub struct HumanByte
{
68 impl std
::fmt
::Display
for HumanByte
{
69 fn fmt(&self, f
: &mut std
::fmt
::Formatter
<'_
>) -> std
::fmt
::Result
{
71 return write
!(f
, "{} B", self.b
);
73 let kb
: f64 = self.b
as f64 / 1024.0;
75 return write
!(f
, "{:.2} KiB", kb
);
77 let mb
: f64 = kb
/ 1024.0;
79 return write
!(f
, "{:.2} MiB", mb
);
81 let gb
: f64 = mb
/ 1024.0;
83 return write
!(f
, "{:.2} GiB", gb
);
85 let tb
: f64 = gb
/ 1024.0;
87 return write
!(f
, "{:.2} TiB", tb
);
89 let pb
: f64 = tb
/ 1024.0;
90 return write
!(f
, "{:.2} PiB", pb
);
93 impl From
<usize> for HumanByte
{
94 fn from(v
: usize) -> Self {
98 impl From
<u64> for HumanByte
{
99 fn from(v
: u64) -> Self {
100 HumanByte { b: v as usize }
104 pub fn as_fingerprint(bytes
: &[u8]) -> String
{
105 proxmox
::tools
::digest_to_hex(bytes
)
108 .map(|v
| std
::str::from_utf8(v
).unwrap())
109 .collect
::<Vec
<&str>>().join(":")
112 pub mod bytes_as_fingerprint
{
113 use serde
::{Deserialize, Serializer, Deserializer}
;
118 ) -> Result
<S
::Ok
, S
::Error
>
122 let s
= super::as_fingerprint(bytes
);
123 serializer
.serialize_str(&s
)
126 pub fn deserialize
<'de
, D
>(
128 ) -> Result
<[u8; 32], D
::Error
>
130 D
: Deserializer
<'de
>,
132 let mut s
= String
::deserialize(deserializer
)?
;
133 s
.retain(|c
| c
!= '
:'
);
134 proxmox
::tools
::hex_to_digest(&s
).map_err(serde
::de
::Error
::custom
)
139 fn correct_byte_convert() {
140 fn convert(b
: usize) -> String
{
141 HumanByte
::from(b
).to_string()
143 assert_eq
!(convert(1023), "1023 B");
144 assert_eq
!(convert(1<<10), "1.00 KiB");
145 assert_eq
!(convert(1<<20), "1.00 MiB");
146 assert_eq
!(convert((1<<30) + 103 * (1<<20)), "1.10 GiB");
147 assert_eq
!(convert((2<<50) + 500 * (1<<40)), "2.49 PiB");