human_bytes-0.4.3/.cargo_vcs_info.json0000644000000001360000000000100133560ustar { "git": { "sha1": "80c39f18f410673867ea9521b8a07da8ffff4e73" }, "path_in_vcs": "" }human_bytes-0.4.3/.gitignore000064400000000000000000000000361046102023000141350ustar 00000000000000/target **/*.rs.bk Cargo.lock human_bytes-0.4.3/.gitlab-ci.yml000064400000000000000000000012401046102023000145770ustar 00000000000000cache: key: ${CI_COMMIT_REF_SLUG} paths: - target/ # Cache cargo downloads (see # https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci) - cargo_home/bin/ - cargo_home/registry/index/ - cargo_home/registry/cache/ - cargo_home/git/db/ stages: - check before_script: - export CARGO_HOME="$PWD/cargo_home" - mkdir -p $CARGO_HOME check: image: "rust:latest" stage: check before_script: - export PATH="$CARGO_HOME/bin:$PATH" script: - cargo check - cargo test - cargo test --features fast - cargo test --no-default-features - cargo test --no-default-features --features fast human_bytes-0.4.3/CHANGELOG.md000064400000000000000000000027341046102023000137650ustar 00000000000000# Changelog Notes significant changes to human_bytes The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [v0.4.3] - 2023-09-10 ### Changed * Updated author, homepage & repo ## [0.4.2] 2023-04-30 ### Fixed * Updated dependencies ## [0.4.1] 2022-10-28 ### Fixed * A few docs typos, improved Cargo.toml metadata & fixed the tests ## [0.4.0] 2022-10-25 ### Breaking changes * The `bibytes` feature is now `si-units`, and is enabled by default. When disabled, the base unit becomes 1000 instead of 1024. ### Added * CLI binary: `hb` ### Changed * Moved the project's home to [SourceHut](https://sr.ht/~f9/human_bytes) * Switched from `lexical` to [`ryu`](https://github.com/dtolnay/ryu) ## [0.3.1] 2022-02-22 ### Changed * Updated `lexical` to v6.0 ## [0.3] 2021-04-20 ### Fixed * Switch from using `format!` to `String.push` and `String.push_str`. +/- 8% performance improvement. ### Added * A `bibytes` feature, which allows users to use KiB, GiB, etc instead of KB, GB, etc. * More `crates.io` keywords to `Cargo.toml` ## [0.2.1] 2020-04-08 ### Fixed * The README example on how to enable the `fast` feature ### Changed * Simplified the README ## [0.2] 2020-02-15 ### Added * A `fast` feature, which improves performance by using [lexical](https://github.com/Alexhuszagh/rust-lexical) instead of `format!` to convert `f64`s to strings human_bytes-0.4.3/Cargo.lock0000644000000014050000000000100113310ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "anyhow" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "human_bytes" version = "0.4.3" dependencies = [ "anyhow", "lexopt", "ryu", ] [[package]] name = "lexopt" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" human_bytes-0.4.3/Cargo.toml0000644000000024110000000000100113520ustar # 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 are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "human_bytes" version = "0.4.3" authors = ["Namkhai B. "] description = "Crate to convert bytes into human-readable values" homepage = "https://sr.ht/~nkeor/human_bytes" readme = "README.md" keywords = [ "bytes", "conversion", "format", "value-formatting", "utility", ] categories = ["value-formatting"] license = "BSD-2-Clause" repository = "https://git.sr.ht/~nkeor/human_bytes" [profile.release] lto = true strip = true [[bin]] name = "hb" required-features = ["build-binary"] [dependencies.anyhow] version = "1.0" optional = true [dependencies.lexopt] version = "0.3" optional = true [dependencies.ryu] version = "1.0" optional = true [features] build-binary = [ "anyhow", "lexopt", ] default = ["si-units"] fast = ["ryu"] si-units = [] human_bytes-0.4.3/Cargo.toml.orig000064400000000000000000000013651046102023000150420ustar 00000000000000[package] name = "human_bytes" version = "0.4.3" authors = ["Namkhai B. "] edition = "2018" description = "Crate to convert bytes into human-readable values" license = "BSD-2-Clause" homepage = "https://sr.ht/~nkeor/human_bytes" repository = "https://git.sr.ht/~nkeor/human_bytes" categories = ["value-formatting"] keywords = ["bytes", "conversion", "format", "value-formatting", "utility"] [features] default = ["si-units"] si-units = [] build-binary = ["anyhow", "lexopt"] fast = ["ryu"] [dependencies] anyhow = { version = "1.0", optional = true } lexopt = { version = "0.3", optional = true } ryu = { version = "1.0", optional = true } [[bin]] name = "hb" required-features = ["build-binary"] [profile.release] lto = true strip = true human_bytes-0.4.3/LICENSE000064400000000000000000000024251046102023000131560ustar 00000000000000Copyright (c) 2020-2022, Namkhai B. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. human_bytes-0.4.3/README.md000064400000000000000000000045021046102023000134260ustar 00000000000000# human_bytes > A Rust crate & cli to convert bytes into human-readable values. [![License](https://img.shields.io/crates/l/human_bytes?style=flat-square)](./LICENSE) [![Latest version](https://img.shields.io/crates/v/human_bytes?style=flat-square)](https://crates.io/crates/human_bytes) [![Build status](https://img.shields.io/gitlab/pipeline/nkeor/human_bytes-rs?style=flat-square)]() It can return either KiB/MiB/GiB/TiB or KB/MB/GB/TB by disabling the `si-units` feature. > 1 KiB = 1024 B, 1 KB = 1000 B It supports from 0 bytes to several yottabytes (I cannot tell how many because I have to use `u128`s to fit a single YB) ## Usage ### As a CLI * (Optional) Install [Just](https://just.systems/) * Build: - With just: `just build-binary` - Plain cargo: `cargo build --release --features 'build-binary fast' --bin hb` * Copy `target/release/hb` to somewhere in your `$PATH` * Run `hb ` or `echo | hb` ### As a library Add to your `Cargo.toml`: ```toml [dependencies] human_bytes = "0.4" # or, to disable the SI Units: human_bytes = { version = "0.4", default-features = false } ``` And then ```rust use human_bytes::human_bytes; assert_eq!(human_bytes(563_200_u32), "550 KiB".to_string()); // or assert_eq!(human_bytes(563_200_u64 as f64), "550 KiB".to_string()); // ________________________________/ // | // | Needed only when you're using `u64` values, // | because `f64` doesn't implement `std::convert::From` // With the `si-units` feature disabled: assert_eq!(human_bytes(550_000_u32), "550 KB".to_string()); ``` The crate is dependency-free, but you can boost the speed by enabling the `fast` feature, which switches from using `std::format!` to [ryu](https://github.com/dtolnay/ryu) to convert floats to strings. ```toml [dependencies] human_bytes = { version = "0.4", features = ["fast"] } ``` ## About The code is based on a PHP function I found [here](https://math.stackexchange.com/questions/247444/explain-convertion-algorithm-from-bytes-to-kb-mb-gb). It is useful because you don't have to provide a prefix, it does it on its own. It'll always return `1 MiB` instead of `1024 KiB` It has some tests I wrote to check that the conversion is correct, and it returns decimals (e.g. `16.5 GiB`) ## Changelog Check the [CHANGELOG.md](./CHANGELOG.md) ## License [BSD 2-clause](./LICENSE) (c) 2020-2022 Namkhai B. human_bytes-0.4.3/justfile000064400000000000000000000005211046102023000137140ustar 00000000000000all: test lint build-binary test: cargo test cargo test --features fast cargo test --no-default-features cargo test --no-default-features --features fast lint: cargo clippy cargo clippy --features fast cargo clippy --bin hb --features "build-binary" build-binary: cargo build --release --features 'build-binary fast' --bin hb human_bytes-0.4.3/src/bin/hb.rs000064400000000000000000000024671046102023000144550ustar 00000000000000use std::io::{stdin, IsTerminal, Read}; use anyhow::Context; use human_bytes::human_bytes; use lexopt::prelude::*; const fn usage() -> &'static str { "Usage: hb [options] -h, --help Print this help message -V, --version Print version info" } fn main() -> anyhow::Result<()> { let mut bytes: Option = None; if stdin().is_terminal() { let mut cli = lexopt::Parser::from_env(); while let Some(arg) = cli.next()? { match arg { Value(val) if bytes.is_none() => { bytes = Some(val.to_string_lossy().parse()?); } Short('h') | Long("help") => { println!("{}", usage()); std::process::exit(0); } Short('V') | Long("version") => { println!("{} v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); std::process::exit(0); } _ => return Err(arg.unexpected())?, } } } else { let mut tmp = String::new(); std::io::stdin().read_to_string(&mut tmp)?; bytes = Some(tmp.trim().parse()?); } let bytes = bytes.context("missing (see -h)")?; println!("{}", human_bytes(bytes as f64)); Ok(()) } human_bytes-0.4.3/src/lib.rs000064400000000000000000000032751046102023000140600ustar 00000000000000//! ## A Rust crate & cli to convert bytes into human-readable values. //! It can return either KiB/MiB/GiB/TiB or KB/MB/GB/TB by disabling the `si-units` feature. //! //! > 1 KiB = 1024 B, 1 KB = 1000 B //! //! It supports from 0 bytes to several yottabytes (I cannot tell how many because I have to use `u128`s //! to fit a single YB) //! //! For more info, check out the [README.md](https://sr.ht/~f9/human_bytes) #[cfg(test)] mod tests; #[cfg(not(feature = "si-units"))] // Just be future-proof const SUFFIX: [&str; 9] = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; #[cfg(feature = "si-units")] // Just be future-proof const SUFFIX: [&str; 9] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; #[cfg(not(feature = "si-units"))] const UNIT: f64 = 1000.0; #[cfg(feature = "si-units")] const UNIT: f64 = 1024.0; /// Converts bytes to human-readable values pub fn human_bytes>(bytes: T) -> String { let size = bytes.into(); if size <= 0.0 { return "0 B".to_string(); } let base = size.log10() / UNIT.log10(); #[cfg(feature = "fast")] { let mut buffer = ryu::Buffer::new(); let result = buffer // Source for this hack: https://stackoverflow.com/a/28656825 .format((UNIT.powf(base - base.floor()) * 10.0).round() / 10.0) .trim_end_matches(".0"); // Add suffix [result, SUFFIX[base.floor() as usize]].join(" ") } #[cfg(not(feature = "fast"))] { let result = format!("{:.1}", UNIT.powf(base - base.floor()),) .trim_end_matches(".0") .to_owned(); // Add suffix [&result, SUFFIX[base.floor() as usize]].join(" ") } } human_bytes-0.4.3/src/tests.rs000064400000000000000000000031771046102023000144550ustar 00000000000000#[cfg(not(feature = "si-units"))] mod decimal { use crate::human_bytes; #[test] fn nothing() { assert_eq!(human_bytes(0_u32), "0 B".to_string()); } #[test] fn bytes() { assert_eq!(human_bytes(550_u32), "550 B".to_string()); } #[test] fn kilobytes() { assert_eq!(human_bytes(550_000_u32), "550 KB".to_string()); } #[test] fn megabytes() { assert_eq!(human_bytes(650_000_000_u32), "650 MB".to_string()); } #[test] fn gigabytes() { assert_eq!( human_bytes(15_300_000_000_u64 as f64), "15.3 GB".to_string() ); } #[test] fn terabytes() { assert_eq!(human_bytes(2_500_000_000_000_u64 as f64), "2.5 TB"); } } #[cfg(feature = "si-units")] mod binary { use crate::human_bytes; #[test] fn nothing() { assert_eq!(human_bytes(0_u32), "0 B".to_string()); } #[test] fn bytes() { assert_eq!(human_bytes(550_u32), "550 B".to_string()); } #[test] fn kibibytes() { assert_eq!(human_bytes(563_200_u32), "550 KiB".to_string()); } #[test] fn mebibytes() { assert_eq!(human_bytes(681_574_400_u32), "650 MiB".to_string()); } #[test] fn gibibytes() { assert_eq!( human_bytes(16_428_249_907_u64 as f64), "15.3 GiB".to_string() ); } #[test] fn tebibytes() { // Hacky, I know, but easier to write ;) let tebibyte: u64 = 2_u64.pow(40); assert_eq!( human_bytes(((tebibyte * 2) + (tebibyte / 2)) as f64), "2.5 TiB" ); } }