11 releases
0.5.0-preview2 | Apr 27, 2024 |
---|---|
0.5.0-preview1 | Apr 26, 2024 |
0.4.1 | Oct 13, 2022 |
0.4.0 | Jun 23, 2022 |
0.1.1 | Aug 16, 2018 |
#11 in Value formatting
57,747 downloads per month
Used in 55 crates
(27 directly)
81KB
1.5K
SLoC
PrettySize, rust edition
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 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 thesize::consts
namespace, available both in abbreviated and unabridged forms (i.e.consts::KiB
andconsts::KIBIBYTE
orconsts::GB
andconsts::GIGABYTE
), - an
std::Display
impl forSize
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 useSize::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 formats
This 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:
[dependencies]
size = "0.5.0-preview2"
and in your code:
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:
[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:
[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:
#[derive(Serialize, Deserialize)]
struct File {
path: PathBuf,
size: Size,
}
Using JSON as an example, the File
type above will serialize to/from the following:
{
"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 support a wide variety of input formats and representations:
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 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!
Dependencies
~160KB