Code Monkey home page Code Monkey logo

prettysize-rs's Introduction

PrettySize, rust edition

crates.io docs.rs

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 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 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!

prettysize-rs's People

Contributors

angusholder avatar antosser avatar mqudsi avatar vic1707 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

prettysize-rs's Issues

Feature request: Support Add and Sub operations

Hi.

Would be useful to be able to add and subtract values, wouldn't it?

Note that you might not only want to add implementations for Add, AddAssign, Sub and SubAssign , but maybe also safe implementations for adding one byte to 1000 exabyte ... which would overflow I guess.

Specify the number of decimal places

From what I've read in the source code, there's no way to set the number of decimal places. I'm making an app where it kind of matters, because when I have Size::from_bytes(170_516_114) which should be around 162.6 MiB, but lib shows it as 163 MiB and in other cases (examples from the docs etc seems to display fine) it just seems to round up the number which is not ideal but not a top priority for me right now.

Would it be something that could be added in 0.5 version? From what I saw, there's just a map of rules on how to format, so I'm not sure how hard would it be to add this feature.

Support display modifiers

Hey, thanks for the nice crate!

It would be great if you could add support for display modifiers, so that e.g. format!("{size:>10}") prints the value of the size with a total width of (at least) 10 characters, aligned to the right, and format!("{size:<10.3}") left-aligns the value and uses exactly 3 decimal places.

This is useful e.g. to display values in a column layout. In a perfect world something like below is what I'm looking for, but this may be a bit too much.

 1.0 B
 2.1kB
 4.0MB
12.2GB

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.