Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
1
vendor/number_prefix/.cargo-checksum.json
vendored
Normal file
1
vendor/number_prefix/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"files":{"Cargo.lock":"01454ee6fc7a3b4a5dcabb1b64b26311c1bcc2c123648ee0c5fefb6815ce91f6","Cargo.toml":"6aadc2cd8a03e769f52f3f060995000391489af3cd79451af99a8ef35187988a","examples/conversions.rs":"30eb463f19021f238bd5b3e64173b7104c1643b9882de23f0870c4c333dd8c3b","src/lib.rs":"8b81ff583facf0c5b61f430081ebc8b47b841fd0b61e25ad3d4a39ab0d231d7b","src/parse.rs":"3aa29a67ac439964696f6b086036fbb0f3fdc7cda698dc66c6fea88127f1ef6b"},"package":"830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"}
|
6
vendor/number_prefix/Cargo.lock
generated
vendored
Normal file
6
vendor/number_prefix/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
|
34
vendor/number_prefix/Cargo.toml
vendored
Normal file
34
vendor/number_prefix/Cargo.toml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
authors = ["Benjamin Sago <ogham@bsago.me>"]
|
||||
exclude = ["/README.md", "/LICENCE", "/.rustfmt.toml", "/.travis.yml"]
|
||||
description = "Library for numeric prefixes (kilo, giga, kibi)."
|
||||
documentation = "https://docs.rs/number_prefix"
|
||||
readme = "README.md"
|
||||
keywords = ["mathematics", "numerics"]
|
||||
categories = ["algorithms", "no-std"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/ogham/rust-number-prefix"
|
||||
[package.metadata.docs.rs]
|
||||
features = ["std"]
|
||||
|
||||
[[example]]
|
||||
name = "conversions"
|
||||
required-features = ["std"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
61
vendor/number_prefix/examples/conversions.rs
vendored
Normal file
61
vendor/number_prefix/examples/conversions.rs
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/// This example prints out the conversions for increasingly-large numbers, to
|
||||
/// showcase how the numbers change as the input gets bigger.
|
||||
/// It results in this:
|
||||
///
|
||||
/// ```text
|
||||
/// 1000 bytes is 1.000 kB and 1000 bytes
|
||||
/// 1000000 bytes is 1.000 MB and 976.562 KiB
|
||||
/// 1000000000 bytes is 1.000 GB and 953.674 MiB
|
||||
/// 1000000000000 bytes is 1.000 TB and 931.323 GiB
|
||||
/// 1000000000000000 bytes is 1.000 PB and 909.495 TiB
|
||||
/// 1000000000000000000 bytes is 1.000 EB and 888.178 PiB
|
||||
/// 1000000000000000000000 bytes is 1.000 ZB and 867.362 EiB
|
||||
/// 1000000000000000000000000 bytes is 1.000 YB and 847.033 ZiB
|
||||
///
|
||||
/// 1024 bytes is 1.000 KiB and 1.024 kB
|
||||
/// 1048576 bytes is 1.000 MiB and 1.049 MB
|
||||
/// 1073741824 bytes is 1.000 GiB and 1.074 GB
|
||||
/// 1099511627776 bytes is 1.000 TiB and 1.100 TB
|
||||
/// 1125899906842624 bytes is 1.000 PiB and 1.126 PB
|
||||
/// 1152921504606847000 bytes is 1.000 EiB and 1.153 EB
|
||||
/// 1180591620717411300000 bytes is 1.000 ZiB and 1.181 ZB
|
||||
/// 1208925819614629200000000 bytes is 1.000 YiB and 1.209 YB
|
||||
/// ```
|
||||
|
||||
extern crate number_prefix;
|
||||
use number_prefix::NumberPrefix;
|
||||
use std::fmt::Display;
|
||||
|
||||
|
||||
fn main() {
|
||||
|
||||
// part one, decimal prefixes
|
||||
let mut n = 1_f64;
|
||||
for _ in 0 .. 8 {
|
||||
n *= 1000_f64;
|
||||
|
||||
let decimal = format_prefix(NumberPrefix::decimal(n));
|
||||
let binary = format_prefix(NumberPrefix::binary(n));
|
||||
println!("{:26} bytes is {} and {:10}", n, decimal, binary);
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
// part two, binary prefixes
|
||||
let mut n = 1_f64;
|
||||
for _ in 0 .. 8 {
|
||||
n *= 1024_f64;
|
||||
|
||||
let decimal = format_prefix(NumberPrefix::decimal(n));
|
||||
let binary = format_prefix(NumberPrefix::binary(n));
|
||||
println!("{:26} bytes is {} and {:10}", n, binary, decimal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn format_prefix<T: Display>(np: NumberPrefix<T>) -> String {
|
||||
match np {
|
||||
NumberPrefix::Prefixed(prefix, n) => format!("{:.3} {}B", n, prefix),
|
||||
NumberPrefix::Standalone(bytes) => format!("{} bytes", bytes),
|
||||
}
|
||||
}
|
553
vendor/number_prefix/src/lib.rs
vendored
Normal file
553
vendor/number_prefix/src/lib.rs
vendored
Normal file
@ -0,0 +1,553 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(nonstandard_style)]
|
||||
#![warn(trivial_numeric_casts)]
|
||||
#![warn(unreachable_pub)]
|
||||
#![warn(unused)]
|
||||
|
||||
|
||||
//! This is a library for formatting numbers with numeric prefixes, such as
|
||||
//! turning “3000 metres” into “3 kilometres”, or “8705 bytes” into “8.5 KiB”.
|
||||
//!
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! The function [`NumberPrefix::decimal`](enum.NumberPrefix.html#method.decimal)
|
||||
//! returns either a pair of the resulting number and its prefix, or a
|
||||
//! notice that the number was too small to have any prefix applied to it. For
|
||||
//! example:
|
||||
//!
|
||||
//! ```
|
||||
//! use number_prefix::NumberPrefix;
|
||||
//!
|
||||
//! let amount = 8542_f32;
|
||||
//! let result = match NumberPrefix::decimal(amount) {
|
||||
//! NumberPrefix::Standalone(bytes) => {
|
||||
//! format!("The file is {} bytes in size", bytes)
|
||||
//! }
|
||||
//! NumberPrefix::Prefixed(prefix, n) => {
|
||||
//! format!("The file is {:.1} {}B in size", n, prefix)
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! assert_eq!("The file is 8.5 kB in size", result);
|
||||
//! ```
|
||||
//!
|
||||
//! The `{:.1}` part of the formatting string tells it to restrict the
|
||||
//! output to only one decimal place. This value is calculated by repeatedly
|
||||
//! dividing the number by 1000 until it becomes less than that, which in this
|
||||
//! case results in 8.542, which gets rounded down. Because only one division
|
||||
//! had to take place, the function also returns the decimal prefix `Kilo`,
|
||||
//! which gets converted to its internationally-recognised symbol when
|
||||
//! formatted as a string.
|
||||
//!
|
||||
//! If the value is too small to have any prefixes applied to it — in this case,
|
||||
//! if it’s under 1000 — then the standalone value will be returned:
|
||||
//!
|
||||
//! ```
|
||||
//! use number_prefix::NumberPrefix;
|
||||
//!
|
||||
//! let amount = 705_f32;
|
||||
//! let result = match NumberPrefix::decimal(amount) {
|
||||
//! NumberPrefix::Standalone(bytes) => {
|
||||
//! format!("The file is {} bytes in size", bytes)
|
||||
//! }
|
||||
//! NumberPrefix::Prefixed(prefix, n) => {
|
||||
//! format!("The file is {:.1} {}B in size", n, prefix)
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! assert_eq!("The file is 705 bytes in size", result);
|
||||
//! ```
|
||||
//!
|
||||
//! In this particular example, the user expects different formatting for
|
||||
//! both bytes and kilobytes: while prefixed values are given more precision,
|
||||
//! there’s no point using anything other than whole numbers for just byte
|
||||
//! amounts. This is why the function pays attention to values without any
|
||||
//! prefixes — they often need to be special-cased.
|
||||
//!
|
||||
//!
|
||||
//! ## Binary Prefixes
|
||||
//!
|
||||
//! This library also allows you to use the *binary prefixes*, which use the
|
||||
//! number 1024 (2<sup>10</sup>) as the multiplier, rather than the more common 1000
|
||||
//! (10<sup>3</sup>). This uses the
|
||||
//! [`NumberPrefix::binary`](enum.NumberPrefix.html#method.binary) function.
|
||||
//! For example:
|
||||
//!
|
||||
//! ```
|
||||
//! use number_prefix::NumberPrefix;
|
||||
//!
|
||||
//! let amount = 8542_f32;
|
||||
//! let result = match NumberPrefix::binary(amount) {
|
||||
//! NumberPrefix::Standalone(bytes) => {
|
||||
//! format!("The file is {} bytes in size", bytes)
|
||||
//! }
|
||||
//! NumberPrefix::Prefixed(prefix, n) => {
|
||||
//! format!("The file is {:.1} {}B in size", n, prefix)
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! assert_eq!("The file is 8.3 KiB in size", result);
|
||||
//! ```
|
||||
//!
|
||||
//! A kibibyte is slightly larger than a kilobyte, so the number is smaller
|
||||
//! in the result; but other than that, it works in exactly the same way, with
|
||||
//! the binary prefix being converted to a symbol automatically.
|
||||
//!
|
||||
//!
|
||||
//! ## Which type of prefix should I use?
|
||||
//!
|
||||
//! There is no correct answer this question! Common practice is to use
|
||||
//! the binary prefixes for numbers of *bytes*, while still using the decimal
|
||||
//! prefixes for everything else. Computers work with powers of two, rather than
|
||||
//! powers of ten, and by using the binary prefixes, you get a more accurate
|
||||
//! representation of the amount of data.
|
||||
//!
|
||||
//!
|
||||
//! ## Prefix Names
|
||||
//!
|
||||
//! If you need to describe your unit in actual words, rather than just with the
|
||||
//! symbol, use one of the `upper`, `caps`, `lower`, or `symbol`, which output the
|
||||
//! prefix in a variety of formats. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! use number_prefix::NumberPrefix;
|
||||
//!
|
||||
//! let amount = 8542_f32;
|
||||
//! let result = match NumberPrefix::decimal(amount) {
|
||||
//! NumberPrefix::Standalone(bytes) => {
|
||||
//! format!("The file is {} bytes in size", bytes)
|
||||
//! }
|
||||
//! NumberPrefix::Prefixed(prefix, n) => {
|
||||
//! format!("The file is {:.1} {}bytes in size", n, prefix.lower())
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! assert_eq!("The file is 8.5 kilobytes in size", result);
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! ## String Parsing
|
||||
//!
|
||||
//! There is a `FromStr` implementation for `NumberPrefix` that parses
|
||||
//! strings containing numbers and trailing prefixes, such as `7.5E`.
|
||||
//!
|
||||
//! Currently, the only supported units are `b` and `B` for bytes, and `m` for
|
||||
//! metres. Whitespace is allowed between the number and the rest of the string.
|
||||
//!
|
||||
//! ```
|
||||
//! use number_prefix::{NumberPrefix, Prefix};
|
||||
//!
|
||||
//! assert_eq!("7.05E".parse::<NumberPrefix<_>>(),
|
||||
//! Ok(NumberPrefix::Prefixed(Prefix::Exa, 7.05_f64)));
|
||||
//!
|
||||
//! assert_eq!("7.05".parse::<NumberPrefix<_>>(),
|
||||
//! Ok(NumberPrefix::Standalone(7.05_f64)));
|
||||
//!
|
||||
//! assert_eq!("7.05 GiB".parse::<NumberPrefix<_>>(),
|
||||
//! Ok(NumberPrefix::Prefixed(Prefix::Gibi, 7.05_f64)));
|
||||
//! ```
|
||||
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod parse;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use core::ops::{Neg, Div};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::{fmt, ops::{Neg, Div}};
|
||||
|
||||
|
||||
/// A numeric prefix, either binary or decimal.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Prefix {
|
||||
|
||||
/// _kilo_, 10<sup>3</sup> or 1000<sup>1</sup>.
|
||||
/// From the Greek ‘χίλιοι’ (‘chilioi’), meaning ‘thousand’.
|
||||
Kilo,
|
||||
|
||||
/// _mega_, 10<sup>6</sup> or 1000<sup>2</sup>.
|
||||
/// From the Ancient Greek ‘μέγας’ (‘megas’), meaning ‘great’.
|
||||
Mega,
|
||||
|
||||
/// _giga_, 10<sup>9</sup> or 1000<sup>3</sup>.
|
||||
/// From the Greek ‘γίγας’ (‘gigas’), meaning ‘giant’.
|
||||
Giga,
|
||||
|
||||
/// _tera_, 10<sup>12</sup> or 1000<sup>4</sup>.
|
||||
/// From the Greek ‘τέρας’ (‘teras’), meaning ‘monster’.
|
||||
Tera,
|
||||
|
||||
/// _peta_, 10<sup>15</sup> or 1000<sup>5</sup>.
|
||||
/// From the Greek ‘πέντε’ (‘pente’), meaning ‘five’.
|
||||
Peta,
|
||||
|
||||
/// _exa_, 10<sup>18</sup> or 1000<sup>6</sup>.
|
||||
/// From the Greek ‘ἕξ’ (‘hex’), meaning ‘six’.
|
||||
Exa,
|
||||
|
||||
/// _zetta_, 10<sup>21</sup> or 1000<sup>7</sup>.
|
||||
/// From the Latin ‘septem’, meaning ‘seven’.
|
||||
Zetta,
|
||||
|
||||
/// _yotta_, 10<sup>24</sup> or 1000<sup>8</sup>.
|
||||
/// From the Green ‘οκτώ’ (‘okto’), meaning ‘eight’.
|
||||
Yotta,
|
||||
|
||||
/// _kibi_, 2<sup>10</sup> or 1024<sup>1</sup>.
|
||||
/// The binary version of _kilo_.
|
||||
Kibi,
|
||||
|
||||
/// _mebi_, 2<sup>20</sup> or 1024<sup>2</sup>.
|
||||
/// The binary version of _mega_.
|
||||
Mebi,
|
||||
|
||||
/// _gibi_, 2<sup>30</sup> or 1024<sup>3</sup>.
|
||||
/// The binary version of _giga_.
|
||||
Gibi,
|
||||
|
||||
/// _tebi_, 2<sup>40</sup> or 1024<sup>4</sup>.
|
||||
/// The binary version of _tera_.
|
||||
Tebi,
|
||||
|
||||
/// _pebi_, 2<sup>50</sup> or 1024<sup>5</sup>.
|
||||
/// The binary version of _peta_.
|
||||
Pebi,
|
||||
|
||||
/// _exbi_, 2<sup>60</sup> or 1024<sup>6</sup>.
|
||||
/// The binary version of _exa_.
|
||||
Exbi,
|
||||
// you can download exa binaries at https://exa.website/#installation
|
||||
|
||||
/// _zebi_, 2<sup>70</sup> or 1024<sup>7</sup>.
|
||||
/// The binary version of _zetta_.
|
||||
Zebi,
|
||||
|
||||
/// _yobi_, 2<sup>80</sup> or 1024<sup>8</sup>.
|
||||
/// The binary version of _yotta_.
|
||||
Yobi,
|
||||
}
|
||||
|
||||
|
||||
/// The result of trying to apply a prefix to a floating-point value.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub enum NumberPrefix<F> {
|
||||
|
||||
/// A **standalone** value is returned when the number is too small to
|
||||
/// have any prefixes applied to it. This is commonly a special case, so
|
||||
/// is handled separately.
|
||||
Standalone(F),
|
||||
|
||||
/// A **prefixed** value *is* large enough for prefixes. This holds the
|
||||
/// prefix, as well as the resulting value.
|
||||
Prefixed(Prefix, F),
|
||||
}
|
||||
|
||||
impl<F: Amounts> NumberPrefix<F> {
|
||||
|
||||
/// Formats the given floating-point number using **decimal** prefixes.
|
||||
///
|
||||
/// This function accepts both `f32` and `f64` values. If you’re trying to
|
||||
/// format an integer, you’ll have to cast it first.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::{Prefix, NumberPrefix};
|
||||
///
|
||||
/// assert_eq!(NumberPrefix::decimal(1_000_000_000_f32),
|
||||
/// NumberPrefix::Prefixed(Prefix::Giga, 1_f32));
|
||||
/// ```
|
||||
pub fn decimal(amount: F) -> Self {
|
||||
use self::Prefix::*;
|
||||
Self::format_number(amount, Amounts::NUM_1000, [Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta])
|
||||
}
|
||||
|
||||
/// Formats the given floating-point number using **binary** prefixes.
|
||||
///
|
||||
/// This function accepts both `f32` and `f64` values. If you’re trying to
|
||||
/// format an integer, you’ll have to cast it first.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::{Prefix, NumberPrefix};
|
||||
///
|
||||
/// assert_eq!(NumberPrefix::binary(1_073_741_824_f64),
|
||||
/// NumberPrefix::Prefixed(Prefix::Gibi, 1_f64));
|
||||
/// ```
|
||||
pub fn binary(amount: F) -> Self {
|
||||
use self::Prefix::*;
|
||||
Self::format_number(amount, Amounts::NUM_1024, [Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi])
|
||||
}
|
||||
|
||||
fn format_number(mut amount: F, kilo: F, prefixes: [Prefix; 8]) -> Self {
|
||||
|
||||
// For negative numbers, flip it to positive, do the processing, then
|
||||
// flip it back to negative again afterwards.
|
||||
let was_negative = if amount.is_negative() { amount = -amount; true } else { false };
|
||||
|
||||
let mut prefix = 0;
|
||||
while amount >= kilo && prefix < 8 {
|
||||
amount = amount / kilo;
|
||||
prefix += 1;
|
||||
}
|
||||
|
||||
if was_negative {
|
||||
amount = -amount;
|
||||
}
|
||||
|
||||
if prefix == 0 {
|
||||
NumberPrefix::Standalone(amount)
|
||||
}
|
||||
else {
|
||||
NumberPrefix::Prefixed(prefixes[prefix - 1], amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl fmt::Display for Prefix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.symbol())
|
||||
}
|
||||
}
|
||||
|
||||
impl Prefix {
|
||||
|
||||
/// Returns the name in uppercase, such as “KILO”.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::Prefix;
|
||||
///
|
||||
/// assert_eq!("GIGA", Prefix::Giga.upper());
|
||||
/// assert_eq!("GIBI", Prefix::Gibi.upper());
|
||||
/// ```
|
||||
pub fn upper(self) -> &'static str {
|
||||
use self::Prefix::*;
|
||||
match self {
|
||||
Kilo => "KILO", Mega => "MEGA", Giga => "GIGA", Tera => "TERA",
|
||||
Peta => "PETA", Exa => "EXA", Zetta => "ZETTA", Yotta => "YOTTA",
|
||||
Kibi => "KIBI", Mebi => "MEBI", Gibi => "GIBI", Tebi => "TEBI",
|
||||
Pebi => "PEBI", Exbi => "EXBI", Zebi => "ZEBI", Yobi => "YOBI",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name with the first letter capitalised, such as “Mega”.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::Prefix;
|
||||
///
|
||||
/// assert_eq!("Giga", Prefix::Giga.caps());
|
||||
/// assert_eq!("Gibi", Prefix::Gibi.caps());
|
||||
/// ```
|
||||
pub fn caps(self) -> &'static str {
|
||||
use self::Prefix::*;
|
||||
match self {
|
||||
Kilo => "Kilo", Mega => "Mega", Giga => "Giga", Tera => "Tera",
|
||||
Peta => "Peta", Exa => "Exa", Zetta => "Zetta", Yotta => "Yotta",
|
||||
Kibi => "Kibi", Mebi => "Mebi", Gibi => "Gibi", Tebi => "Tebi",
|
||||
Pebi => "Pebi", Exbi => "Exbi", Zebi => "Zebi", Yobi => "Yobi",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name in lowercase, such as “giga”.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::Prefix;
|
||||
///
|
||||
/// assert_eq!("giga", Prefix::Giga.lower());
|
||||
/// assert_eq!("gibi", Prefix::Gibi.lower());
|
||||
/// ```
|
||||
pub fn lower(self) -> &'static str {
|
||||
use self::Prefix::*;
|
||||
match self {
|
||||
Kilo => "kilo", Mega => "mega", Giga => "giga", Tera => "tera",
|
||||
Peta => "peta", Exa => "exa", Zetta => "zetta", Yotta => "yotta",
|
||||
Kibi => "kibi", Mebi => "mebi", Gibi => "gibi", Tebi => "tebi",
|
||||
Pebi => "pebi", Exbi => "exbi", Zebi => "zebi", Yobi => "yobi",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the short-hand symbol, such as “T” (for “tera”).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use number_prefix::Prefix;
|
||||
///
|
||||
/// assert_eq!("G", Prefix::Giga.symbol());
|
||||
/// assert_eq!("Gi", Prefix::Gibi.symbol());
|
||||
/// ```
|
||||
pub fn symbol(self) -> &'static str {
|
||||
use self::Prefix::*;
|
||||
match self {
|
||||
Kilo => "k", Mega => "M", Giga => "G", Tera => "T",
|
||||
Peta => "P", Exa => "E", Zetta => "Z", Yotta => "Y",
|
||||
Kibi => "Ki", Mebi => "Mi", Gibi => "Gi", Tebi => "Ti",
|
||||
Pebi => "Pi", Exbi => "Ei", Zebi => "Zi", Yobi => "Yi",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Traits for floating-point values for both the possible multipliers. They
|
||||
/// need to be Copy, have defined 1000 and 1024s, and implement a bunch of
|
||||
/// operators.
|
||||
pub trait Amounts: Copy + Sized + PartialOrd + Div<Output=Self> + Neg<Output=Self> {
|
||||
|
||||
/// The constant representing 1000, for decimal prefixes.
|
||||
const NUM_1000: Self;
|
||||
|
||||
/// The constant representing 1024, for binary prefixes.
|
||||
const NUM_1024: Self;
|
||||
|
||||
/// Whether this number is negative.
|
||||
/// This is used internally.
|
||||
fn is_negative(self) -> bool;
|
||||
}
|
||||
|
||||
impl Amounts for f32 {
|
||||
const NUM_1000: Self = 1000_f32;
|
||||
const NUM_1024: Self = 1024_f32;
|
||||
|
||||
fn is_negative(self) -> bool {
|
||||
self.is_sign_negative()
|
||||
}
|
||||
}
|
||||
|
||||
impl Amounts for f64 {
|
||||
const NUM_1000: Self = 1000_f64;
|
||||
const NUM_1024: Self = 1024_f64;
|
||||
|
||||
fn is_negative(self) -> bool {
|
||||
self.is_sign_negative()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{NumberPrefix, Prefix};
|
||||
|
||||
#[test]
|
||||
fn decimal_minus_one_billion() {
|
||||
assert_eq!(NumberPrefix::decimal(-1_000_000_000_f64),
|
||||
NumberPrefix::Prefixed(Prefix::Giga, -1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_minus_one() {
|
||||
assert_eq!(NumberPrefix::decimal(-1f64),
|
||||
NumberPrefix::Standalone(-1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_0() {
|
||||
assert_eq!(NumberPrefix::decimal(0f64),
|
||||
NumberPrefix::Standalone(0f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_999() {
|
||||
assert_eq!(NumberPrefix::decimal(999f32),
|
||||
NumberPrefix::Standalone(999f32))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_1000() {
|
||||
assert_eq!(NumberPrefix::decimal(1000f32),
|
||||
NumberPrefix::Prefixed(Prefix::Kilo, 1f32))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_1030() {
|
||||
assert_eq!(NumberPrefix::decimal(1030f32),
|
||||
NumberPrefix::Prefixed(Prefix::Kilo, 1.03f32))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_1100() {
|
||||
assert_eq!(NumberPrefix::decimal(1100f64),
|
||||
NumberPrefix::Prefixed(Prefix::Kilo, 1.1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_1111() {
|
||||
assert_eq!(NumberPrefix::decimal(1111f64),
|
||||
NumberPrefix::Prefixed(Prefix::Kilo, 1.111f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_126456() {
|
||||
assert_eq!(NumberPrefix::binary(126_456f32),
|
||||
NumberPrefix::Prefixed(Prefix::Kibi, 123.492188f32))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_1048576() {
|
||||
assert_eq!(NumberPrefix::binary(1_048_576f64),
|
||||
NumberPrefix::Prefixed(Prefix::Mebi, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_1073741824() {
|
||||
assert_eq!(NumberPrefix::binary(2_147_483_648f32),
|
||||
NumberPrefix::Prefixed(Prefix::Gibi, 2f32))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn giga() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Giga, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tera() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Tera, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peta() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Peta, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exa() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Exa, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zetta() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Zetta, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yotta() {
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Yotta, 1f64))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(overflowing_literals)]
|
||||
fn and_so_on() {
|
||||
// When you hit yotta, don't keep going
|
||||
assert_eq!(NumberPrefix::decimal(1_000_000_000_000_000_000_000_000_000f64),
|
||||
NumberPrefix::Prefixed(Prefix::Yotta, 1000f64))
|
||||
}
|
||||
}
|
87
vendor/number_prefix/src/parse.rs
vendored
Normal file
87
vendor/number_prefix/src/parse.rs
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
use std::{error::Error, fmt, str};
|
||||
|
||||
use super::{NumberPrefix, Prefix};
|
||||
|
||||
|
||||
impl<T: str::FromStr> str::FromStr for NumberPrefix<T> {
|
||||
type Err = NumberPrefixParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let splitted = s.find(|p| {
|
||||
p == 'k' || p == 'K' || p == 'M' || p == 'G' || p == 'T' ||
|
||||
p == 'P' || p == 'E' || p == 'Z' || p == 'Y'
|
||||
});
|
||||
|
||||
let num_prefix = s.split_at(splitted.unwrap_or(s.len()));
|
||||
let num = match num_prefix.0.trim().parse::<T>() {
|
||||
Ok(n) => n,
|
||||
Err(_) => return Err(NumberPrefixParseError(())),
|
||||
};
|
||||
|
||||
let prefix_unit = num_prefix.1.trim_matches(|p|
|
||||
p == 'b' || p == 'B' || p == 'm'
|
||||
);
|
||||
|
||||
let prefix = match prefix_unit {
|
||||
"k" |
|
||||
"K" => Prefix::Kilo,
|
||||
"M" => Prefix::Mega,
|
||||
"G" => Prefix::Giga,
|
||||
"T" => Prefix::Tera,
|
||||
"P" => Prefix::Peta,
|
||||
"E" => Prefix::Exa,
|
||||
"Z" => Prefix::Zetta,
|
||||
"Y" => Prefix::Yotta,
|
||||
"Ki" => Prefix::Kibi,
|
||||
"Mi" => Prefix::Mebi,
|
||||
"Gi" => Prefix::Gibi,
|
||||
"Ti" => Prefix::Tebi,
|
||||
"Pi" => Prefix::Pebi,
|
||||
"Ei" => Prefix::Exbi,
|
||||
"Zi" => Prefix::Zebi,
|
||||
"Yi" => Prefix::Yobi,
|
||||
"" => return Ok(NumberPrefix::Standalone(num)),
|
||||
_ => return Err(NumberPrefixParseError(())),
|
||||
};
|
||||
|
||||
Ok(NumberPrefix::Prefixed(prefix, num))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The error returned when a `NumberPrefix` is failed to be parsed.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct NumberPrefixParseError(());
|
||||
|
||||
impl fmt::Display for NumberPrefixParseError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.write_str("invalid prefix syntax")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for NumberPrefixParseError {
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_examples() {
|
||||
let parse_example_a = "7.05E".parse::<NumberPrefix<f64>>();
|
||||
let parse_example_b = "7.05".parse::<NumberPrefix<f64>>();
|
||||
let parse_example_c = "7.05 GiB".parse::<NumberPrefix<f64>>();
|
||||
|
||||
assert_eq!(parse_example_a, Ok(NumberPrefix::Prefixed(Prefix::Exa, 7.05_f64)));
|
||||
assert_eq!(parse_example_b, Ok(NumberPrefix::Standalone(7.05_f64)));
|
||||
assert_eq!(parse_example_c, Ok(NumberPrefix::Prefixed(Prefix::Gibi, 7.05_f64)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_parse() {
|
||||
let parsed = "bogo meters per second".parse::<NumberPrefix<f64>>();
|
||||
|
||||
assert_ne!(parsed, Ok(NumberPrefix::Prefixed(Prefix::Kilo, 7.05_f64)));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user