crate documentation minimum rustc 1.8 build status
Format value with units according to SI (système international d’unités).
Version requirement: rustc 1.50+
toml
[dependencies]
si-scale = "0.1"
This crate parses and formats numbers using the SI Scales: from 1 y (yocto, i.e. 1e-24) to 1 Y (Yotta, i.e. 1e24). It is essentially agnostic of units per-se; you can totally keep representing units with strings or uom, or something else.
You can use one of the predefined helper functions to format numbers:
[seconds()
][crate::helpers::seconds()
],
[bytes()
][crate::helpers::bytes()
],
[bibytes()
][crate::helpers::bibytes()
]:
```rust use si_scale::helpers::{seconds, seconds3};
let actual = format!("{}", seconds(1.3e-5)); let expected = "13 µs"; assert_eq!(actual, expected);
let actual = format!("{}", seconds3(1.3e-5)); let expected = "13.000 µs"; assert_eq!(actual, expected); ```
To define your own format function, use the
[scale_fn!()
][crate::scale_fn!()
] macro. For instance, let's define a
formatting function for bits per sec which prints the mantissa with 2
decimals, and also uses base 1024 (where 1 ki = 1024). Note that although
we define the function in a separate module, this is not a requirement.
```rust mod unitfmt { use siscale::scalefn; use siscale::prelude::Value;
// defines the `bits_per_sec()` function
scale_fn!(bits_per_sec,
base: B1024,
constraint: UnitAndAbove,
mantissa_fmt: "{:.2}",
groupings: '_',
unit: "bit/s");
}
use unitfmt::bitsper_sec;
fn main() { let x = 2.1 * 1024 as f32; let actual = format!("throughput: {:>15}", bitspersec(x)); let expected = "throughput: 2.10 kibit/s"; assert_eq!(actual, expected);
let x = 2;
let actual = format!("throughput: {}", bits_per_sec(x));
let expected = "throughput: 2.00 bit/s";
assert_eq!(actual, expected);
}
```
With base = 1000, 1k = 1000, 1M = 1_000_000, 1m = 0.001, 1µ = 0.000_001, etc.
| min (incl.) | max (excl.) | magnitude | prefix |
| --- | --- | --- | ---- |
| .. | .. | -24 | Prefix::Yocto
|
| .. | .. | -21 | Prefix::Zepto
|
| .. | .. | -18 | Prefix::Atto
|
| .. | .. | -15 | Prefix::Femto
|
| .. | .. | -12 | Prefix::Pico
|
| .. | .. | -9 | Prefix::Nano
|
| 0.000_001 | 0.001 | -6 | Prefix::Micro
|
| 0.001 | 1 | -3 | Prefix::Milli
|
| 1 | 1_000 | 0 | Prefix::Unit
|
| 1000 | 1_000_000 | 3 | Prefix::Kilo
|
| 1_000_000 | 1_000_000_000 | 6 | Prefix::Mega
|
| .. | .. | 9 | Prefix::Giga
|
| .. | .. | 12 | Prefix::Tera
|
| .. | .. | 15 | Prefix::Peta
|
| .. | .. | 18 | Prefix::Exa
|
| .. | .. | 21 | Prefix::Zetta
|
| .. | .. | 24 | Prefix::Yotta
|
The base is usually 1000, but can also be 1024 (bibytes).
With base = 1024, 1ki = 1024, 1Mi = 1024 * 1024, etc.
The central representation is the [Value
][crate::value::Value
] type,
which holds
This crate provides 2 APIs: a low-level API, and a high-level API for convenience.
For the low-level API, the typical use case is
first parse a number into a [Value
][crate::value::Value
]. For doing
this, you have to specify the base, and maybe some constraint on the SI
scales. See [Value::new()
][crate::value::Value::new()
] and
[Value::new_with()
][crate::value::Value::new_with()
]
then display the Value
either by yourself formatting the mantissa
and prefix (implements the fmt::Display
trait), or using the provided
Formatter.
For the high-level API, the typical use cases are
parse and display a number using the provided functions such as
bibytes()
, bytes()
or seconds()
, they will choose for each number
the most appropriate SI scale.
In case you want the same control granularity as the low-level API
(e.g. constraining the scale in some way, using some base, specific
mantissa formatting), then you can build a custom function using the
provided macro scale_fn!()
. The existing functions such as
bibytes()
, bytes()
, seconds()
are all built using this same
macro.
The seconds3()
function parses a number into a Value
and displays it
using 3 decimals and the appropriate scale for seconds (UnitAndBelow
),
so that non-sensical scales such as kilo-seconds may not appear. The
seconds()
function does the same but formats the mantissa with the
default "{}"
, so no decimals are printed for integer mantissa.
```rust use si_scale::helpers::{seconds, seconds3};
let actual = format!("result is {:>15}", seconds(1234.5678)); let expected = "result is 1234.5678 s"; assert_eq!(actual, expected);
let actual = format!("result is {:>10}", seconds3(12.3e-7)); let expected = "result is 1.230 µs"; assert_eq!(actual, expected); ```
The bytes()
function parses a number into a Value
using base 1000
and displays it using 1 decimal and the appropriate scale for bytes
(UnitAndAbove
), so that non-sensical scales such as milli-bytes may not
appear.
```rust use si_scale::helpers::{bytes, bytes1};
let actual = format!("result is {}", bytes1(12345678)); let expected = "result is 12.3 MB"; assert_eq!(actual, expected);
let actual = format!("result is {:>10}", bytes(16)); let expected = "result is 16 B"; assert_eq!(actual, expected);
let actual = format!("result is {}", bytes(0.12)); let expected = "result is 0.12 B"; assert_eq!(actual, expected); ```
The bibytes1()
function parses a number into a Value
using base 1024
and displays it using 1 decimal and the appropriate scale for bytes
(UnitAndAbove
), so that non-sensical scales such as milli-bytes may not
appear.
```rust use si_scale::helpers::{bibytes, bibytes1};
let actual = format!("result is {}", bibytes1(12345678)); let expected = "result is 11.8 MiB"; assert_eq!(actual, expected);