https://github.com/neosmart/prettysize-rs
Pretty-print file sizes and more
https://github.com/neosmart/prettysize-rs
crate formatting rust rust-library units
Last synced: 2 months ago
JSON representation
Pretty-print file sizes and more
- Host: GitHub
- URL: https://github.com/neosmart/prettysize-rs
- Owner: neosmart
- License: other
- Created: 2018-08-10T03:58:04.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2025-03-28T02:03:36.000Z (3 months ago)
- Last Synced: 2025-03-28T11:07:55.292Z (3 months ago)
- Topics: crate, formatting, rust, rust-library, units
- Language: Rust
- Homepage:
- Size: 162 KB
- Stars: 44
- Watchers: 3
- Forks: 7
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# PrettySize, rust edition
[](https://crates.io/crates/size) [](https://docs.rs/size/latest/size/)
A comprehensive file size crate for rust applications, meant to be light and effective.
Includes utilities for human-readable formatting of file sizes as well as converting
between different base-two and base-ten size units and performing both mathematical and
logical operations on strongly-typed file sizes.[See the crate documentation](https://docs.rs/size/latest/size/) for a more complete summary of
what this crate can do and how to use it.## Features
`PrettySize` provides
* a `Size` type that can be used to hold a strongly-typed size
(e.g. `let size = Size::from_gigabytes(4)`) and perform operations on it,
* definitions for the base-two and base-ten file size units defined as `pub const` in the
`size::consts` namespace, available both in abbreviated and unabridged forms (i.e.
`consts::KiB` and `consts::KIBIBYTE` or `consts::GB` and `consts::GIGABYTE`),
* an `std::Display` impl for `Size` to automatically display sizes in a human-readable
format, automatically choosing the best size unit and numeric precision to
give the nicest results (you can also use `Size::to_string()` instead).
* a `Size.format()` method that gives you more control over how sizes are converted
to a textual representation, letting you to specify the base of the human-readable
units and their style (smart, abbreviated, or full; plus their lowercase variants).
* mathematical and logical operations on strongly-typed `Size` values,
* full support for expressing negative sizes (e.g. the difference between two sizes, or the
amount of space reclaimed on a disk)
* serialization to/from bare byte fields in network payloads or other api requests/responses
* parsing sizes from text representation in a wide variety of formatsThis crate can also be used in `no_std` mode (by compiling with default features
disabled). This disables string conversion/formatting/parsing but keeps all the strongly-typed
size conversion and mathematical/logical operations available.This crate is free of any dependencies.
## Usage
Cargo.toml:
```toml
[dependencies]
size = "0.5.0-preview2"
```and in your code:
```rust
use size::{Base, Size};
// You can use/import consts representing base2/base10 sizes individually
// as (e.g.) size::KiB, or import all with `use size::consts::*`fn main() {
// Create strongly-typed sizes:
let byte_count = Size::from_kilobytes(42);
assert_eq!(42_000, byte_count.bytes());// Use predefined constants for the various units
let byte_count = 42 * size::KiB;
assert_eq!(43_008, byte_count);// `Size` can take any numeric type you throw at it
let byte_count = Size::from_mib(0.040055);
assert_eq!(byte_count.bytes(), 42_000);// And for those of you that haven't yet drunk the base-two Kool-Aid:
let file_size = Size::from_kb(42);
assert_eq!(file_size.bytes(), 42_000);println!("{}, I say!", file_size);
// prints "41 KiB, I say!"// Override the default choice of base-2 units
println!("{}, I meant!", file_size.format().with_base(Base::Base10));
// prints "42 KB, I meant!"// Add and subtract strongly-typed sizes, even with different underlying types
let sum = Size::from_mb(1.0) + Size::from_kb(200);
assert_eq!(sum.bytes(), 1_200_000);// Multiply and divide strongly-typed sizes by scalar values
let new_size = Size::from_mib(2) * 2;
assert_eq!(new_size, Size::from_mib(4));// Compare sizes for equality or order
let size1 = Size::from_gigabytes(2);
let size2 = Size::from_gibibytes(1.99);
assert!(size1 < size2);// Parse sizes from textual representations
let size1 = Size::from_str("12 KiB").unwrap();
let size2 = Size::from_str("42mb").unwrap();
}
```## Parsing and formatting
The `size` crate supports parsing textual representations of file sizes into strongly typed `Size` objects, both via the `Size::from_str()` function and its `FromStr` implementation that lets you call `"1234 kilobytes".parse()`.
The `Size` type implements `std::fmt::Display` (in addition to many other traits), which provides a facility to generate properly formatted textual representations of file sizes via the `Size::to_string()` impl of the `ToString` trait or when used in a `format!(..., Size)` context.
By default, `Size` objects are formatted as base-2 (KiB, MiB, etc) with heuristically chosen precision and units. The member function `Size::format()` can be used to override the unit base (e.g. MB vs MiB) and whether or not abbreviated unit names are used (e.g. KiB vs Kebibyte).
Feel free to open a GitHub issue or PR if you need further control over formatting (precision, case, etc)!
## `no_std` usage
Add the crate to `Cargo.toml` with `default-features` disabled for `no_std` support:
```toml
[dependencies]
size = { version = ..., default-features = false }
```Building in `no_std` mode disables support for floating point `Size` operations/conversions as well as string formatting and conversion.
## `serde` support
For serialization and deserialization support, add the `size` crate to your `Cargo.toml` with the `serde` feature enabled:
```toml
[dependencies]
size = { version = ..., features = [ "serde" ] }
```**The `Size` type is serialized/deserialized transparently.** This means that it acts as if it were a `u64` field denoting the size in bytes. This was done to allow directly deserializing from network payloads from languages/apis that do not express sizes as strongly typed fields (and vice-versa).
As a concrete example, let's pretend you have the following struct that contains a `Size` field:
```rust
#[derive(Serialize, Deserialize)]
struct File {
path: PathBuf,
size: Size,
}
```Using JSON as an example, the `File` type above will serialize to/from the following:
```json
{
"path:" "/foo/bar",
"size:" 1024
}
```As you can see, the `size` field has been serialized directly to a numeric value (and not a `Size` object _containing_ that number value).
## Parsing sizes from strings
The `FromStr` impl or the static `Size::from_str()` member function can be used to parse sizes from text, and supports a wide variety of input formats and representations:
```rust
let size1 = Size::from_str("123456").unwrap();
let size2 = Size::from_str("17mib").unwrap();
let size3 = Size::from_str("12.8 KB").unwrap();
let size4 = Size::from_str("18.9 gigabytes").unwrap();
```## About
This project started off as a port of Mahmoud's
[PrettySize.NET](https://github.com/neosmart/PrettySize.net) library from C# to Rust. Like
the C# edition of this project. Rust's richer `enum` types and powerful generics made
implementing a custom `Size` generic over the number type without verbosity additionally
possible. Its scope has since grown considerably.# License
`PrettySize` is written and maintained by Mahmoud Al-Qudsi of NeoSmart Technologies and
released to the general public under the terms of the MIT public license.## To-Do
*This section is currently empty 🎉*
Pull requests are welcome!