human-units

Crates.iohuman-units
lib.rshuman-units
version0.5.3
created_at2024-09-14 10:45:41.323958+00
updated_at2025-08-03 17:51:34.697457+00
descriptionUnits serialization and formatting library designed for configuration files and command line arguments
homepagehttps://github.com/igankevich/human-units
repositoryhttps://github.com/igankevich/human-units
max_upload_size
id1374662
size134,714
Ivan Gankevich (igankevich)

documentation

https://docs.rs/human-units

README

human-units

Crates.io Version Docs dependency status

Size, duration and other SI units serialization and formatting library designed for configuration files and command line arguments.

Introduction

human-units is a library with Size, Duration and other SI-related types specifically designed to be used in configuration files and as command line arguments. These types serialize sizes and durations in exact but human-readable form.

The library also provides FormatSize, FormatDuration traits to print approximate values in a short human-readable form.

  • No floating point operations.

  • No dependencies by default.

  • Supports serde.

  • Supports clap.

  • Supports no_std.

  • Tested with Miri.

  • 72–85% faster than similar libraries (see benchmarks below).

  • 50–87% less binary size compared to similar libraries (see benchmarks below).

Examples

Exact human-readable size/duration

use human_units::{Duration, Size};
assert_eq!("1k", Size(1024).to_string());
assert_eq!("1025", Size(1025).to_string());
assert_eq!("1m", Duration(core::time::Duration::from_secs(60)).to_string());
assert_eq!("61s", Duration(core::time::Duration::from_secs(61)).to_string());

Inexact short human-readable size/duration

use core::time::Duration;
use human_units::{FormatDuration, FormatSize};
assert_eq!("1 KiB", 1024_u64.format_size().to_string());
assert_eq!("1 m", Duration::from_secs(60).format_duration().to_string());

Custom output

use colored::Colorize;
use core::time::Duration;
use human_units::{FormatDuration, FormattedDuration};

/// Prints the unit in cyan.
struct ColoredDuration(FormattedDuration);

impl core::fmt::Display for ColoredDuration {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(f, "{}", self.0.integer)?;
        if self.0.fraction != 0 {
            write!(f, ".{}", self.0.fraction)?;
        }
        write!(f, " {}", self.0.unit.cyan())
    }
}

// prints "1 m ago", "m" is printed with cyan color
println!("{} ago", ColoredDuration(Duration::from_secs(60).format_duration()));

Serde integration

use human_units::Size;
use serde::Serialize;

#[derive(Serialize, PartialEq, Eq, Debug)]
struct SizeWrapper {
    size: Size,
}

let object = SizeWrapper{ size: Size(1024) };
assert_eq!(r#"size = "1k""#, toml::to_string(&object).unwrap().trim());

Clap integration

use clap::Parser;
use human_units::{Duration, Size};

#[derive(Parser, Debug)]
struct Args {
    #[arg(long, value_parser=clap::value_parser!(Duration))]
    timeout: Duration,
    #[arg(long, value_parser=clap::value_parser!(Size))]
    size: Size,
}

let args = Args::parse_from(["test-clap", "--timeout", "1m", "--size", "1g"]);
assert_eq!(args.timeout, Duration(core::time::Duration::from_secs(60)));
assert_eq!(args.size, Size(1024_u64.pow(3)));

SI units

use human_units::si::{Frequency, Prefix};

// Convert from hertz, internal representation is nHz (nanohertz).
let cpu_freq = Frequency::with_si_prefix(2200, Prefix::Mega);
assert_eq!("2200 MHz", cpu_freq.to_string());
assert_eq!("2.2 GHz", cpu_freq.format_si().to_string());

IEC units

use human_units::iec::{Byte, Prefix};

let size = Byte::with_iec_prefix(1536, Prefix::Kibi);
assert_eq!("1536 KiB", size.to_string());
assert_eq!("1.5 MiB", size.format_iec().to_string());

Custom units

use human_units::si::si_unit;
use human_units::iec::iec_unit;

#[si_unit(symbol = "l")]
struct Volume(pub u64);

let volume = Volume(2_200_000_000);
assert_eq!("2200 ml", volume.to_string());

#[iec_unit(symbol = "B/s")]
struct Throughput(pub u64);

let throughput = Throughput(100 * 1024);
assert_eq!("100 KiB/s", throughput.to_string());

Performance benchmarks

Benchmarks were done with Rust 1.80.1 on a x86_64 laptop.

Format size

Library Version Features Benchmark Time
human_bytes 0.4.3 fast format_size_then_to_string 88.40 ns ± 5.02 ns
human-repr 1.1.0 1024,space format_size_then_to_string 161.38 ns ± 13.29 ns
human-units 0.1.3 format_size_then_to_string 24.24 ns ± 1.23 ns

Format duration

Library Version Features Benchmark Time
human-repr 1.1.0 1024,space format_duration_then_to_string 229.47 ns ± 11.90 ns
human-units 0.1.3 format_duration_then_to_string 41.55 ns ± 2.77 ns

Executable size benchmarks

Benchmarks were done with Rust 1.80.1 on a x86_64 laptop.

Format size

Library Version Features Benchmark Executable size, B
human_bytes 0.4.3 fast print formatted size 8192
human-repr 1.1.0 1024,space print formatted size 28672
human-units 0.1.3 print formatted size 4096

Format duration

Library Version Features Benchmark Executable size, B
human-repr 1.1.0 1024,space print formatted duration 28672
human-units 0.1.3 print formatted duration 4096
Commit count: 10

cargo fmt