rabbitmq_stream_client/
byte_capacity.rs1pub const KILOBYTE: u64 = 1000;
2pub const MEGABYTE: u64 = 1000 * KILOBYTE;
3pub const GIGABYTE: u64 = 1000 * MEGABYTE;
4pub const TERABYTE: u64 = 1000 * GIGABYTE;
5
6pub enum ByteCapacity {
7 B(u64),
8 KB(u64),
9 MB(u64),
10 GB(u64),
11 TB(u64),
12}
13
14impl ByteCapacity {
15 pub fn bytes(&self) -> u64 {
16 match self {
17 ByteCapacity::B(x) => *x,
18 ByteCapacity::KB(x) => x * KILOBYTE,
19 ByteCapacity::MB(x) => x * MEGABYTE,
20 ByteCapacity::GB(x) => x * GIGABYTE,
21 ByteCapacity::TB(x) => x * TERABYTE,
22 }
23 }
24}
25
26#[cfg(feature = "serde")]
27impl<'de> serde::Deserialize<'de> for ByteCapacity {
28 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
29 where
30 D: serde::Deserializer<'de>,
31 {
32 use serde::Deserialize;
33
34 #[derive(Deserialize)]
35 #[serde(untagged)]
36 enum StringOrNumber {
37 String(String),
38 Number(u64),
39 }
40
41 macro_rules! match_suffix {
42 ($str: ident, $suf: expr, $variant: expr) => {
43 if $str.ends_with($suf) {
44 let num = $str
45 .trim_end_matches($suf)
46 .parse()
47 .map_err(serde::de::Error::custom)?;
48 return Ok(($variant)(num));
49 }
50 };
51 }
52
53 let s_or_n = StringOrNumber::deserialize(deserializer)?;
54
55 match s_or_n {
56 StringOrNumber::String(str) => {
57 match_suffix!(str, "TB", ByteCapacity::TB);
58 match_suffix!(str, "GB", ByteCapacity::GB);
59 match_suffix!(str, "MB", ByteCapacity::MB);
60 match_suffix!(str, "KB", ByteCapacity::KB);
61 match_suffix!(str, "B", ByteCapacity::B);
62
63 let num = str.parse().map_err(|_| {
64 serde::de::Error::custom(
65 "Expect a number or a string with a TB|GB|MB|KB|B suffix",
66 )
67 })?;
68 Ok(ByteCapacity::B(num))
69 }
70 StringOrNumber::Number(num) => Ok(ByteCapacity::B(num)),
71 }
72 }
73}
74
75#[cfg(feature = "serde")]
76mod tests {
77 #[test]
78 fn test_deserilize_byte_capacity() {
79 use crate::types::ByteCapacity;
80
81 assert!(matches!(
82 serde_json::from_str::<ByteCapacity>("\"5GB\""),
83 Ok(ByteCapacity::GB(5))
84 ));
85 assert!(matches!(
86 serde_json::from_str::<ByteCapacity>("\"5TB\""),
87 Ok(ByteCapacity::TB(5))
88 ));
89 assert!(matches!(
90 serde_json::from_str::<ByteCapacity>("\"5MB\""),
91 Ok(ByteCapacity::MB(5))
92 ));
93 assert!(matches!(
94 serde_json::from_str::<ByteCapacity>("\"5KB\""),
95 Ok(ByteCapacity::KB(5))
96 ));
97 assert!(matches!(
98 serde_json::from_str::<ByteCapacity>("\"5B\""),
99 Ok(ByteCapacity::B(5))
100 ));
101 assert!(matches!(
102 serde_json::from_str::<ByteCapacity>("\"5\""),
103 Ok(ByteCapacity::B(5))
104 ));
105 assert!(matches!(
106 serde_json::from_str::<ByteCapacity>("5"),
107 Ok(ByteCapacity::B(5))
108 ));
109 let err = serde_json::from_str::<ByteCapacity>("\"Wrong string format\"")
110 .err()
111 .expect("Expect an error");
112 assert_eq!(
113 err.to_string(),
114 "Expect a number or a string with a TB|GB|MB|KB|B suffix"
115 );
116 }
117}