1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use super::*;

/// Specify the possible choices for the base used
/// for the display of bytes, i.e.
/// **Gabyte**: Powers of 1000 bytes (Kilobyte, Megabyte, ...)
/// **Bibyte**: Powers of 1024 bytes (Kibibyte, Mebibyte, ...)
/// giving its name to the crate Ga/Bi(byte).
#[derive(Clone, Copy)]
pub enum BytesBase {
    Gabyte,
    Bibyte,
}

impl Default for BytesBase {
    fn default() -> Self {
        BytesBase::Gabyte
    }
}

/// This struct stores the preferences for the display of bytes
/// inside BytesConfig.
#[derive(Default, Clone, Copy)]
pub(crate) struct BytesParam {
    pub(crate) base: BytesBase,
    pub(crate) precision: usize,
    pub(crate) aligned: bool,
}

/// This struct captures the preferences for display of bytes and
/// creates instances of `Bytes` struct that contain a reference
/// to the preferences that they must use for display.
/// If the preferences are changed, all `Bytes` that the `BytesConfig`
/// instanciated adopt immediately the change. Config wrapped in Mutex
/// makes the implementation threadsafe.
pub struct BytesConfig {
    pub(crate) config: Arc<Mutex<Cell<BytesParam>>>,
}

impl BytesConfig {
    /// Specify preferences for the creation of the `BytesConfig` struct.
    pub fn new(base: BytesBase, precision: usize, padded: bool) -> Self {
        Self {
            config: Arc::new(Mutex::new(Cell::new(BytesParam {
                base,
                precision,
                aligned: padded,
            }))),
        }
    }

    /// Specify the base used for the display of bytes: Gabyte = 1000 bytes or bibyte = 1024 bytes
    pub fn set_base(&mut self, b: BytesBase) {
        // Acquire lock on config and modify cell content
        let mut config = (*self.config).lock().unwrap().get();
        config.base = b;
        (*self.config).lock().unwrap().set(config);
    }

    /// Specify whether the display of values is aligned or not
    pub fn set_aligned(&mut self, pa: bool) {
        let mut config = (*self.config).lock().unwrap().get();
        config.aligned = pa;
        (*self.config).lock().unwrap().set(config);
    }

    /// Specify how many decimals to display
    pub fn set_precision(&mut self, pr: usize) {
        let mut config = (*self.config).lock().unwrap().get();
        config.precision = pr;
        (*self.config).lock().unwrap().set(config);
    }

    /// Creates an instance of `Bytes` that stores a reference to the
    /// BytesConfig instance that created it to obtain preferences from it
    pub fn bytes<U: Unsigned + Display + PartialOrd + Into<u64> + Copy>(&self, b: U) -> Bytes<U> {
        Bytes::new(self.config.clone(), b)
    }
}

impl Default for BytesConfig {
    /// By default, capacities are displayed in Bibytes (powers of 1000), precision is set to 2 decimals
    /// and the display of values is not aligned
    fn default() -> Self {
        Self {
            config: Arc::new(Mutex::new(Cell::new(BytesParam {
                base: BytesBase::default(),
                precision: 2,
                aligned: false,
            }))),
        }
    }
}