1#![no_std]
2
3use core::fmt;
75use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
76
77pub mod iec;
78pub mod si;
79
80use iec::{GIB, GiB, KIB, KiB, MIB, MiB, PIB, PiB, TIB, TiB};
81use si::{GB, GB_BYTES, KB, KB_BYTES, MB, MB_BYTES, PB, PB_BYTES, TB, TB_BYTES};
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
85pub struct Bytes(pub u64);
86
87impl Bytes {
88 pub const fn new(val: u64) -> Self {
89 Self(val)
90 }
91
92 pub const fn as_u64(&self) -> u64 {
93 self.0
94 }
95
96 pub const fn as_kib(self) -> KiB {
98 KiB(self.0 / KIB)
99 }
100
101 pub const fn as_mib(self) -> MiB {
102 MiB(self.0 / MIB)
103 }
104
105 pub const fn as_gib(self) -> GiB {
106 GiB(self.0 / GIB)
107 }
108
109 pub const fn as_tib(self) -> TiB {
110 TiB(self.0 / TIB)
111 }
112
113 pub const fn as_pib(self) -> PiB {
114 PiB(self.0 / PIB)
115 }
116
117 pub const fn as_kb(self) -> KB {
119 KB(self.0 / KB_BYTES)
120 }
121
122 pub const fn as_mb(self) -> MB {
123 MB(self.0 / MB_BYTES)
124 }
125
126 pub const fn as_gb(self) -> GB {
127 GB(self.0 / GB_BYTES)
128 }
129
130 pub const fn as_tb(self) -> TB {
131 TB(self.0 / TB_BYTES)
132 }
133
134 pub const fn as_pb(self) -> PB {
135 PB(self.0 / PB_BYTES)
136 }
137}
138
139impl fmt::Display for Bytes {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 write!(f, "{} B", self.0)
142 }
143}
144
145impl Add for Bytes {
146 type Output = Self;
147 fn add(self, rhs: Self) -> Self::Output {
148 Self(self.0 + rhs.0)
149 }
150}
151impl AddAssign for Bytes {
152 fn add_assign(&mut self, rhs: Self) {
153 self.0 += rhs.0;
154 }
155}
156
157impl Sub for Bytes {
158 type Output = Self;
159 fn sub(self, rhs: Self) -> Self::Output {
160 Self(self.0 - rhs.0)
161 }
162}
163impl SubAssign for Bytes {
164 fn sub_assign(&mut self, rhs: Self) {
165 self.0 -= rhs.0;
166 }
167}
168
169impl Mul<u64> for Bytes {
170 type Output = Self;
171 fn mul(self, rhs: u64) -> Self::Output {
172 Self(self.0 * rhs)
173 }
174}
175impl Mul<Bytes> for u64 {
176 type Output = Bytes;
177 fn mul(self, rhs: Bytes) -> Self::Output {
178 Bytes(self * rhs.0)
179 }
180}
181impl MulAssign<u64> for Bytes {
182 fn mul_assign(&mut self, rhs: u64) {
183 self.0 *= rhs;
184 }
185}
186
187impl Div<u64> for Bytes {
188 type Output = Self;
189 fn div(self, rhs: u64) -> Self::Output {
190 Self(self.0 / rhs)
191 }
192}
193impl DivAssign<u64> for Bytes {
194 fn div_assign(&mut self, rhs: u64) {
195 self.0 /= rhs;
196 }
197}
198
199impl Div for Bytes {
200 type Output = u64;
201 fn div(self, rhs: Self) -> Self::Output {
202 self.0 / rhs.0
203 }
204}
205
206impl Rem for Bytes {
207 type Output = Self;
208 fn rem(self, rhs: Self) -> Self::Output {
209 Self(self.0 % rhs.0)
210 }
211}
212
213impl RemAssign for Bytes {
214 fn rem_assign(&mut self, rhs: Self) {
215 self.0 %= rhs.0;
216 }
217}
218
219impl From<u64> for Bytes {
221 fn from(val: u64) -> Self {
222 Bytes(val)
223 }
224}
225
226impl From<usize> for Bytes {
227 fn from(val: usize) -> Self {
228 Bytes(val as u64)
229 }
230}
231
232impl From<Bytes> for u64 {
233 fn from(bytes: Bytes) -> u64 {
234 bytes.0
235 }
236}
237
238#[macro_export]
239macro_rules! impl_comparison {
240 ($target:ident, $($other:ident),+) => {
241 $(
242 impl PartialEq<$other> for $target {
243 fn eq(&self, other: &$other) -> bool {
244 $crate::Bytes::from(*self) == $crate::Bytes::from(*other)
245 }
246 }
247
248 impl PartialEq<$target> for $other {
249 fn eq(&self, other: &$target) -> bool {
250 $crate::Bytes::from(*self) == $crate::Bytes::from(*other)
251 }
252 }
253
254 impl PartialOrd<$other> for $target {
255 fn partial_cmp(&self, other: &$other) -> Option<core::cmp::Ordering> {
256 $crate::Bytes::from(*self).partial_cmp(&$crate::Bytes::from(*other))
257 }
258 }
259
260 impl PartialOrd<$target> for $other {
261 fn partial_cmp(&self, other: &$target) -> Option<core::cmp::Ordering> {
262 $crate::Bytes::from(*self).partial_cmp(&$crate::Bytes::from(*other))
263 }
264 }
265 )+
266 };
267}