zeros/argon2/
memory.rs

1/*
2==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
3
4Zeros
5
6Copyright (C) 2019-2025  Anonymous
7
8There are several releases over multiple years,
9they are listed as ranges, such as: "2019-2025".
10
11This program is free software: you can redistribute it and/or modify
12it under the terms of the GNU Lesser General Public License as published by
13the Free Software Foundation, either version 3 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public License
22along with this program.  If not, see <https://www.gnu.org/licenses/>.
23
24::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
25*/
26
27//! # Memory
28
29use core::{
30    cmp::Ordering,
31    fmt::{self, Display, Formatter},
32    hash::{Hash, Hasher},
33};
34
35#[cfg(test)]
36mod tests;
37
38const N1024: u32 = 1024;
39const N1024_P2: u32 = N1024.pow(2);
40
41/// # Memory
42#[derive(Debug, Clone, Copy, Eq)]
43pub enum Memory {
44
45    /// # KiB
46    KiB(u32),
47
48    /// # MiB
49    MiB(u32),
50
51    /// # GiB
52    GiB(u32),
53
54}
55
56impl Memory {
57
58    /// # Converts to KiB
59    pub (crate) const fn to_kib(&self) -> Option<u32> {
60        match self {
61            Self::KiB(k) => Some(*k),
62            Self::MiB(m) => m.checked_mul(N1024),
63            Self::GiB(g) => g.checked_mul(N1024_P2),
64        }
65    }
66
67    /// # Converts to KiB as u64
68    const fn to_kib_u64(&self) -> u64 {
69        match self {
70            Self::KiB(k) => *k as u64,
71            Self::MiB(m) => *m as u64 * N1024 as u64,
72            Self::GiB(g) => *g as u64 * N1024_P2 as u64,
73        }
74    }
75
76}
77
78impl Display for Memory {
79
80    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
81        const KIB: &str = "KiB";
82        const MIB: &str = "MiB";
83        const GIB: &str = "GiB";
84
85        let mib = |m| if m == 0 || m % N1024 != 0 { (m, MIB) } else { (m / N1024, GIB) };
86        let (v, unit) = match self {
87            Self::KiB(k) => if k == &0 || k % N1024 != 0 { (*k, KIB) } else { mib(k / N1024) },
88            Self::MiB(m) => mib(*m),
89            Self::GiB(g) => (*g, GIB),
90        };
91        write!(f, concat!("{v}", ' ', "{unit}"), v=v, unit=unit)
92    }
93
94}
95
96impl Hash for Memory {
97
98    fn hash<H>(&self, h: &mut H) where H: Hasher {
99        self.to_kib_u64().hash(h);
100    }
101
102}
103
104impl PartialEq for Memory {
105
106    fn eq(&self, other: &Self) -> bool {
107        self.cmp(other) == Ordering::Equal
108    }
109
110}
111
112impl Ord for Memory {
113
114    fn cmp(&self, other: &Self) -> Ordering {
115        self.to_kib_u64().cmp(&other.to_kib_u64())
116    }
117
118}
119
120impl PartialOrd for Memory {
121
122    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
123        Some(self.cmp(other))
124    }
125
126}