diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 5359c4ad..3b950d96 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -7,42 +7,40 @@ on: pull_request: branches: [main] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: rust: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable with: - submodules: true # Fetch and checkout submodules + components: clippy, rustfmt # Rust cache - uses: Swatinem/rust-cache@v2 - - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - components: clippy, rustfmt - - name: Install cargo-sort - run: cargo install cargo-sort - - - name: Cancel previous runs - uses: styfle/cancel-workflow-action@0.9.1 + uses: taiki-e/install-action@v2 with: - access_token: ${{ github.token }} + tool: cargo-sort - name: Check formatting - run: cargo fmt -- --check + run: cargo fmt --all -- --check + + - name: Check TOML files are sorted + run: cargo sort --workspace --check - name: Clippy - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features -- -Dclippy::all + run: cargo clippy --workspace --all-features --all-targets -- -Dclippy::all - name: Test - run: cargo test + run: cargo test --workspace --all-features - - name: Check TOML files are sorted - run: cargo sort --check \ No newline at end of file + - name: Check no_std + run: cargo check -p humanbyte --no-default-features diff --git a/Cargo.toml b/Cargo.toml index 335dccdf..4b3eb7e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,3 @@ [workspace] -members = [ - "bytescale", - "humanbyte", - "humanbyte-derive" -] +members = ["bytescale", "humanbyte", "humanbyte-derive"] resolver = "2" diff --git a/bytescale/Cargo.toml b/bytescale/Cargo.toml index 5b080a2d..0197ae45 100644 --- a/bytescale/Cargo.toml +++ b/bytescale/Cargo.toml @@ -10,6 +10,13 @@ license = "Apache-2.0" edition = "2021" rust-version = "1.65" +[features] +default = ["std", "derive"] +std = ["humanbyte/std"] +derive = [] +arbitrary = ["dep:arbitrary", "std"] +serde = ["humanbyte/serde"] + [dependencies] arbitrary = { version = "1", features = ["derive"], optional = true } humanbyte = { version = "0.2.1-alpha.0", path = "../humanbyte", features = ["derive"] } @@ -18,10 +25,3 @@ humanbyte = { version = "0.2.1-alpha.0", path = "../humanbyte", features = ["der serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["std"] } toml = "0.8" - -[features] -default = ["std", "derive"] -std = ["humanbyte/std"] -derive = [] -arbitrary = ["dep:arbitrary", "std"] -serde = ["humanbyte/serde"] diff --git a/bytescale/src/lib.rs b/bytescale/src/lib.rs index 50ba513b..71d0b0f2 100644 --- a/bytescale/src/lib.rs +++ b/bytescale/src/lib.rs @@ -44,7 +44,7 @@ mod tests { fn test_arithmetic_primitives() { let mut x = ByteScale::mb(1); - assert_eq!((x + MB as u64).as_u64(), 2_000_000); + assert_eq!((x + MB).as_u64(), 2_000_000); assert_eq!((x + MB as u32).as_u64(), 2_000_000); @@ -60,7 +60,7 @@ mod tests { assert_eq!((x - B as u32).as_u64(), 999_999); - x += MB as u64; + x += MB; x += MB as u32; x += 10u16; x += 1u8; diff --git a/humanbyte-derive/Cargo.toml b/humanbyte-derive/Cargo.toml index b0295ead..8384608f 100644 --- a/humanbyte-derive/Cargo.toml +++ b/humanbyte-derive/Cargo.toml @@ -10,11 +10,11 @@ license = "Apache-2.0" [lib] proc-macro = true +[features] +default = [] +serde = [] + [dependencies] proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full"] } - -[features] -default = [] -serde = [] diff --git a/humanbyte/Cargo.toml b/humanbyte/Cargo.toml index 38d42934..b2e44f9d 100644 --- a/humanbyte/Cargo.toml +++ b/humanbyte/Cargo.toml @@ -7,12 +7,12 @@ description = "A procedural macro for deriving human readable byte functions" keywords = ["byte-size", "utility", "human-readable", "no_std"] license = "Apache-2.0" -[dependencies] -humanbyte-derive = { version = "0.2.1-alpha.0", path = "../humanbyte-derive", optional = true } -serde = { version = "1.0", features = ["derive"], optional = true } - [features] default = ["std"] std = [] derive = ["dep:humanbyte-derive"] serde = ["dep:serde", "std", "humanbyte-derive/serde"] + +[dependencies] +humanbyte-derive = { version = "0.2.1-alpha.0", path = "../humanbyte-derive", optional = true } +serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/humanbyte/src/lib.rs b/humanbyte/src/lib.rs index 02e1c83b..256a0b96 100644 --- a/humanbyte/src/lib.rs +++ b/humanbyte/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] -#![cfg_attr(not(feature = "std"), no_std)] //! Common types and functions for byte size handling extern crate alloc; @@ -52,10 +51,6 @@ const UNITS_IEC: &str = "KMGTPE"; /// /// See . const UNITS_SI: &str = "kMGTPE"; -/// `ln(1024) ~= 6.931` -const LN_KIB: f64 = 6.931_471_805_599_453; -/// `ln(1000) ~= 6.908` -const LN_KB: f64 = 6.907_755_278_982_137; #[derive(Debug, Clone, Default)] pub enum Format { #[default] @@ -68,10 +63,6 @@ pub fn to_string(bytes: u64, format: Format) -> String { Format::IEC => KIB, Format::SI => KB, }; - let unit_base = match format { - Format::IEC => LN_KIB, - Format::SI => LN_KB, - }; let unit_prefix = match format { Format::IEC => UNITS_IEC.as_bytes(), Format::SI => UNITS_SI.as_bytes(), @@ -83,15 +74,18 @@ pub fn to_string(bytes: u64, format: Format) -> String { if bytes < unit { format!("{} B", bytes) } else { - let size = bytes as f64; - let exp = match (size.ln() / unit_base) as usize { - 0 => 1, - e => e, - }; + // Integer log: largest exp such that bytes >= unit^exp. + // (f64::ln is unavailable in core, and this is exact at boundaries.) + let mut exp = 0u32; + let mut n = bytes; + while n >= unit { + n /= unit; + exp += 1; + } format!( "{:.1} {}{}", - (size / unit.pow(exp as u32) as f64), - unit_prefix[exp - 1] as char, + (bytes as f64 / unit.pow(exp) as f64), + unit_prefix[(exp - 1) as usize] as char, unit_suffix ) }