Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
use alloc::string::String;
use crate::numeric_traits::*;
use crate::options::FormatSizeOptions;
use crate::ISizeFormatter;
pub fn format_size_i(input: impl ToF64, options: impl AsRef<FormatSizeOptions>) -> String {
format!("{}", ISizeFormatter::new(input, options))
}
pub fn format_size(input: impl ToF64 + Unsigned, options: impl AsRef<FormatSizeOptions>) -> String {
format_size_i(input, &options)
}
pub fn make_format_i<T: ToF64>(options: impl AsRef<FormatSizeOptions>) -> impl Fn(T) -> String {
move |val| -> String { format_size_i(val, &options) }
}
pub fn make_format<T: ToF64 + Unsigned>(
options: impl AsRef<FormatSizeOptions>,
) -> impl Fn(T) -> String {
make_format_i(options)
}
+95
View File
@@ -0,0 +1,95 @@
use libm::{fabs, modf};
use crate::{scales, utils::f64_eq, BaseUnit, FormatSizeOptions, Kilo, ToF64, Unsigned};
pub struct ISizeFormatter<T: ToF64, O: AsRef<FormatSizeOptions>> {
value: T,
options: O,
}
impl<V: ToF64, O: AsRef<FormatSizeOptions>> ISizeFormatter<V, O> {
pub fn new(value: V, options: O) -> Self {
ISizeFormatter { value, options }
}
}
impl<T: ToF64, O: AsRef<FormatSizeOptions>> core::fmt::Display for ISizeFormatter<T, O> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let opts = self.options.as_ref();
let divider = opts.kilo.value();
let mut size: f64 = self.value.to_f64();
let mut scale_idx = 0;
if let Some(val) = opts.fixed_at {
while scale_idx != val as usize {
size /= divider;
scale_idx += 1;
}
} else {
while fabs(size) >= divider {
size /= divider;
scale_idx += 1;
}
}
let mut scale = match (opts.units, opts.long_units, opts.base_unit) {
(Kilo::Decimal, false, BaseUnit::Byte) => scales::SCALE_DECIMAL[scale_idx],
(Kilo::Decimal, true, BaseUnit::Byte) => scales::SCALE_DECIMAL_LONG[scale_idx],
(Kilo::Binary, false, BaseUnit::Byte) => scales::SCALE_BINARY[scale_idx],
(Kilo::Binary, true, BaseUnit::Byte) => scales::SCALE_BINARY_LONG[scale_idx],
(Kilo::Decimal, false, BaseUnit::Bit) => scales::SCALE_DECIMAL_BIT[scale_idx],
(Kilo::Decimal, true, BaseUnit::Bit) => scales::SCALE_DECIMAL_BIT_LONG[scale_idx],
(Kilo::Binary, false, BaseUnit::Bit) => scales::SCALE_BINARY_BIT[scale_idx],
(Kilo::Binary, true, BaseUnit::Bit) => scales::SCALE_BINARY_BIT_LONG[scale_idx],
};
// Remove "s" from the scale if the size is 1.x
let (fpart, ipart) = modf(size);
if f64_eq(ipart, 1.0)
&& (opts.long_units || (opts.base_unit == BaseUnit::Bit && scale_idx == 0))
{
scale = &scale[0..scale.len() - 1];
}
let places = if f64_eq(fpart, 0.0) {
opts.decimal_zeroes
} else {
opts.decimal_places
};
let space = if opts.space_after_value { " " } else { "" };
write!(f, "{:.*}{}{}{}", places, size, space, scale, opts.suffix)
}
}
impl<'a, U: ToF64 + Unsigned + Copy, O: AsRef<FormatSizeOptions>> From<&'a SizeFormatter<U, O>>
for ISizeFormatter<U, &'a O>
{
fn from(source: &'a SizeFormatter<U, O>) -> Self {
ISizeFormatter {
value: source.value,
options: &source.options,
}
}
}
pub struct SizeFormatter<T: ToF64 + Unsigned, O: AsRef<FormatSizeOptions>> {
value: T,
options: O,
}
impl<V: ToF64 + Unsigned, O: AsRef<FormatSizeOptions>> SizeFormatter<V, O> {
pub fn new(value: V, options: O) -> Self {
SizeFormatter { value, options }
}
}
impl<T: ToF64 + Unsigned + Copy, O: AsRef<FormatSizeOptions> + Copy> core::fmt::Display
for SizeFormatter<T, O>
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}", ISizeFormatter::from(self))
}
}
+22
View File
@@ -0,0 +1,22 @@
use crate::{FormatSizeOptions, SizeFormatter, ISizeFormatter, Signed, ToF64, Unsigned};
use alloc::string::String;
pub trait FormatSize<T> {
fn format_size(&self, opts: FormatSizeOptions) -> String;
}
pub trait FormatSizeI<T> {
fn format_size_i(&self, opts: FormatSizeOptions) -> String;
}
impl<T: ToF64 + Unsigned + Copy> FormatSize<T> for T {
fn format_size(&self, opts: FormatSizeOptions) -> String {
format!("{}", SizeFormatter::new(*self, opts))
}
}
impl<T: ToF64 + Signed + Copy> FormatSizeI<T> for T {
fn format_size_i(&self, opts: FormatSizeOptions) -> String {
format!("{}", ISizeFormatter::new(*self, opts))
}
}
+147
View File
@@ -0,0 +1,147 @@
#![no_std]
/*!
# **Humansize**
## Features
Humansize is a humanization library for information size that is:
- Simple & convenient to use
- Customizable
- Supports byte or bit sizes
- `no-std`
- Optionally non-allocating
- Optionally accepts signed values
## How to use it...
Add humansize as a dependency to your project's `cargo.toml`:
```toml
[dependencies]
...
humansize = "2.0.0"
```
### ... to easily format a size:
1. Import the `format_size` function as well as your preferred set of defaults:
- `DECIMAL` (SI)
- `BINARY` (IEC)
- `WINDOWS` (IEC values but SI units)
2. Call `format_size` with an unsigned integer
```rust
use humansize::{format_size, DECIMAL};
let size = 1_000_000u64;
let res: String = format_size(size, DECIMAL);
assert_eq!(&res, "1 MB");
```
### ... to format many sizes:
To improve reusability, you can use `create_format`, which returns a formatter function akin to `format_size` but with the options argument curried so it doesn't need to be specified again:
```rust
use humansize::{make_format, DECIMAL};
let formatter = make_format(DECIMAL);
assert_eq!(formatter(1_000_000u64), "1 MB");
assert_eq!(formatter(1_000_000_000u64), "1 GB");
//...
```
### ... to avoid allocation:
Specify the `no_alloc` feature flag in your project's `cargo.toml`:
```toml
[dependencies]
...
humansize = { version = "2.0.0", features = ["no_alloc"] }
```
This excludes all allocating code from compilation. You may now use the library's internal `SizeFormatter` struct, which implements `core::fmt::display` so that you can `write!` it to a custom buffer of your choice:
```rust
use humansize::{SizeFormatter, DECIMAL};
let formatter = SizeFormatter::new(1_000_000usize, DECIMAL);
assert_eq!(format!("{}", formatter), "1 MB");
```
### ... with the `impl` style API:
For stylistic reasons, you may prefer to use the impl-style API of earlier versions of the crate.
To do so, specify the `impl-style` feature flag in your project's `cargo.toml`:
```toml
[dependencies]
...
humansize = { version = "2.0.0", features = ["impl_style"] }
```
Enabling this feature makes two methods available:
- `format_size` on unsigned integers types
- `format_size_i` on signed integer types.
To use it, bring the FormatSize trait into scope and call its method on an integer type:
```ignore
use humansize::{FormatSize, FormatSizeI DECIMAL};
assert_eq!(1_000_000u64.format_size(DECIMAL), "1 MB");
assert_eq!((-1_000_000).format_size_i(DECIMAL), "-1 MB");
```
### ... to further customize the output:
Humansize exports three default option sets:
* `Decimal`: kilo = 1000, unit format is `XB`.
* `Binary`: kilo = 1024, unit format is `XiB`.
* `WINDOWS` (Windows): kilo = 1024, unit format is `XB`.
The formatting can be further customized by providing providing your own option set. See the documentation of the `FormatSizeOptions` struct to see all the addressable parameters, and [this example](examples/custom_options.rs) for its usage.
### ... to accept negative values:
The solutions presented above only accept unsigned integer types as input (`usize`, `8`, `u16`, `u32` and `u64`). If however accepting negative values is correct for your application, a signed alternative exists for each of them that will accept signed integer types, and format them accordingly if negative:
- `format_size` : `format_size_i`
- `create_format` : `create_format_i`
- `FormatSize` trait : `FormatSizeI` trait
- `SizeFormatter` : `ISizeFormatter`
```rust
use humansize::{format_size_i, make_format_i, ISizeFormatter, DECIMAL};
assert_eq!(&format_size_i(-1_000_000, DECIMAL), "-1 MB");
let signed_formatter = make_format_i(DECIMAL);
assert_eq!(&signed_formatter(-1_000_000), "-1 MB");
// With the `impl-style` feature enabled:
// use humansize::FormatSizeI;
// assert_eq(-1_000_000.format_size(DECIMAL), "-1 MB");
let signed_size_formatter = ISizeFormatter::new(-1_000_000, DECIMAL);
assert_eq!(format!("{}", signed_size_formatter), "-1 MB");
```
*/
#[macro_use]
#[cfg(not(feature = "no_alloc"))]
extern crate alloc;
extern crate libm;
mod options;
pub use options::{BaseUnit, FixedAt, FormatSizeOptions, Kilo, BINARY, DECIMAL, WINDOWS};
mod numeric_traits;
pub use numeric_traits::{Signed, ToF64, Unsigned};
mod scales;
mod utils;
#[cfg(not(feature = "no_alloc"))]
mod allocating;
#[cfg(not(feature = "no_alloc"))]
pub use allocating::*;
#[cfg(feature = "impl_style")]
mod impl_style;
#[cfg(feature = "impl_style")]
pub use impl_style::{FormatSize, FormatSizeI};
mod formatters;
pub use formatters::{SizeFormatter, ISizeFormatter};
+35
View File
@@ -0,0 +1,35 @@
pub trait ToF64 {
fn to_f64(&self) -> f64;
}
macro_rules! impl_to_f64 {
(for $($t:ty)*) => ($(
impl ToF64 for $t {
fn to_f64(&self) -> f64 {
*self as f64
}
}
)*)
}
impl_to_f64!(for usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64);
pub trait Unsigned {}
macro_rules! impl_unsigned {
(for $($t:ty)*) => ($(
impl Unsigned for $t {}
)*)
}
impl_unsigned!(for usize u8 u16 u32 u64);
pub trait Signed {}
macro_rules! impl_unsigned {
(for $($t:ty)*) => ($(
impl Signed for $t {}
)*)
}
impl_unsigned!(for isize i8 i16 i32 i64);
+41
View File
@@ -0,0 +1,41 @@
use super::{BaseUnit, FormatSizeOptions, Kilo};
/// Options to display sizes in the SI format.
pub const BINARY: FormatSizeOptions = FormatSizeOptions {
base_unit: BaseUnit::Byte,
kilo: Kilo::Binary,
units: Kilo::Binary,
decimal_places: 2,
decimal_zeroes: 0,
fixed_at: None,
long_units: false,
space_after_value: true,
suffix: "",
};
/// Options to display sizes in the SI (decimal) format.
pub const DECIMAL: FormatSizeOptions = FormatSizeOptions {
base_unit: BaseUnit::Byte,
kilo: Kilo::Decimal,
units: Kilo::Decimal,
decimal_places: 2,
decimal_zeroes: 0,
fixed_at: None,
long_units: false,
space_after_value: true,
suffix: "",
};
/// Options to display sizes in the "WINDOWS" format.
/// Uses 1024 as the value of the `Kilo`, but displays decimal-style units (`kB`, not `KiB`).
pub const WINDOWS: FormatSizeOptions = FormatSizeOptions {
base_unit: BaseUnit::Byte,
kilo: Kilo::Binary,
units: Kilo::Decimal,
decimal_places: 2,
decimal_zeroes: 0,
fixed_at: None,
long_units: false,
space_after_value: true,
suffix: "",
};
+176
View File
@@ -0,0 +1,176 @@
//! Describes the struct that holds the options needed by the formatting functions.
//! The three most common formats are provided as constants to be used easily
mod defaults;
pub use self::defaults::*;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
/// Holds the standard to use when displaying the size.
pub enum Kilo {
/// The decimal scale and units. SI standard.
Decimal,
/// The binary scale and units.
Binary,
}
impl Default for Kilo {
fn default() -> Self {
Self::Decimal
}
}
impl Kilo {
pub(crate) fn value(&self) -> f64 {
match self {
Kilo::Decimal => 1000.0,
Kilo::Binary => 1024.0,
}
}
}
#[derive(Debug, Copy, Clone)]
/// Forces a certain representation of the resulting file size.
pub enum FixedAt {
Base,
Kilo,
Mega,
Giga,
Tera,
Peta,
Exa,
Zetta,
Yotta,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum BaseUnit {
Bit,
Byte,
}
impl Default for BaseUnit {
fn default() -> Self {
Self::Byte
}
}
/// Holds the options for the `file_size` method.
#[derive(Debug, Clone, Copy, Default)]
#[non_exhaustive]
pub struct FormatSizeOptionsBuilder {
/// Whether the value being formatted represents an amount of bits or bytes.
pub base_unit: BaseUnit,
/// The scale (binary/decimal) to divide against.
pub kilo: Kilo,
/// The unit set to display.
pub units: Kilo,
/// The amount of decimal places to display if the decimal part is non-zero.
pub decimal_places: usize,
/// The amount of zeroes to display if the decimal part is zero.
pub decimal_zeroes: usize,
/// Whether to force a certain representation and if so, which one.
pub fixed_at: Option<FixedAt>,
/// Whether to use the full unit (e.g. `Kilobyte`) or its abbreviation (`kB`).
pub long_units: bool,
/// Whether to place a space between value and units.
pub space_after_value: bool,
/// An optional suffix which will be appended after the unit. Useful to represent speeds (e.g. `1 kB/s)
pub suffix: &'static str,
}
/// Holds the options for the `file_size` method.
#[derive(Debug, Clone, Copy, Default)]
#[non_exhaustive]
pub struct FormatSizeOptions {
/// Whether the value being formatted represents an amount of bits or bytes.
pub base_unit: BaseUnit,
/// The scale (binary/decimal) to divide against.
pub kilo: Kilo,
/// The unit set to display.
pub units: Kilo,
/// The amount of decimal places to display if the decimal part is non-zero.
pub decimal_places: usize,
/// The amount of zeroes to display if the decimal part is zero.
pub decimal_zeroes: usize,
/// Whether to force a certain representation and if so, which one.
pub fixed_at: Option<FixedAt>,
/// Whether to use the full unit (e.g. `Kilobyte`) or its abbreviation (`kB`).
pub long_units: bool,
/// Whether to place a space between value and units.
pub space_after_value: bool,
/// An optional suffix which will be appended after the unit. Useful to represent speeds (e.g. `1 kB/s)
pub suffix: &'static str,
}
impl FormatSizeOptions {
pub fn from(from: FormatSizeOptions) -> FormatSizeOptions {
FormatSizeOptions { ..from }
}
pub fn base_unit(mut self, base_unit: BaseUnit) -> FormatSizeOptions {
self.base_unit = base_unit;
self
}
pub fn kilo(mut self, kilo: Kilo) -> FormatSizeOptions {
self.kilo = kilo;
self
}
pub fn units(mut self, units: Kilo) -> FormatSizeOptions {
self.units = units;
self
}
pub fn decimal_places(mut self, decimal_places: usize) -> FormatSizeOptions {
self.decimal_places = decimal_places;
self
}
pub fn decimal_zeroes(mut self, decimal_zeroes: usize) -> FormatSizeOptions {
self.decimal_zeroes = decimal_zeroes;
self
}
pub fn fixed_at(mut self, fixed_at: Option<FixedAt>) -> FormatSizeOptions {
self.fixed_at = fixed_at;
self
}
pub fn long_units(mut self, long_units: bool) -> FormatSizeOptions {
self.long_units = long_units;
self
}
pub fn space_after_value(mut self, insert_space: bool) -> FormatSizeOptions {
self.space_after_value = insert_space;
self
}
pub fn suffix(mut self, suffix: &'static str) -> FormatSizeOptions {
self.suffix = suffix;
self
}
}
impl AsRef<FormatSizeOptions> for FormatSizeOptions {
fn as_ref(&self) -> &FormatSizeOptions {
self
}
}
+53
View File
@@ -0,0 +1,53 @@
pub(crate) static SCALE_DECIMAL: [&str; 9] = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
pub(crate) static SCALE_DECIMAL_LONG: [&str; 9] = [
"Bytes",
"Kilobytes",
"Megabytes",
"Gigabytes",
"Terabytes",
"Petabytes",
"Exabytes",
"Zettabytes",
"Yottabytes",
];
pub(crate) static SCALE_BINARY: [&str; 9] =
["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
pub(crate) static SCALE_BINARY_LONG: [&str; 9] = [
"Bytes",
"Kibibytes",
"Mebibytes",
"Gibibytes",
"Tebibytes",
"Pebibytes",
"Exbibytes",
"Zebibytes",
"Yobibytes",
];
pub(crate) static SCALE_DECIMAL_BIT: [&str; 9] = [
"bits", "kbit", "Mbit", "Gbit", "Tbit", "Pbit", "Ebit", "Zbit", "Ybit",
];
pub(crate) static SCALE_DECIMAL_BIT_LONG: [&str; 9] = [
"Bits",
"Kilobits",
"Megabits",
"Gigabits",
"Terabits",
"Petabits",
"Exabits",
"Zettabits",
"Yottabits",
];
pub(crate) static SCALE_BINARY_BIT: [&str; 9] = [
"bits", "Kibit", "Mibit", "Gibit", "Tibit", "Pibit", "Eibit", "Zibit", "Yibit",
];
pub(crate) static SCALE_BINARY_BIT_LONG: [&str; 9] = [
"bits", "Kibibits", "Mebibits", "Gibibits", "Tebibits", "Pebibits", "Exbibits", "Zebibits",
"Yobibits",
];
+5
View File
@@ -0,0 +1,5 @@
use libm::fabs;
pub(crate) fn f64_eq(left: f64, right: f64) -> bool {
left == right || fabs(left - right) <= f64::EPSILON
}