ouisync/protocol/
storage_size.rs

1use crate::protocol::BLOCK_RECORD_SIZE;
2use ouisync_macros::api;
3use serde::{Deserialize, Serialize};
4use std::{fmt, str::FromStr};
5
6/// Strongly typed storage size.
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Deserialize)]
8#[serde(transparent)]
9#[api]
10pub struct StorageSize {
11    bytes: u64,
12}
13
14impl StorageSize {
15    pub fn from_bytes(value: u64) -> Self {
16        Self { bytes: value }
17    }
18
19    pub fn from_blocks(value: u64) -> Self {
20        Self {
21            bytes: value * BLOCK_RECORD_SIZE,
22        }
23    }
24
25    pub fn to_bytes(self) -> u64 {
26        self.bytes
27    }
28
29    // pub fn to_blocks(self) -> u64 {
30    //     self.bytes / BLOCK_RECORD_SIZE
31    // }
32
33    pub fn saturating_sub(self, rhs: Self) -> Self {
34        Self {
35            bytes: self.bytes.saturating_sub(rhs.bytes),
36        }
37    }
38}
39
40impl fmt::Display for StorageSize {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        const SUFFIXES: &[(u64, &str)] = &[
43            (1024, "ki"),
44            (1024 * 1024, "Mi"),
45            (1024 * 1024 * 1024, "Gi"),
46            (1024 * 1024 * 1024 * 1024, "Ti"),
47        ];
48
49        for (value, suffix) in SUFFIXES.iter().rev().copied() {
50            if self.bytes >= value {
51                return write!(f, "{:.2} {}B", self.bytes as f64 / value as f64, suffix);
52            }
53        }
54
55        write!(f, "{} B", self.bytes)
56    }
57}
58
59impl FromStr for StorageSize {
60    type Err = parse_size::Error;
61
62    fn from_str(s: &str) -> Result<Self, Self::Err> {
63        Ok(Self {
64            bytes: parse_size::parse_size(s)?,
65        })
66    }
67}