Skip to main content

bevy_utils/
memory_size.rs

1//! Types for representing the size of objects in memory.
2
3use core::fmt::Display;
4
5/// The size of an object in memory, in bytes.
6///
7/// The helper methods on this type use powers of 2 for conversions between units,
8/// consistent with the standards for memory reporting.
9///
10/// While it would technically be more correct to use e.g.
11/// "kibibytes" instead of "kilobytes", "mebibytes" instead of "megabytes", etc.,
12/// the more common terms are used here for familiarity and discoverability.
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
14#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
15pub struct MemorySize(pub u64);
16
17impl MemorySize {
18    /// Creates a new [`MemorySize`] from the given number of bytes.
19    ///
20    /// This method is provided for convenience,
21    /// as many other APIs in Rust use `usize` for sizes and counts.
22    /// To initialize this type with a `u64`, just call `MemorySize(bytes)` directly.
23    pub fn new(bytes: usize) -> Self {
24        MemorySize(bytes as u64)
25    }
26
27    /// Returns the size in bytes, as a `usize`.
28    ///
29    /// This method is provided for convenience,
30    /// as many other APIs in Rust use `usize` for sizes and counts.
31    /// To access the value as a `u64`, just use the `.0` field directly.
32    ///
33    /// 1 byte = 8 bits.
34    pub fn as_bytes(&self) -> usize {
35        self.0 as usize
36    }
37
38    /// Returns the size in kilobytes.
39    ///
40    /// 1 kilobyte = 1024 bytes.
41    pub fn as_kilobytes(&self) -> f64 {
42        self.0 as f64 / 1024.0
43    }
44
45    /// Returns the size in megabytes.
46    ///
47    /// 1 megabyte = 1024 kilobytes.
48    pub fn as_megabytes(&self) -> f64 {
49        self.0 as f64 / (1024.0 * 1024.0)
50    }
51
52    /// Returns the size in gigabytes.
53    ///
54    /// 1 gigabyte = 1024 megabytes.
55    pub fn as_gigabytes(&self) -> f64 {
56        self.0 as f64 / (1024.0 * 1024.0 * 1024.0)
57    }
58
59    /// Returns the size in terabytes.
60    ///
61    /// 1 terabyte = 1024 gigabytes.
62    pub fn as_terabytes(&self) -> f64 {
63        self.0 as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
64    }
65
66    /// Determine the appropriate unit for displaying the memory size.
67    ///
68    /// Units are chosen such that the value is at least 1 in that unit.
69    ///
70    /// This is used for formatting the memory size in a human-readable way,
71    /// such as in the [`Display`] implementation for this type.
72    pub fn appropriate_unit(&self) -> MemoryUnit {
73        if self.0 >= 1024 * 1024 * 1024 * 1024 {
74            MemoryUnit::Terabytes
75        } else if self.0 >= 1024 * 1024 * 1024 {
76            MemoryUnit::Gigabytes
77        } else if self.0 >= 1024 * 1024 {
78            MemoryUnit::Megabytes
79        } else if self.0 >= 1024 {
80            MemoryUnit::Kilobytes
81        } else {
82            MemoryUnit::Bytes
83        }
84    }
85}
86
87impl Display for MemorySize {
88    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
89        let unit = self.appropriate_unit();
90        match unit {
91            MemoryUnit::Bytes => write!(f, "{} B", self.as_bytes()),
92            MemoryUnit::Kilobytes => write!(f, "{:.2} KiB", self.as_kilobytes()),
93            MemoryUnit::Megabytes => write!(f, "{:.2} MiB", self.as_megabytes()),
94            MemoryUnit::Gigabytes => write!(f, "{:.2} GiB", self.as_gigabytes()),
95            MemoryUnit::Terabytes => write!(f, "{:.2} TiB", self.as_terabytes()),
96        }
97    }
98}
99
100/// Common units for representing memory size.
101///
102/// Used for determining the most appropriate unit to display a [`MemorySize`].
103#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104pub enum MemoryUnit {
105    /// 8 bits
106    Bytes,
107    /// 1 kilobyte = 1024 bytes
108    Kilobytes,
109    /// 1 megabyte = 1024 kilobytes
110    Megabytes,
111    /// 1 gigabyte = 1024 megabytes
112    Gigabytes,
113    /// 1 terabyte = 1024 gigabytes
114    Terabytes,
115}