|
30 | 30 | mod parse;
|
31 | 31 |
|
32 | 32 | #[cfg(feature = "serde")]
|
33 |
| -#[macro_use] |
34 | 33 | extern crate serde;
|
| 34 | +#[cfg(feature = "serde")] |
| 35 | +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; |
| 36 | +#[cfg(feature = "serde")] |
| 37 | +use std::convert::TryFrom; |
35 | 38 |
|
36 |
| -use std::fmt::{Debug, Display, Formatter, Result}; |
| 39 | +use std::fmt::{self, Debug, Display, Formatter}; |
37 | 40 | use std::ops::{Add, AddAssign, Mul, MulAssign};
|
38 | 41 |
|
39 | 42 | /// byte size for 1 byte
|
@@ -107,7 +110,6 @@ pub fn pib<V: Into<u64>>(size: V) -> u64 {
|
107 | 110 |
|
108 | 111 | /// Byte size representation
|
109 | 112 | #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
|
110 |
| -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] |
111 | 113 | pub struct ByteSize(pub u64);
|
112 | 114 |
|
113 | 115 | impl ByteSize {
|
@@ -206,13 +208,13 @@ pub fn to_string(bytes: u64, si_prefix: bool) -> String {
|
206 | 208 | }
|
207 | 209 |
|
208 | 210 | impl Display for ByteSize {
|
209 |
| - fn fmt(&self, f: &mut Formatter) -> Result { |
| 211 | + fn fmt(&self, f: &mut Formatter) ->fmt::Result { |
210 | 212 | f.pad(&to_string(self.0, false))
|
211 | 213 | }
|
212 | 214 | }
|
213 | 215 |
|
214 | 216 | impl Debug for ByteSize {
|
215 |
| - fn fmt(&self, f: &mut Formatter) -> Result { |
| 217 | + fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
216 | 218 | write!(f, "{}", self)
|
217 | 219 | }
|
218 | 220 | }
|
@@ -292,6 +294,70 @@ impl<T> MulAssign<T> for ByteSize
|
292 | 294 | }
|
293 | 295 | }
|
294 | 296 |
|
| 297 | +#[cfg(feature = "serde")] |
| 298 | +impl<'de> Deserialize<'de> for ByteSize { |
| 299 | + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
| 300 | + where |
| 301 | + D: Deserializer<'de>, |
| 302 | + { |
| 303 | + struct ByteSizeVistor; |
| 304 | + |
| 305 | + impl<'de> de::Visitor<'de> for ByteSizeVistor { |
| 306 | + type Value = ByteSize; |
| 307 | + |
| 308 | + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 309 | + formatter.write_str("an integer or string") |
| 310 | + } |
| 311 | + |
| 312 | + fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> { |
| 313 | + if let Ok(val) = u64::try_from(value) { |
| 314 | + Ok(ByteSize(val)) |
| 315 | + } else { |
| 316 | + Err(E::invalid_value( |
| 317 | + de::Unexpected::Signed(value), |
| 318 | + &"integer overflow", |
| 319 | + )) |
| 320 | + } |
| 321 | + } |
| 322 | + |
| 323 | + fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> { |
| 324 | + Ok(ByteSize(value)) |
| 325 | + } |
| 326 | + |
| 327 | + fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> { |
| 328 | + if let Ok(val) = value.parse() { |
| 329 | + Ok(val) |
| 330 | + } else { |
| 331 | + Err(E::invalid_value( |
| 332 | + de::Unexpected::Str(value), |
| 333 | + &"parsable string", |
| 334 | + )) |
| 335 | + } |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | + if deserializer.is_human_readable() { |
| 340 | + deserializer.deserialize_any(ByteSizeVistor) |
| 341 | + } else { |
| 342 | + deserializer.deserialize_u64(ByteSizeVistor) |
| 343 | + } |
| 344 | + } |
| 345 | +} |
| 346 | + |
| 347 | +#[cfg(feature = "serde")] |
| 348 | +impl Serialize for ByteSize { |
| 349 | + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
| 350 | + where |
| 351 | + S: Serializer, |
| 352 | + { |
| 353 | + if serializer.is_human_readable() { |
| 354 | + <str>::serialize(self.to_string().as_str(), serializer) |
| 355 | + } else { |
| 356 | + self.0.serialize(serializer) |
| 357 | + } |
| 358 | + } |
| 359 | +} |
| 360 | + |
295 | 361 | #[cfg(test)]
|
296 | 362 | mod tests {
|
297 | 363 | use super::*;
|
@@ -327,8 +393,8 @@ mod tests {
|
327 | 393 |
|
328 | 394 | x += MB as u64;
|
329 | 395 | x += MB as u32;
|
330 |
| - x += 10 as u16; |
331 |
| - x += 1 as u8; |
| 396 | + x += 10u16; |
| 397 | + x += 1u8; |
332 | 398 | assert_eq!(x.as_u64(), 3_000_011);
|
333 | 399 | }
|
334 | 400 |
|
@@ -412,4 +478,26 @@ mod tests {
|
412 | 478 | fn test_to_string() {
|
413 | 479 | assert_to_string("609.0 PB", ByteSize::pb(609), false);
|
414 | 480 | }
|
| 481 | + |
| 482 | + #[cfg(feature = "serde")] |
| 483 | + #[test] |
| 484 | + fn test_serde() { |
| 485 | + #[derive(Serialize, Deserialize)] |
| 486 | + struct S { |
| 487 | + x: ByteSize, |
| 488 | + } |
| 489 | + |
| 490 | + let s: S = serde_json::from_str(r#"{ "x": "5 B" }"#).unwrap(); |
| 491 | + assert_eq!(s.x, ByteSize(5)); |
| 492 | + |
| 493 | + let s: S = serde_json::from_str(r#"{ "x": 1048576 }"#).unwrap(); |
| 494 | + assert_eq!(s.x, "1 MiB".parse::<ByteSize>().unwrap()); |
| 495 | + |
| 496 | + let s: S = toml::from_str(r#"x = "2.5 MiB""#).unwrap(); |
| 497 | + assert_eq!(s.x, "2.5 MiB".parse::<ByteSize>().unwrap()); |
| 498 | + |
| 499 | + // i64 MAX |
| 500 | + let s: S = toml::from_str(r#"x = "9223372036854775807""#).unwrap(); |
| 501 | + assert_eq!(s.x, "9223372036854775807".parse::<ByteSize>().unwrap()); |
| 502 | + } |
415 | 503 | }
|
0 commit comments