1 use core::convert::TryFrom; 2 use core::str::FromStr; 3 4 #[cfg(feature = "serde")] 5 use alloc::string::String; 6 7 use alloc::fmt::{self, Display, Formatter}; 8 9 use crate::{ 10 get_char_from_bytes, read_xib, AdjustedByte, ByteError, ByteUnit, ValueIncorrectError, 11 }; 12 13 #[cfg(feature = "serde")] 14 use crate::serde::ser::{Serialize, Serializer}; 15 16 #[cfg(feature = "serde")] 17 use crate::serde::de::{Deserialize, Deserializer, Error as DeError, Unexpected, Visitor}; 18 19 #[cfg(feature = "u128")] 20 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)] 21 /// Represent the n-bytes data. Use associated functions: `from_unit`, `from_bytes`, `from_str`, to create the instance. 22 pub struct Byte(u128); 23 24 #[cfg(not(feature = "u128"))] 25 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)] 26 /// Represent the n-bytes data. Use associated functions: `from_unit`, `from_bytes`, `from_str`, to create the instance. 27 pub struct Byte(u64); 28 29 impl Byte { 30 /// Create a new `Byte` object from a specified value and a unit. **Accuracy** should be taken care of. specialcase(v_f32_t poly,v_f32_t n,v_u32_t e,v_f32_t absn)31 /// 32 /// ## Examples 33 /// 34 /// ``` 35 /// extern crate byte_unit; 36 /// 37 /// use byte_unit::{Byte, ByteUnit}; 38 /// 39 /// let result = Byte::from_unit(1500f64, ByteUnit::KB).unwrap(); 40 /// 41 /// assert_eq!(1500000, result.get_bytes()); 42 /// ``` 43 #[inline] 44 pub fn from_unit(value: f64, unit: ByteUnit) -> Result<Byte, ByteError> { 45 if value < 0f64 { 46 return Err(ValueIncorrectError::Negative(value).into()); 47 } 48 49 let bytes = get_bytes(value, unit); 50 51 Ok(Byte(bytes)) 52 } 53 54 /// Create a new `Byte` object from bytes. 55 /// 56 /// ## Examples 57 /// 58 /// ``` 59 /// extern crate byte_unit; 60 /// 61 /// use byte_unit::{Byte, ByteUnit}; 62 /// 63 /// let result = Byte::from_bytes(1500000); 64 /// 65 /// assert_eq!(1500000, result.get_bytes()); 66 /// ``` 67 #[cfg(feature = "u128")] 68 #[inline] 69 pub const fn from_bytes(bytes: u128) -> Byte { 70 Byte(bytes) 71 } 72 73 /// Create a new `Byte` object from bytes. 74 /// 75 /// ## Examples 76 /// 77 /// ``` 78 /// extern crate byte_unit; 79 /// 80 /// use byte_unit::{Byte, ByteUnit}; 81 /// 82 /// let result = Byte::from_bytes(1500000); 83 /// 84 /// assert_eq!(1500000, result.get_bytes()); 85 /// ``` 86 #[cfg(not(feature = "u128"))] 87 #[inline] 88 pub const fn from_bytes(bytes: u64) -> Byte { 89 Byte(bytes) 90 } 91 92 /// Create a new `Byte` object from string. **Accuracy** should be taken care of. 93 /// 94 /// ## Examples 95 /// 96 /// ``` 97 /// extern crate byte_unit; 98 /// 99 /// use byte_unit::{Byte, ByteUnit}; 100 /// 101 /// let result = Byte::from_str("123KiB").unwrap(); 102 /// 103 /// assert_eq!(Byte::from_unit(123f64, ByteUnit::KiB).unwrap(), result); 104 /// ``` 105 /// 106 /// ``` 107 /// extern crate byte_unit; 108 /// 109 /// use byte_unit::{Byte, ByteUnit}; 110 /// 111 /// let result = Byte::from_str("50.84 MB").unwrap(); 112 /// 113 /// assert_eq!(Byte::from_unit(50.84f64, ByteUnit::MB).unwrap(), result); 114 /// ``` 115 /// 116 /// ``` 117 /// extern crate byte_unit; 118 /// 119 /// use byte_unit::{Byte, ByteUnit}; 120 /// 121 /// let result = Byte::from_str("8 B").unwrap(); // 8 bytes 122 /// 123 /// assert_eq!(8, result.get_bytes()); 124 /// ``` 125 /// 126 /// ``` 127 /// extern crate byte_unit; 128 /// 129 /// use byte_unit::{Byte, ByteUnit}; 130 /// 131 /// let result = Byte::from_str("8").unwrap(); // 8 bytes 132 /// 133 /// assert_eq!(8, result.get_bytes()); 134 /// ``` 135 /// 136 /// ``` 137 /// extern crate byte_unit; 138 /// 139 /// use byte_unit::{Byte, ByteUnit}; 140 /// 141 /// let result = Byte::from_str("8 b").unwrap(); // 8 bytes 142 /// 143 /// assert_eq!(8, result.get_bytes()); 144 /// ``` 145 /// 146 /// ``` 147 /// extern crate byte_unit; 148 /// 149 /// use byte_unit::{Byte, ByteUnit}; 150 /// 151 /// let result = Byte::from_str("8 kb").unwrap(); // 8 kilobytes 152 /// 153 /// assert_eq!(8000, result.get_bytes()); 154 /// ``` 155 /// 156 /// ``` 157 /// extern crate byte_unit; 158 /// 159 /// use byte_unit::{Byte, ByteUnit}; 160 /// 161 /// let result = Byte::from_str("8 kib").unwrap(); // 8 kibibytes 162 /// 163 /// assert_eq!(8192, result.get_bytes()); 164 /// ``` 165 /// 166 /// ``` 167 /// extern crate byte_unit; 168 /// 169 /// use byte_unit::{Byte, ByteUnit}; 170 /// 171 /// let result = Byte::from_str("8 k").unwrap(); // 8 kilobytes 172 /// 173 /// assert_eq!(8000, result.get_bytes()); 174 /// ``` 175 #[inline] 176 #[allow(clippy::should_implement_trait)] 177 pub fn from_str<S: AsRef<str>>(s: S) -> Result<Byte, ByteError> { 178 let s = s.as_ref().trim(); 179 180 let mut bytes = s.bytes(); 181 182 let mut value = match bytes.next() { 183 Some(e) => { 184 match e { 185 b'0'..=b'9' => f64::from(e - b'0'), 186 _ => { 187 return Err( 188 ValueIncorrectError::NotNumber(get_char_from_bytes(e, bytes)).into() 189 ); 190 } 191 } 192 } 193 None => return Err(ValueIncorrectError::NoValue.into()), 194 }; 195 196 let e = 'outer: loop { 197 match bytes.next() { 198 Some(e) => { 199 match e { 200 b'0'..=b'9' => { 201 value = value * 10.0 + f64::from(e - b'0'); 202 } 203 b'.' => { 204 let mut i = 0.1; 205 206 loop { 207 match bytes.next() { 208 Some(e) => { 209 match e { 210 b'0'..=b'9' => { 211 value += f64::from(e - b'0') * i; 212 213 i /= 10.0; 214 } 215 _ => { 216 if (i * 10.0) as u8 == 1 { 217 return Err(ValueIncorrectError::NotNumber( 218 get_char_from_bytes(e, bytes), 219 ) 220 .into()); 221 } 222 223 match e { 224 b' ' => { 225 loop { 226 match bytes.next() { 227 Some(e) => { 228 match e { 229 b' ' => (), 230 _ => break 'outer Some(e), 231 } 232 } 233 None => break 'outer None, 234 } 235 } 236 } 237 _ => break 'outer Some(e), 238 } 239 } 240 } 241 } 242 None => { 243 if (i * 10.0) as u8 == 1 { 244 return Err(ValueIncorrectError::NotNumber( 245 get_char_from_bytes(e, bytes), 246 ) 247 .into()); 248 } 249 250 break 'outer None; 251 } 252 } 253 } 254 } 255 b' ' => { 256 loop { 257 match bytes.next() { 258 Some(e) => { 259 match e { 260 b' ' => (), 261 _ => break 'outer Some(e), 262 } 263 } 264 None => break 'outer None, 265 } 266 } 267 } 268 _ => break 'outer Some(e), 269 } 270 } 271 None => break None, 272 } 273 }; 274 275 let unit = read_xib(e, bytes)?; 276 277 let bytes = get_bytes(value, unit); 278 279 Ok(Byte(bytes)) 280 } 281 } 282 283 impl Byte { 284 /// Get bytes represented by a `Byte` object. 285 /// 286 /// ## Examples 287 /// 288 /// ``` 289 /// extern crate byte_unit; 290 /// 291 /// use byte_unit::Byte; 292 /// 293 /// let byte = Byte::from_str("123KiB").unwrap(); 294 /// 295 /// let result = byte.get_bytes(); 296 /// 297 /// assert_eq!(125952, result); 298 /// ``` 299 /// 300 /// ``` 301 /// extern crate byte_unit; 302 /// 303 /// use byte_unit::Byte; 304 /// 305 /// let byte = Byte::from_str("50.84 MB").unwrap(); 306 /// 307 /// let result = byte.get_bytes(); 308 /// 309 /// assert_eq!(50840000, result); 310 /// ``` 311 #[cfg(feature = "u128")] 312 #[inline] 313 pub const fn get_bytes(&self) -> u128 { 314 self.0 315 } 316 317 /// Get bytes represented by a `Byte` object. 318 /// 319 /// ## Examples 320 /// 321 /// ``` 322 /// extern crate byte_unit; 323 /// 324 /// use byte_unit::Byte; 325 /// 326 /// let byte = Byte::from_str("123KiB").unwrap(); 327 /// 328 /// let result = byte.get_bytes(); 329 /// 330 /// assert_eq!(125952, result); 331 /// ``` 332 /// 333 /// ``` 334 /// extern crate byte_unit; 335 /// 336 /// use byte_unit::Byte; 337 /// 338 /// let byte = Byte::from_str("50.84 MB").unwrap(); 339 /// 340 /// let result = byte.get_bytes(); 341 /// 342 /// assert_eq!(50840000, result); 343 /// ``` 344 #[cfg(not(feature = "u128"))] 345 #[inline] 346 pub const fn get_bytes(&self) -> u64 { 347 self.0 348 } 349 350 /// Adjust the unit and value for `Byte` object. **Accuracy** should be taken care of. 351 /// 352 /// ## Examples 353 /// 354 /// ``` 355 /// extern crate byte_unit; 356 /// 357 /// use byte_unit::{Byte, ByteUnit}; 358 /// 359 /// let byte = Byte::from_str("123KiB").unwrap(); 360 /// 361 /// let adjusted_byte = byte.get_adjusted_unit(ByteUnit::KB); 362 /// 363 /// assert_eq!("125.95 KB", adjusted_byte.to_string()); 364 /// ``` 365 /// 366 /// ``` 367 /// extern crate byte_unit; 368 /// 369 /// use byte_unit::{Byte, ByteUnit}; 370 /// 371 /// let byte = Byte::from_str("50.84 MB").unwrap(); 372 /// 373 /// let adjusted_byte = byte.get_adjusted_unit(ByteUnit::MiB); 374 /// 375 /// assert_eq!("48.48 MiB", adjusted_byte.to_string()); 376 /// ``` 377 #[inline] 378 pub fn get_adjusted_unit(&self, unit: ByteUnit) -> AdjustedByte { 379 let bytes_f64 = self.0 as f64; 380 381 let value = bytes_f64 / unit.get_unit_bytes() as f64; 382 383 AdjustedByte { 384 value, 385 unit, 386 } 387 } 388 389 /// Find the appropriate unit and value for `Byte` object. **Accuracy** should be taken care of. 390 /// 391 /// ## Examples 392 /// 393 /// ``` 394 /// extern crate byte_unit; 395 /// 396 /// use byte_unit::Byte; 397 /// 398 /// let byte = Byte::from_str("123KiB").unwrap(); 399 /// 400 /// let adjusted_byte = byte.get_appropriate_unit(false); 401 /// 402 /// assert_eq!("125.95 KB", adjusted_byte.to_string()); 403 /// ``` 404 /// 405 /// ``` 406 /// extern crate byte_unit; 407 /// 408 /// use byte_unit::Byte; 409 /// 410 /// let byte = Byte::from_str("50.84 MB").unwrap(); 411 /// 412 /// let adjusted_byte = byte.get_appropriate_unit(true); 413 /// 414 /// assert_eq!("48.48 MiB", adjusted_byte.to_string()); 415 /// ``` 416 #[allow(clippy::collapsible_if)] 417 pub fn get_appropriate_unit(&self, binary_multiples: bool) -> AdjustedByte { 418 let bytes = self.0; 419 420 if binary_multiples { 421 #[cfg(feature = "u128")] 422 { 423 if bytes > n_zib_bytes!() { 424 return self.get_adjusted_unit(ByteUnit::ZiB); 425 } else if bytes > n_eib_bytes!() { 426 return self.get_adjusted_unit(ByteUnit::EiB); 427 } 428 } 429 430 if bytes > n_pib_bytes!() { 431 self.get_adjusted_unit(ByteUnit::PiB) 432 } else if bytes > n_tib_bytes!() { 433 self.get_adjusted_unit(ByteUnit::TiB) 434 } else if bytes > n_gib_bytes!() { 435 self.get_adjusted_unit(ByteUnit::GiB) 436 } else if bytes > n_mib_bytes!() { 437 self.get_adjusted_unit(ByteUnit::MiB) 438 } else if bytes > n_kib_bytes!() { 439 self.get_adjusted_unit(ByteUnit::KiB) 440 } else { 441 self.get_adjusted_unit(ByteUnit::B) 442 } 443 } else { 444 #[cfg(feature = "u128")] 445 { 446 if bytes > n_zb_bytes!() { 447 return self.get_adjusted_unit(ByteUnit::ZB); 448 } else if bytes > n_eb_bytes!() { 449 return self.get_adjusted_unit(ByteUnit::EB); 450 } 451 } 452 453 if bytes > n_pb_bytes!() { 454 self.get_adjusted_unit(ByteUnit::PB) 455 } else if bytes > n_tb_bytes!() { 456 self.get_adjusted_unit(ByteUnit::TB) 457 } else if bytes > n_gb_bytes!() { 458 self.get_adjusted_unit(ByteUnit::GB) 459 } else if bytes > n_mb_bytes!() { 460 self.get_adjusted_unit(ByteUnit::MB) 461 } else if bytes > n_kb_bytes!() { 462 self.get_adjusted_unit(ByteUnit::KB) 463 } else { 464 self.get_adjusted_unit(ByteUnit::B) 465 } 466 } 467 } 468 } 469 470 impl Display for Byte { 471 #[inline] 472 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { 473 f.write_fmt(format_args!("{}", self.0)) 474 } 475 } 476 477 #[cfg(feature = "u128")] 478 impl From<Byte> for u128 { 479 #[inline] 480 fn from(b: Byte) -> u128 { 481 b.0 482 } 483 } 484 485 #[cfg(not(feature = "u128"))] 486 impl From<Byte> for u64 { 487 #[inline] 488 fn from(b: Byte) -> u64 { 489 b.0 490 } 491 } 492 493 #[cfg(feature = "u128")] 494 impl From<u128> for Byte { 495 #[inline] 496 fn from(u: u128) -> Self { 497 Byte::from_bytes(u) 498 } 499 } 500 501 #[cfg(feature = "u128")] 502 impl From<usize> for Byte { 503 #[inline] 504 fn from(u: usize) -> Self { 505 Byte::from_bytes(u as u128) 506 } 507 } 508 509 #[cfg(not(feature = "u128"))] 510 impl From<usize> for Byte { 511 #[inline] 512 fn from(u: usize) -> Self { 513 Byte::from_bytes(u as u64) 514 } 515 } 516 517 #[cfg(feature = "u128")] 518 impl From<u64> for Byte { 519 #[inline] 520 fn from(u: u64) -> Self { 521 Byte::from_bytes(u as u128) 522 } 523 } 524 525 #[cfg(not(feature = "u128"))] 526 impl From<u64> for Byte { 527 #[inline] 528 fn from(u: u64) -> Self { 529 Byte::from_bytes(u) 530 } 531 } 532 533 #[cfg(feature = "u128")] 534 impl From<u32> for Byte { 535 #[inline] 536 fn from(u: u32) -> Self { 537 Byte::from_bytes(u as u128) 538 } 539 } 540 541 #[cfg(not(feature = "u128"))] 542 impl From<u32> for Byte { 543 #[inline] 544 fn from(u: u32) -> Self { 545 Byte::from_bytes(u as u64) 546 } 547 } 548 549 #[cfg(feature = "u128")] 550 impl From<u16> for Byte { 551 #[inline] 552 fn from(u: u16) -> Self { 553 Byte::from_bytes(u as u128) 554 } 555 } 556 557 #[cfg(not(feature = "u128"))] 558 impl From<u16> for Byte { 559 #[inline] 560 fn from(u: u16) -> Self { 561 Byte::from_bytes(u as u64) 562 } 563 } 564 565 #[cfg(feature = "u128")] 566 impl From<u8> for Byte { 567 #[inline] 568 fn from(u: u8) -> Self { 569 Byte::from_bytes(u as u128) 570 } 571 } 572 573 #[cfg(not(feature = "u128"))] 574 impl From<u8> for Byte { 575 #[inline] 576 fn from(u: u8) -> Self { 577 Byte::from_bytes(u as u64) 578 } 579 } 580 581 impl TryFrom<&str> for Byte { 582 type Error = ByteError; 583 584 #[inline] 585 fn try_from(s: &str) -> Result<Self, Self::Error> { 586 Byte::from_str(s) 587 } 588 } 589 590 impl FromStr for Byte { 591 type Err = ByteError; 592 593 #[inline] 594 fn from_str(s: &str) -> Result<Self, Self::Err> { 595 Byte::from_str(s) 596 } 597 } 598 599 #[cfg(feature = "u128")] 600 #[inline] 601 pub(crate) fn get_bytes(value: f64, unit: ByteUnit) -> u128 { 602 match unit { 603 ByteUnit::B => value as u128, 604 ByteUnit::KB => n_kb_bytes!(value, f64), 605 ByteUnit::KiB => n_kib_bytes!(value, f64), 606 ByteUnit::MB => n_mb_bytes!(value, f64), 607 ByteUnit::MiB => n_mib_bytes!(value, f64), 608 ByteUnit::GB => n_gb_bytes!(value, f64), 609 ByteUnit::GiB => n_gib_bytes!(value, f64), 610 ByteUnit::TB => n_tb_bytes!(value, f64), 611 ByteUnit::TiB => n_tib_bytes!(value, f64), 612 ByteUnit::PB => n_pb_bytes!(value, f64), 613 ByteUnit::PiB => n_pib_bytes!(value, f64), 614 ByteUnit::EB => n_eb_bytes!(value, f64), 615 ByteUnit::EiB => n_eib_bytes!(value, f64), 616 ByteUnit::ZB => n_zb_bytes!(value, f64), 617 ByteUnit::ZiB => n_zib_bytes!(value, f64), 618 } 619 } 620 621 #[cfg(not(feature = "u128"))] 622 #[inline] 623 pub(crate) fn get_bytes(value: f64, unit: ByteUnit) -> u64 { 624 match unit { 625 ByteUnit::B => value as u64, 626 ByteUnit::KB => n_kb_bytes!(value, f64), 627 ByteUnit::KiB => n_kib_bytes!(value, f64), 628 ByteUnit::MB => n_mb_bytes!(value, f64), 629 ByteUnit::MiB => n_mib_bytes!(value, f64), 630 ByteUnit::GB => n_gb_bytes!(value, f64), 631 ByteUnit::GiB => n_gib_bytes!(value, f64), 632 ByteUnit::TB => n_tb_bytes!(value, f64), 633 ByteUnit::TiB => n_tib_bytes!(value, f64), 634 ByteUnit::PB => n_pb_bytes!(value, f64), 635 ByteUnit::PiB => n_pib_bytes!(value, f64), 636 } 637 } 638 639 #[cfg(feature = "serde")] 640 impl Serialize for Byte { 641 #[allow(unreachable_code)] 642 #[inline] 643 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 644 where 645 S: Serializer, { 646 #[cfg(feature = "u128")] 647 { 648 serde_if_integer128! { 649 return serializer.serialize_u128(self.get_bytes()); 650 } 651 652 unreachable!("the `integer128` feature of the `serde` crate needs to be enabled") 653 } 654 655 #[cfg(not(feature = "u128"))] 656 { 657 serializer.serialize_u64(self.get_bytes()) 658 } 659 } 660 } 661 662 #[cfg(feature = "serde")] 663 impl<'de> Deserialize<'de> for Byte { 664 #[inline] 665 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 666 where 667 D: Deserializer<'de>, { 668 struct ByteVisitor; 669 670 impl<'de> Visitor<'de> for ByteVisitor { 671 type Value = Byte; 672 673 serde_if_integer128! { 674 #[inline] 675 fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> 676 where 677 E: DeError, 678 { 679 if v < 0 { 680 Err(DeError::invalid_value(Unexpected::Other(format!("integer `{}`", v).as_str()), &self)) 681 } else { 682 #[cfg(feature = "u128")] 683 { 684 Ok(Byte::from_bytes(v as u128)) 685 } 686 687 #[cfg(not(feature = "u128"))] 688 { 689 if v > u64::max_value() as i128 { 690 Err(DeError::invalid_value(Unexpected::Other(format!("integer `{}`", v).as_str()), &self)) 691 } else { 692 Ok(Byte::from_bytes(v as u64)) 693 } 694 } 695 } 696 } 697 698 #[inline] 699 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> 700 where 701 E: DeError, 702 { 703 #[cfg(feature = "u128")] 704 { 705 Ok(Byte::from_bytes(v)) 706 } 707 708 #[cfg(not(feature = "u128"))] 709 { 710 if v > u64::max_value() as u128 { 711 Err(DeError::invalid_value(Unexpected::Other(format!("integer `{}`", v).as_str()), &self)) 712 } else { 713 Ok(Byte::from_bytes(v as u64)) 714 } 715 } 716 } 717 } 718 719 #[inline] 720 fn expecting(&self, f: &mut Formatter) -> Result<(), fmt::Error> { 721 f.write_str("a byte such as 123, \"123\", \"123KiB\" or \"50.84 MB\"") 722 } 723 724 #[inline] 725 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> 726 where 727 E: DeError, { 728 Byte::from_str(v).map_err(DeError::custom) 729 } 730 731 #[inline] 732 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> 733 where 734 E: DeError, { 735 Byte::from_str(v.as_str()).map_err(DeError::custom) 736 } 737 738 #[inline] 739 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> 740 where 741 E: DeError, { 742 if v < 0 { 743 Err(DeError::invalid_value(Unexpected::Signed(v), &self)) 744 } else { 745 #[cfg(feature = "u128")] 746 { 747 Ok(Byte::from_bytes(v as u128)) 748 } 749 750 #[cfg(not(feature = "u128"))] 751 { 752 Ok(Byte::from_bytes(v as u64)) 753 } 754 } 755 } 756 757 #[inline] 758 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> 759 where 760 E: DeError, { 761 #[cfg(feature = "u128")] 762 { 763 Ok(Byte::from_bytes(v as u128)) 764 } 765 766 #[cfg(not(feature = "u128"))] 767 { 768 Ok(Byte::from_bytes(v)) 769 } 770 } 771 772 #[inline] 773 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> 774 where 775 E: DeError, { 776 Byte::from_unit(v, ByteUnit::B).map_err(DeError::custom) 777 } 778 } 779 780 deserializer.deserialize_any(ByteVisitor) 781 } 782 } 783