From b363e6d02196983d4f86ac876f79bdf2a4b40397 Mon Sep 17 00:00:00 2001 From: TD-Sky Date: Sun, 25 Feb 2024 15:16:37 +0800 Subject: [PATCH] doc(1st): the first edition document --- .github/workflows/check.yml | 42 +++++++++++++++++++++++++++++ .github/workflows/test.yml | 26 ++++++++++++++++++ Cargo.toml | 4 +-- README.md | 54 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 50 ++++++++++++++++++++++++++++++++-- src/tests.rs | 2 +- 6 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/check.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..c5fd6e3 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,42 @@ +name: check + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + +jobs: + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - run: cargo fmt --check + env: + RUSTFLAGS: "-Dwarnings" + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --all-features --all-targets + env: + RUSTFLAGS: "-Dwarnings" + + doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo install cargo-deadlinks + - run: cargo deadlinks + - run: cargo doc --all-features --no-deps diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b3f9b2b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,26 @@ +name: test + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + target: ${{ matrix.target }} + - uses: Swatinem/rust-cache@v2 + - run: cargo test --all-features diff --git a/Cargo.toml b/Cargo.toml index 5f5ee43..98167af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "typed-bytesize" -version = "0.1.0" +version = "0.1.1" edition = "2021" authors = ["Collide "] description = "Represent bytesize in decimal or binary prefix unit" -documentation = "https://github.com/TD-Sky/typed-bytesize" +documentation = "https://docs.rs/typed-bytesize" repository = "https://github.com/TD-Sky/typed-bytesize" readme = "README.md" categories = ["value-formatting", "parser-implementations"] diff --git a/README.md b/README.md index fb8720c..ac9cd95 100644 --- a/README.md +++ b/README.md @@ -1 +1,55 @@ # Typed Bytesize + +[![crates.io](https://img.shields.io/crates/v/typed-bytesize.svg)](https://crates.io/crates/typed-bytesize) +[![docs.rs](https://docs.rs/typed-bytesize/badge.svg)](https://docs.rs/typed-bytesize/) +[![check](https://github.com/TD-Sky/typed-bytesize/actions/workflows/check.yml/badge.svg)](https://github.com/TD-Sky/typed-bytesize/actions/workflows/check.yml) +[![test](https://github.com/TD-Sky/typed-bytesize/actions/workflows/test.yml/badge.svg)](https://github.com/TD-Sky/typed-bytesize/actions/workflows/test.yml) + +The library provides two types to represent bytesize: +- [ByteSizeSi](https://docs.rs/typed-bytesize/latest/typed_bytesize/struct.ByteSizeSi.html) for **decimal** prefix unit ([SI](https://en.wikipedia.org/wiki/International_System_of_Units)) +- [ByteSizeIec](https://docs.rs/typed-bytesize/latest/typed_bytesize/struct.ByteSizeIec.html) for **binary** prefix unit (IEC 80000-13) + +## Functions + +- Bytesize types can parse each other's units (e.g. `ByteSizeIec` can parse SI values like `114514GB`); +- Bytesize values will only be formatted as the unit has their owned prefix; +- Bytesize types can be converted to each other; +- Supporting *addition*, *subtraction*, *scalar multiplication* arithmetic operations; +- Optional [serde](https://crates.io/crates/serde) support. + +## Example + +```rust +use typed_bytesize::{ByteSizeIec, ByteSizeSi}; + +// SI +assert_eq!(ByteSizeSi::b(114u64), "114".parse().unwrap()); +assert_eq!(ByteSizeSi::mb(114), "114MB".parse().unwrap()); +print!("{}", ByteSizeSi::kb(310)); // 310.0kB + +// IEC +assert_eq!(ByteSizeIec::b(514u64), "514".parse().unwrap()); +assert_eq!(ByteSizeIec::mib(514), "514MiB".parse().unwrap()); +print!("{}", ByteSizeIec::gib(93696)); // 91.5GiB +``` + +For more detailed examples, refer to [tests](https://docs.rs/crate/typed-bytesize/latest/source/src/tests.rs). + + +## BNF + +Parsing follows the rule: + +```ignore +expr ::= num | term +term ::= decimal " "* unit +decimal ::= num | float +float ::= num "." num +num ::= [0-9]+ +``` + + +## Features + +- `serde`: enable [serde](https://crates.io/crates/serde) on `ByteSizeSi` and `ByteSizeIec`. +- `u128`: use `u128` instead of `u64` as inner numeric type to support larger units. (TODO) diff --git a/src/lib.rs b/src/lib.rs index f2a405c..92fa24d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![doc = include_str!("../README.md")] + #[cfg(test)] mod tests; @@ -5,7 +7,7 @@ mod tests; mod serde; use core::num::{IntErrorKind, ParseFloatError, ParseIntError}; -use core::ops::{Add, AddAssign, Mul, MulAssign}; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use core::str::FromStr; /// 1 byte @@ -21,9 +23,10 @@ pub const GB: u64 = 10u64.pow(9); pub const TB: u64 = 10u64.pow(12); /// 1 petabyte pub const PB: u64 = 10u64.pow(15); -/// 1 exbibyte +/// 1 exabyte pub const EB: u64 = 10u64.pow(18); +/// Decimal prefix bytesize #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct ByteSizeSi(pub u64); @@ -96,6 +99,7 @@ impl ByteSizeSi { Self(n * EB) } + /// Convert into binary prefix unit #[inline(always)] pub const fn iec(self) -> ByteSizeIec { ByteSizeIec(self.0) @@ -105,23 +109,42 @@ impl ByteSizeSi { impl Add for ByteSizeSi { type Output = Self; + #[inline(always)] fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl AddAssign for ByteSizeSi { + #[inline(always)] fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; } } +impl Sub for ByteSizeSi { + type Output = Self; + + #[inline(always)] + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl SubAssign for ByteSizeSi { + #[inline(always)] + fn sub_assign(&mut self, rhs: Self) { + self.0 -= rhs.0; + } +} + impl Mul for ByteSizeSi where T: Into, { type Output = Self; + #[inline] fn mul(self, rhs: T) -> Self::Output { Self(self.0 * rhs.into()) } @@ -131,6 +154,7 @@ impl MulAssign for ByteSizeSi where T: Into, { + #[inline] fn mul_assign(&mut self, rhs: T) { self.0 *= rhs.into(); } @@ -149,6 +173,7 @@ pub const PIB: u64 = 2u64.pow(50); /// 1 exbibyte pub const EIB: u64 = 2u64.pow(60); +/// Binary prefix bytesize #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct ByteSizeIec(pub u64); @@ -221,6 +246,7 @@ impl ByteSizeIec { Self(n * EIB) } + /// Convert into decimal prefix unit #[inline(always)] pub const fn si(self) -> ByteSizeSi { ByteSizeSi(self.0) @@ -230,23 +256,42 @@ impl ByteSizeIec { impl Add for ByteSizeIec { type Output = Self; + #[inline(always)] fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl AddAssign for ByteSizeIec { + #[inline(always)] fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; } } +impl Sub for ByteSizeIec { + type Output = Self; + + #[inline(always)] + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl SubAssign for ByteSizeIec { + #[inline(always)] + fn sub_assign(&mut self, rhs: Self) { + self.0 -= rhs.0; + } +} + impl Mul for ByteSizeIec where T: Into, { type Output = Self; + #[inline] fn mul(self, rhs: T) -> Self::Output { Self(self.0 * rhs.into()) } @@ -256,6 +301,7 @@ impl MulAssign for ByteSizeIec where T: Into, { + #[inline] fn mul_assign(&mut self, rhs: T) { self.0 *= rhs.into(); } diff --git a/src/tests.rs b/src/tests.rs index a3118e2..6b32fdd 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -147,7 +147,7 @@ fn test_parse_min() { } #[test] -fn test_parse_with_whitespace() { +fn test_parse_with_mid_spaces() { assert_si_eq!("114.514 kB", ByteSizeSi(114514)); assert_iec_eq!("114.514 KiB", ByteSizeIec(117262)); assert_si_error!("114.514\tKB", Error::Unit);