kutil_std/metric/
byte_count.rs1use super::{super::string::*, units::*};
2
3use std::{fmt, num::*, str::*};
4
5#[derive(Clone, Copy, Debug, Default)]
11pub struct ByteCount(pub u64);
12
13impl ByteCount {
14 pub fn from_bytes(bytes: u64) -> Self {
16 Self(bytes)
17 }
18
19 pub fn from_kibibytes(kibibytes: u64) -> Self {
21 Self(kibibytes * KIBI)
22 }
23
24 pub fn from_mebibytes(mebibytes: u64) -> Self {
26 Self(mebibytes * MEBI)
27 }
28
29 pub fn from_gibibytes(gibibytes: u64) -> Self {
31 Self(gibibytes * GIBI)
32 }
33
34 pub fn from_tebibytes(tebibytes: u64) -> Self {
36 Self(tebibytes * TEBI)
37 }
38
39 fn split(representation: &str) -> Option<(&str, &str)> {
40 for (index, c) in representation.char_indices().rev() {
41 if c == ' ' {
42 return Some((&representation[..index], &representation[index + 1..]));
43 }
44
45 if c.is_ascii_digit() {
46 let index = index + 1;
47 return Some((&representation[..index], &representation[index..]));
48 }
49 }
50
51 None
52 }
53}
54
55impl From<u64> for ByteCount {
56 fn from(bytes: u64) -> Self {
57 Self(bytes)
58 }
59}
60
61impl Into<u64> for ByteCount {
62 fn into(self) -> u64 {
63 self.0
64 }
65}
66
67impl Into<usize> for ByteCount {
68 fn into(self) -> usize {
69 self.0 as usize
71 }
72}
73
74impl FromStr for ByteCount {
75 type Err = ParseError;
76
77 fn from_str(representation: &str) -> Result<Self, Self::Err> {
78 match Self::split(representation) {
79 Some((number, unit)) => {
80 let unit = parse_metric_unit(unit)?;
81
82 let integer: Result<u64, _> = number.parse();
83 match integer {
84 Ok(integer) => Ok(Self(integer * unit)),
85
86 Err(_) => {
87 let float: f64 = number.parse().map_err(|error: ParseFloatError| error.to_string())?;
88
89 if float >= 0.0 {
90 let unit = unit as f64;
92 Ok(Self((float * unit).round() as u64))
93 } else {
94 Err("cannot be negative".into())
95 }
96 }
97 }
98 }
99
100 None => Ok(Self(representation.parse().map_err(|error: ParseIntError| error.to_string())?)),
101 }
102 }
103}
104
105impl fmt::Display for ByteCount {
106 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(formatter, "{} bytes", self.0)
108 }
109}