1use std::{
2 cmp::Ordering,
3 fmt::Display,
4 hash::{Hash, Hasher},
5};
6
7use NetworkSize::*;
8
9use crate::error::NetworkSizeError;
10
11#[derive(Debug, Clone, Copy)]
28pub enum NetworkSize {
29 V4(u32),
30 V6(u128),
31}
32
33impl NetworkSize {
34 fn as_u128(&self) -> u128 {
36 match *self {
37 V4(a) => a as u128,
38 V6(a) => a,
39 }
40 }
41}
42
43impl From<u32> for NetworkSize {
44 fn from(value: u32) -> Self {
45 V4(value)
46 }
47}
48
49impl From<u128> for NetworkSize {
50 fn from(value: u128) -> Self {
51 V6(value)
52 }
53}
54
55impl TryFrom<NetworkSize> for u32 {
56 type Error = NetworkSizeError;
57 fn try_from(value: NetworkSize) -> Result<Self, Self::Error> {
58 match value {
59 V4(a) => Ok(a),
60 V6(_) => Err(NetworkSizeError::NetworkIsTooLarge),
61 }
62 }
63}
64
65impl From<NetworkSize> for u128 {
66 fn from(val: NetworkSize) -> Self {
67 val.as_u128()
68 }
69}
70
71impl PartialEq for NetworkSize {
72 fn eq(&self, other: &Self) -> bool {
73 let a = self.as_u128();
74 let b = other.as_u128();
75 a == b
76 }
77}
78
79impl Eq for NetworkSize {}
80
81impl Hash for NetworkSize {
82 fn hash<H: Hasher>(&self, state: &mut H) {
83 let a = self.as_u128();
84 a.hash(state);
85 }
86}
87
88impl Ord for NetworkSize {
89 fn cmp(&self, other: &Self) -> Ordering {
90 let a = self.as_u128();
91 let b = other.as_u128();
92 a.cmp(&b)
93 }
94}
95
96impl PartialOrd for NetworkSize {
97 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98 Some(self.cmp(other))
99 }
100}
101
102impl Display for NetworkSize {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 write!(f, "{}", self.as_u128())
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_from_u128() {
114 let value: u128 = 100;
115 let ns = NetworkSize::from(value);
116 assert_eq!(ns, V6(100));
117 }
118
119 #[test]
120 fn test_from_u32() {
121 let value: u32 = 100;
122 let ns = NetworkSize::from(value);
123 assert_eq!(ns, V4(100));
124 }
125
126 #[test]
127 fn test_try_into_u32() {
128 let value: u32 = 100;
129 let ns = V4(value);
130 let result: Result<u32, _> = ns.try_into();
131 assert!(result.is_ok());
132 assert_eq!(result.unwrap(), value);
133 }
134
135 #[test]
136 fn test_try_into_u32_error() {
137 let value: u128 = u32::MAX as u128 + 1;
138 let ns = V6(value);
139 let result: Result<u32, _> = ns.try_into();
140 assert!(result.is_err());
141 }
142
143 #[test]
144 fn test_into_u128() {
145 let value: u32 = 100;
146 let ns = V4(value);
147 let result: u128 = ns.into();
148 assert_eq!(result, value as u128);
149 }
150
151 #[test]
152 fn test_eq() {
153 let ns1 = V4(100);
154 let ns2 = V4(100);
155 assert_eq!(ns1, ns2);
156
157 let ns1 = V6(100);
158 let ns2 = V6(100);
159 assert_eq!(ns1, ns2);
160
161 let ns1 = V4(100);
162 let ns2 = V6(100);
163 assert_eq!(ns1, ns2);
164 }
165
166 #[test]
167 fn test_cmp() {
168 let ns1 = V4(100);
169 let ns2 = V4(200);
170 assert!(ns1 < ns2);
171
172 let ns1 = V6(200);
173 let ns2 = V6(100);
174 assert!(ns1 > ns2);
175
176 let ns1 = V4(100);
177 let ns2 = V6(200);
178 assert!(ns1 < ns2);
179 }
180
181 #[test]
182 fn test_display() {
183 let ns1 = V4(u32::MAX);
184 let ns2 = V6(ns1.into());
185 assert_eq!(ns1.to_string(), ns2.to_string());
186 }
187
188 #[test]
190 fn test_hash() {
191 let a = NetworkSize::V4(100);
192 let b = NetworkSize::V6(100);
193
194 let mut hasher = std::hash::DefaultHasher::default();
196 a.hash(&mut hasher);
197 let hash_a = hasher.finish();
198
199 let mut hasher = std::hash::DefaultHasher::default();
200 b.hash(&mut hasher);
201 let hash_b = hasher.finish();
202
203 assert_eq!(a, b);
205 assert_eq!(hash_a, hash_b);
207 }
208}