unity_types/
digital.rs

1use serde::{Deserialize, Serialize};
2use std::cmp::Ordering;
3use std::fmt;
4use std::hash::{Hash, Hasher};
5
6#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy, Deserialize, Serialize)]
7#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
8pub enum DigitalUnit {
9    Byte,
10    Kilobyte,
11    Megabyte,
12    Gigabyte,
13}
14
15impl DigitalUnit {
16    fn to_bytes(&self) -> f64 {
17        match self {
18            DigitalUnit::Byte => 1.0,
19            DigitalUnit::Kilobyte => 1_000.0,
20            DigitalUnit::Megabyte => 1_000_000.0,
21            DigitalUnit::Gigabyte => 1_000_000_000.0,
22        }
23    }
24}
25
26impl fmt::Display for DigitalUnit {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        use DigitalUnit::*;
29        let s = match self {
30            Byte => "byte",
31            Kilobyte => "kilobyte",
32            Megabyte => "megabyte",
33            Gigabyte => "gigabyte",
34        };
35        write!(f, "{}", s)
36    }
37}
38
39#[derive(PartialEq, PartialOrd, Debug, Clone, Deserialize, Serialize)]
40pub struct DigitalValue {
41    pub value: f64,
42    unit: DigitalUnit,
43    #[serde(rename="__typename")]
44    type_name: Option<String>
45}
46
47impl DigitalValue {
48    pub fn to_bytes(self) -> DigitalValue {
49        self.convert_to(DigitalUnit::Byte)
50    }
51    pub fn to_kilobytes(self) -> DigitalValue {
52        self.convert_to(DigitalUnit::Kilobyte)
53    }
54    pub fn to_megabytes(self) -> DigitalValue {
55        self.convert_to(DigitalUnit::Megabyte)
56    }
57    pub fn to_gigabytes(self) -> DigitalValue {
58        self.convert_to(DigitalUnit::Gigabyte)
59    }
60
61    fn convert_to(self, target_unit: DigitalUnit) -> DigitalValue {
62        let bytes = self.value * self.unit.to_bytes();
63        let converted_value = bytes / target_unit.to_bytes();
64        DigitalValue {
65            value: converted_value,
66            unit: target_unit,
67            type_name: None,
68        }
69    }
70}
71
72impl Eq for DigitalValue {}
73
74impl Ord for DigitalValue {
75    fn cmp(&self, other: &Self) -> Ordering {
76        let self_bytes = self.value * self.unit.to_bytes();
77        let other_bytes = other.value * other.unit.to_bytes();
78
79        // Compare by converted values first
80        match self_bytes.total_cmp(&other_bytes) {
81            Ordering::Equal => self.unit.cmp(&other.unit),
82            other => other,
83        }
84    }
85}
86
87impl Hash for DigitalValue {
88    fn hash<H: Hasher>(&self, state: &mut H) {
89        self.value.to_bits().hash(state);
90        self.unit.hash(state);
91    }
92}
93
94impl fmt::Display for DigitalValue {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        write!(f, "{} {}", self.value, self.unit)
97    }
98}
99
100#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Deserialize, Serialize)]
101#[serde(untagged)]
102pub enum Size {
103    Bytes(usize),
104    DigitalValue(DigitalValue),
105}
106
107impl fmt::Display for Size {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        use Size::*;
110        match self {
111            Bytes(bytes) => {
112                write!(f, "{} byte", bytes)
113            }
114            DigitalValue(d) => {
115                write!(f, "{} {}", d.value, d.unit)
116            }
117        }
118    }
119}