1use std::{
20 fmt::{Debug, Display, Formatter},
21 ops::{Add, Div, Mul, Sub},
22 str::FromStr,
23};
24
25use crate::{
26 arithmetic::{divisor, multiplier},
27 suffix::{parse, suffix},
28};
29
30pub const IEC: ByteUnit<()> = ByteUnit::IEC(());
32pub const SI: ByteUnit<()> = ByteUnit::SI(());
34pub const E: i8 = 6;
36pub const P: i8 = 5;
38pub const T: i8 = 4;
40pub const G: i8 = 3;
42pub const M: i8 = 2;
44pub const K: i8 = 1;
46pub const B: i8 = 0;
48pub const MAX: i8 = E;
50
51pub enum ByteUnit<T: Copy> {
53 IEC(T),
54 SI(T),
55}
56
57#[derive(Debug)]
58pub enum Error {
59 InvalidUnit(String),
60 ErroroneousInput(String),
61}
62
63pub trait ToByteUnit<T: Copy> {
65 fn to_byteunit(self, byte: ByteUnit<()>) -> ByteUnit<T>;
66}
67
68impl ToByteUnit<u32> for u32
69where
70 i64: From<u32>,
71{
72 fn to_byteunit(self, unit: ByteUnit<()>) -> ByteUnit<u32> {
73 match unit {
74 ByteUnit::IEC(()) => ByteUnit::IEC(self),
75 ByteUnit::SI(()) => ByteUnit::SI(self),
76 }
77 }
78}
79
80impl ToByteUnit<i32> for i32
81where
82 i64: From<i32>,
83{
84 fn to_byteunit(self, unit: ByteUnit<()>) -> ByteUnit<i32> {
85 match unit {
86 ByteUnit::IEC(()) => ByteUnit::IEC(self),
87 ByteUnit::SI(()) => ByteUnit::SI(self),
88 }
89 }
90}
91
92impl ToByteUnit<i64> for i64
93where
94 i64: From<i64>,
95{
96 fn to_byteunit(self, unit: ByteUnit<()>) -> ByteUnit<i64> {
97 match unit {
98 ByteUnit::IEC(()) => ByteUnit::IEC(self),
99 ByteUnit::SI(()) => ByteUnit::SI(self),
100 }
101 }
102}
103
104impl<T> ByteUnit<T>
105where
106 i64: From<T>,
107 T: Copy,
108{
109 fn value(&self) -> (T, f64) {
110 match self {
111 Self::IEC(val) => (*val, 1024.0),
112 Self::SI(val) => (*val, 1000.0),
113 }
114 }
115
116 fn format(&self, arithmetic: (i8, f64)) -> String {
117 let power = arithmetic.0;
118 let value = arithmetic.1;
119
120 match power {
121 B => format!("{:.0} {}", value, suffix(self, power)),
122 _ => format!("{:.2} {}", value, suffix(self, power)),
123 }
124 }
125
126 pub fn val(&self) -> T {
128 match self {
129 Self::IEC(val) => *val,
130 Self::SI(val) => *val,
131 }
132 }
133
134 pub fn max(&self) -> String {
136 self.format(divisor(self.value(), MAX))
137 }
138
139 pub fn pow(&self, power_of: i8) -> String {
141 self.format(divisor(self.value(), power_of))
142 }
143
144 pub fn k(&self) -> String {
146 self.format(divisor(self.value(), K))
147 }
148
149 pub fn m(&self) -> String {
151 self.format(divisor(self.value(), M))
152 }
153
154 pub fn g(&self) -> String {
156 self.format(divisor(self.value(), G))
157 }
158
159 pub fn p(&self) -> String {
161 self.format(divisor(self.value(), P))
162 }
163
164 pub fn t(&self) -> String {
166 self.format(divisor(self.value(), T))
167 }
168
169 pub fn e(&self) -> String {
171 self.format(divisor(self.value(), E))
172 }
173}
174
175impl<T> Display for ByteUnit<T>
177where
178 i64: From<T>,
179 T: Copy,
180{
181 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
182 let arithmetic = divisor(self.value(), MAX);
183 let bytes = arithmetic.1;
184 let index = arithmetic.0;
185
186 match index {
187 B => write!(f, "{:.0} {}", bytes, suffix(self, index)),
188 _ => write!(f, "{:.2} {}", bytes, suffix(self, index)),
189 }
190 }
191}
192
193impl<T> Debug for ByteUnit<T>
195where
196 i64: From<T>,
197 T: Copy,
198{
199 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
200 let arithmetic = divisor(self.value(), MAX);
201 let bytes = arithmetic.1;
202 let index = arithmetic.0;
203
204 match index {
205 B => write!(f, "'{:.0} {}'", bytes, suffix(self, index)),
206 _ => write!(f, "'{:.2} {}'", bytes, suffix(self, index)),
207 }
208 }
209}
210
211impl<T> From<&str> for ByteUnit<T>
212where
213 i64: From<T>,
214 T: Copy,
215 T: From<i64>,
216{
217 fn from(value: &str) -> Self {
218 ByteUnit::from_str(value).unwrap()
219 }
220}
221
222impl<T> FromStr for ByteUnit<T>
223where
224 i64: From<T>,
225 T: Copy,
226 i64: From<T>,
227 T: From<i64>,
228{
229 type Err = Error;
230
231 fn from_str(s: &str) -> Result<Self, Self::Err> {
232 let input = multiplier::<T>(parse(s)?);
233
234 match input.0 {
235 true => Ok(ByteUnit::IEC(input.1)),
236 false => Ok(ByteUnit::SI(input.1)),
237 }
238 }
239}
240
241impl<T> PartialOrd for ByteUnit<T>
242where
243 i64: From<T>,
244 T: Copy + PartialEq,
245{
246 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
247 let value = i64::from(self.val());
248 let other = i64::from(other.val());
249
250 value.partial_cmp(&other)
251 }
252}
253
254impl<T> PartialEq for ByteUnit<T>
255where
256 i64: From<T>,
257 T: Copy + PartialEq,
258{
259 fn eq(&self, other: &Self) -> bool {
260 other.val().eq(&self.val())
261 }
262}
263
264impl<T> Add for ByteUnit<T>
265where
266 i64: From<T>,
267 T: Copy + Add<Output = T>,
268{
269 type Output = Self;
270
271 fn add(self, input: Self) -> Self::Output {
272 match self {
273 Self::IEC(value) => Self::IEC(value + input.val()),
274 Self::SI(value) => Self::SI(value + input.val()),
275 }
276 }
277}
278
279impl<T> Sub for ByteUnit<T>
280where
281 i64: From<T>,
282 T: Copy + Sub<Output = T>,
283{
284 type Output = Self;
285
286 fn sub(self, input: Self) -> Self::Output {
287 match self {
288 Self::IEC(value) => Self::IEC(value - input.val()),
289 Self::SI(value) => Self::SI(value - input.val()),
290 }
291 }
292}
293
294impl<T> Mul for ByteUnit<T>
295where
296 i64: From<T>,
297 T: Copy + Mul<Output = T>,
298{
299 type Output = Self;
300
301 fn mul(self, input: Self) -> Self::Output {
302 match self {
303 Self::IEC(value) => Self::IEC(value * input.val()),
304 Self::SI(value) => Self::SI(value * input.val()),
305 }
306 }
307}
308
309impl<T> Div for ByteUnit<T>
310where
311 i64: From<T>,
312 T: Copy + Div<Output = T>,
313{
314 type Output = Self;
315
316 fn div(self, input: Self) -> Self::Output {
317 match self {
318 Self::IEC(value) => Self::IEC(value / input.val()),
319 Self::SI(value) => Self::SI(value / input.val()),
320 }
321 }
322}