Merge pull request #56 from NotAShelf/notashelf/push-kpolspkuxwln

treewide: break into multiple crates
This commit is contained in:
raf 2026-03-27 17:19:06 +03:00 committed by GitHub
commit 325bc7ab5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 719 additions and 597 deletions

View file

@ -1,4 +1,3 @@
# https://github.com/rui314/mold?tab=readme-ov-file#how-to-use # https://github.com/rui314/mold?tab=readme-ov-file#how-to-use
[target.'cfg(target_os = "linux")'] [target.'cfg(target_os = "linux")']
linker = "clang" rustflags = [ "-C", "link-arg=-fuse-ld=mold" ]
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

View file

@ -14,49 +14,31 @@ jobs:
comment: comment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps: steps:
- name: Checkout - uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Download profiling results - uses: actions-rust-lang/setup-rust-toolchain@v1
uses: actions/download-artifact@v8
- uses: actions/download-artifact@v4
with: with:
name: hotpath-results name: profile-metrics
path: /tmp/ path: /tmp/metrics/
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }} run-id: ${{ github.event.workflow_run.id }}
- name: Setup Rust - name: Install hotpath-utils CLI
uses: actions-rust-lang/setup-rust-toolchain@v1 run: cargo install hotpath --bin hotpath-utils --features=utils
- name: Install hotpath CLI - name: Post PR comment
run: cargo install hotpath
- name: Post timing comparison comment
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
set -euo pipefail set -euo pipefail
HEAD_METRICS=$(cat /tmp/head_timing.json) export GITHUB_BASE_REF=$(cat /tmp/metrics/base_ref.txt)
BASE_METRICS=$(cat /tmp/base_timing.json) export GITHUB_HEAD_REF=$(cat /tmp/metrics/head_ref.txt)
PR_NUMBER=$(cat /tmp/pr_number.txt) hotpath-utils profile-pr \
hotpath profile-pr \ --head-metrics /tmp/metrics/head_timing.json \
--head-metrics "$HEAD_METRICS" \ --base-metrics /tmp/metrics/base_timing.json \
--base-metrics "$BASE_METRICS" \
--github-token "$GH_TOKEN" \ --github-token "$GH_TOKEN" \
--pr-number "$PR_NUMBER" --pr-number "$(cat /tmp/metrics/pr_number.txt)" \
--benchmark-id "timing"
- name: Post allocation comparison comment
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
HEAD_METRICS=$(cat /tmp/head_alloc.json)
BASE_METRICS=$(cat /tmp/base_alloc.json)
PR_NUMBER=$(cat /tmp/pr_number.txt)
hotpath profile-pr \
--head-metrics "$HEAD_METRICS" \
--base-metrics "$BASE_METRICS" \
--github-token "$GH_TOKEN" \
--pr-number "$PR_NUMBER"

View file

@ -4,62 +4,57 @@ on:
pull_request: pull_request:
branches: [ "main" ] branches: [ "main" ]
env: permissions:
CARGO_TERM_COLOR: always contents: read
jobs: jobs:
profile: profile:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout PR HEAD - uses: actions/checkout@v4
uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Rust - uses: actions-rust-lang/setup-rust-toolchain@v1
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Create metrics directory
- name: Run timing profiling on HEAD run: mkdir -p /tmp/metrics
- name: Head benchmark (timing)
env: env:
HOTPATH_JSON: "true" HOTPATH_OUTPUT_FORMAT: json
run: | HOTPATH_OUTPUT_PATH: /tmp/metrics/head_timing.json
cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/head_timing.json run: cargo run -p microfetch --release --features='hotpath'
- name: Run allocation profiling on HEAD - name: Head benchmark (alloc)
env: env:
HOTPATH_JSON: "true" HOTPATH_OUTPUT_FORMAT: json
run: | HOTPATH_OUTPUT_PATH: /tmp/metrics/head_alloc.json
cargo run --features='hotpath,hotpath-alloc' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/head_alloc.json run: cargo run -p microfetch --release --features='hotpath,hotpath-alloc'
- name: Checkout base branch - name: Checkout base
run: | run: git checkout ${{ github.event.pull_request.base.sha }}
git checkout ${{ github.event.pull_request.base.sha }}
- name: Base benchmark (timing)
- name: Run timing profiling on base
env: env:
HOTPATH_JSON: "true" HOTPATH_OUTPUT_FORMAT: json
run: | HOTPATH_OUTPUT_PATH: /tmp/metrics/base_timing.json
cargo run --features='hotpath' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/base_timing.json || echo '{}' > /tmp/base_timing.json run: cargo run -p microfetch --release --features='hotpath' || echo '{}' > /tmp/metrics/base_timing.json
- name: Run allocation profiling on base - name: Base benchmark (alloc)
env: env:
HOTPATH_JSON: "true" HOTPATH_OUTPUT_FORMAT: json
HOTPATH_OUTPUT_PATH: /tmp/metrics/base_alloc.json
run: cargo run -p microfetch --release --features='hotpath,hotpath-alloc' || echo '{}' > /tmp/metrics/base_alloc.json
- name: Save PR metadata
run: | run: |
cargo run --features='hotpath,hotpath-alloc' 2>&1 | grep '^{"hotpath_profiling_mode"' > /tmp/base_alloc.json || echo '{}' > /tmp/base_alloc.json echo '${{ github.event.pull_request.number }}' > /tmp/metrics/pr_number.txt
echo '${{ github.base_ref }}' > /tmp/metrics/base_ref.txt
- name: Save PR number echo '${{ github.head_ref }}' > /tmp/metrics/head_ref.txt
run: |
echo '${{ github.event.pull_request.number }}' > /tmp/pr_number.txt - uses: actions/upload-artifact@v4
- name: Upload profiling results
uses: actions/upload-artifact@v7
with: with:
name: hotpath-results name: profile-metrics
path: | path: /tmp/metrics/
/tmp/head_timing.json
/tmp/head_alloc.json
/tmp/base_timing.json
/tmp/base_alloc.json
/tmp/pr_number.txt
retention-days: 1 retention-days: 1

View file

@ -12,15 +12,14 @@ env:
jobs: jobs:
test: test:
name: Test on ${{ matrix.target }} name: Test on ${{ matrix.target }}
runs-on: ${{ matrix.os }} runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: target:
- os: ubuntu-latest - x86_64-unknown-linux-gnu
target: x86_64-unknown-linux-gnu - aarch64-unknown-linux-gnu
- os: ubuntu-latest - riscv64gc-unknown-linux-gnu
target: aarch64-unknown-linux-gnu
steps: steps:
- name: "Checkout" - name: "Checkout"
@ -31,24 +30,15 @@ jobs:
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
- name: "Install cross-compilation tools" - name: "Make Mold the default linker"
if: matrix.target == 'aarch64-unknown-linux-gnu' uses: rui314/setup-mold@v1
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: "Configure linker for aarch64" - name: "Install cross"
if: matrix.target == 'aarch64-unknown-linux-gnu' run: cargo install cross --git https://github.com/cross-rs/cross
run: |
mkdir -p .cargo
cat >> .cargo/config.toml << EOF
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
EOF
- name: "Build" - name: "Build"
run: cargo build --verbose --target ${{ matrix.target }} run: cross build --verbose --target ${{ matrix.target }}
- name: "Run tests" - name: "Run tests"
if: matrix.target == 'x86_64-unknown-linux-gnu' if: matrix.target == 'x86_64-unknown-linux-gnu'
run: cargo test --verbose --target ${{ matrix.target }} run: cross test --verbose --target ${{ matrix.target }}

2
.gitignore vendored
View file

@ -1,3 +1,3 @@
/target **/target
result* result*
/.direnv /.direnv

396
Cargo.lock generated
View file

@ -4,9 +4,9 @@ version = 4
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.3" version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -28,9 +28,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.21" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
@ -43,15 +43,15 @@ dependencies = [
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.10" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
version = "0.2.7" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [ dependencies = [
"utf8parse", "utf8parse",
] ]
@ -62,7 +62,7 @@ version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [ dependencies = [
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@ -73,14 +73,17 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"once_cell_polyfill", "once_cell_polyfill",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
name = "arc-swap" name = "arc-swap"
version = "1.7.1" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "ascii" name = "ascii"
@ -90,21 +93,21 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.9.0" version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.17.0" version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -120,9 +123,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.46" version = "1.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"shlex", "shlex",
@ -130,9 +133,9 @@ dependencies = [
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]] [[package]]
name = "chunked_transfer" name = "chunked_transfer"
@ -169,9 +172,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.35" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -179,9 +182,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.35" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -191,9 +194,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.32" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -203,30 +206,30 @@ dependencies = [
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.7.4" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.4" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]] [[package]]
name = "colored" name = "colored"
version = "3.0.0" version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]] [[package]]
name = "criterion" name = "criterion"
version = "0.8.1" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3"
dependencies = [ dependencies = [
"alloca", "alloca",
"anes", "anes",
@ -248,10 +251,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "criterion-plot" name = "criterion-cycles-per-byte"
version = "0.8.1" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" checksum = "5396de42a52e9e5d8f67ef0702dae30451f310a9ba1c3094dcf228f0be0e54bc"
dependencies = [
"cfg-if",
"criterion",
]
[[package]]
name = "criterion-plot"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea"
dependencies = [ dependencies = [
"cast", "cast",
"itertools", "itertools",
@ -293,9 +306,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.2.3" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]] [[package]]
name = "dirs-next" name = "dirs-next"
@ -342,21 +355,21 @@ dependencies = [
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.5" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -365,36 +378,35 @@ dependencies = [
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-macro", "futures-macro",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"pin-project-lite", "pin-project-lite",
"pin-utils",
"slab", "slab",
] ]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.16" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -403,12 +415,13 @@ dependencies = [
[[package]] [[package]]
name = "half" name = "half"
version = "2.6.0" version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crunchy", "crunchy",
"zerocopy",
] ]
[[package]] [[package]]
@ -435,9 +448,9 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]] [[package]]
name = "hotpath" name = "hotpath"
version = "0.13.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51462b35dc551217e1d1dd3f8c5eebbb5df7103370b1e55d24c19a3411d290f7" checksum = "2fde50be006a0fe95cc2fd6d25d884aa6932218e4055d7df2fa0d95c386acf8d"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"cfg-if", "cfg-if",
@ -462,9 +475,9 @@ dependencies = [
[[package]] [[package]]
name = "hotpath-macros" name = "hotpath-macros"
version = "0.13.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f022365c90cc04455f17a2b9ba5fe0e661cde1ab27434d382f1f8693fe124e7d" checksum = "dd884cee056e269e41e1127549458e1c4e309f31897ebbc1416982a74d40a5b5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -491,7 +504,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@ -511,15 +524,15 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.15" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.77" version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"wasm-bindgen", "wasm-bindgen",
@ -539,19 +552,18 @@ checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.10" version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08"
dependencies = [ dependencies = [
"bitflags",
"libc", "libc",
] ]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.27" version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]] [[package]]
name = "mach2" name = "mach2"
@ -561,16 +573,37 @@ checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]] [[package]]
name = "microfetch" name = "microfetch"
version = "0.4.13" version = "0.4.13"
dependencies = [ dependencies = [
"criterion",
"hotpath", "hotpath",
"microfetch-lib",
]
[[package]]
name = "microfetch-asm"
version = "0.4.13"
[[package]]
name = "microfetch-bench"
version = "0.4.13"
dependencies = [
"criterion",
"criterion-cycles-per-byte",
"microfetch-lib",
]
[[package]]
name = "microfetch-lib"
version = "0.4.13"
dependencies = [
"hotpath",
"microfetch-asm",
] ]
[[package]] [[package]]
@ -584,9 +617,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.3" version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]] [[package]]
name = "once_cell_polyfill" name = "once_cell_polyfill"
@ -612,15 +645,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.16" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "plotters" name = "plotters"
@ -665,9 +692,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.94" version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -689,9 +716,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.40" version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -707,9 +734,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.10.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [ dependencies = [
"either", "either",
"rayon-core", "rayon-core",
@ -717,9 +744,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.12.1" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [ dependencies = [
"crossbeam-deque", "crossbeam-deque",
"crossbeam-utils", "crossbeam-utils",
@ -738,9 +765,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -750,9 +777,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.9" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -761,21 +788,15 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.5" version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.20" version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -788,18 +809,28 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.219" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.219" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -808,14 +839,15 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.140" version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
"ryu",
"serde", "serde",
"serde_core",
"zmij",
] ]
[[package]] [[package]]
@ -826,9 +858,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]] [[package]]
name = "strsim" name = "strsim"
@ -838,9 +870,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.100" version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -902,18 +934,18 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.48.0" version = "1.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
dependencies = [ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.18" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@ -945,35 +977,22 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.100" version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"once_cell", "once_cell",
"rustversion", "rustversion",
"wasm-bindgen-macro", "wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.100" version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -981,31 +1000,31 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.100" version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
dependencies = [ dependencies = [
"bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.100" version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.77" version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@ -1029,11 +1048,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.9" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]] [[package]]
@ -1048,15 +1067,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.2" version = "0.61.2"
@ -1067,65 +1077,27 @@ dependencies = [
] ]
[[package]] [[package]]
name = "windows-targets" name = "zerocopy"
version = "0.52.6" version = "0.8.47"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "zerocopy-derive",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
] ]
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "zerocopy-derive"
version = "0.52.6" version = "0.8.47"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "zmij"
version = "0.52.6" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View file

@ -1,36 +1,20 @@
[package] [workspace]
name = "microfetch" members = [ "crates/*", "microfetch", "crates/benchmarks" ]
description = "Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed" resolver = "3"
version = "0.4.13"
edition = "2024" [workspace.package]
authors = [ "NotAShelf <raf@notashelf.dev>" ] authors = [ "NotAShelf <raf@notashelf.dev>" ]
rust-version = "1.91.0" edition = "2024"
readme = "./docs/README.md"
repository = "https://github.com/notashelf/microfetch"
license = "GPL-3.0" license = "GPL-3.0"
rust-version = "1.92.0"
version = "0.4.13"
[lib] [workspace.dependencies]
name = "microfetch_lib" microfetch-asm = { path = "./crates/asm" }
path = "src/lib.rs" microfetch-lib = { path = "./crates/lib" }
[[bin]] criterion = { default-features = false, features = [ "cargo_bench_support" ], version = "0.8.2" }
name = "microfetch" criterion-cycles-per-byte = "0.8.0"
path = "src/main.rs"
[dependencies]
hotpath = { optional = true, version = "0.13.0" }
[dev-dependencies]
criterion = "0.8.1"
[features]
hotpath = [ "dep:hotpath", "hotpath/hotpath" ]
hotpath-alloc = [ "hotpath/hotpath-alloc" ]
hotpath-off = [ "hotpath/hotpath-off" ]
[[bench]]
harness = false
name = "benchmark"
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1
@ -48,15 +32,13 @@ inherits = "release"
split-debuginfo = "unpacked" split-debuginfo = "unpacked"
strip = "none" strip = "none"
[lints.clippy] [workspace.lints.clippy]
complexity = { level = "warn", priority = -1 } complexity = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 } pedantic = { level = "warn", priority = -1 }
perf = { level = "warn", priority = -1 } perf = { level = "warn", priority = -1 }
style = { level = "warn", priority = -1 } style = { level = "warn", priority = -1 }
# The lint groups above enable some less-than-desirable rules, we should manually
# enable those to keep our sanity.
absolute_paths = "allow" absolute_paths = "allow"
arbitrary_source_item_ordering = "allow" arbitrary_source_item_ordering = "allow"
implicit_return = "allow" implicit_return = "allow"

12
crates/asm/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "microfetch-asm"
description = "Inline assembly syscall helpers for microfetch"
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
publish = false
license.workspace = true
[lints]
workspace = true

View file

@ -5,11 +5,20 @@
//! What do you mean I wasted two whole hours to make the program only 100µs //! What do you mean I wasted two whole hours to make the program only 100µs
//! faster? //! faster?
//! //!
//! Supports `x86_64` and `aarch64` architectures. Riscv support will be //! Supports `x86_64`, `aarch64`, and `riscv64` architectures.
//! implemented when and ONLY WHEN I can be bothered to work on it.
use std::io; use std::io;
// Ensure we're compiling for a supported architecture.
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64"
)))]
compile_error!(
"Unsupported architecture: only x86_64, aarch64, and riscv64 are supported"
);
/// Direct syscall to open a file /// Direct syscall to open a file
/// ///
/// # Returns /// # Returns
@ -62,21 +71,37 @@ pub unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
fd as i32 fd as i32
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))] #[cfg(target_arch = "riscv64")]
{ unsafe {
compile_error!("Unsupported architecture for inline assembly syscalls"); let fd: i64;
std::arch::asm!(
"ecall",
in("a7") 56i64, // SYS_openat
in("a0") -100i32, // AT_FDCWD
in("a1") path,
in("a2") flags,
in("a3") 0i32, // mode
lateout("a0") fd,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
fd as i32
}
} }
} }
/// Direct syscall to read from a file descriptor /// Direct syscall to read from a file descriptor
/// ///
/// # Returns n /// # Returns
/// ///
/// Number of bytes read or -1 on error /// Number of bytes read or -1 on error
/// ///
/// # Safety /// # Safety
/// ///
/// The caller must ensure: /// The caller must ensure that:
///
/// - `buf` points to a valid writable buffer of at least `count` bytes /// - `buf` points to a valid writable buffer of at least `count` bytes
/// - `fd` is a valid open file descriptor /// - `fd` is a valid open file descriptor
#[inline] #[inline]
@ -95,11 +120,13 @@ pub unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
lateout("r11") _, lateout("r11") _,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as isize ret as isize
} }
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe { unsafe {
let ret: i64; let ret: i64;
@ -112,14 +139,30 @@ pub unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
lateout("x0") ret, lateout("x0") ret,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as isize ret as isize
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{ #[cfg(target_arch = "riscv64")]
compile_error!("Unsupported architecture for inline assembly syscalls"); unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 63i64, // SYS_read
in("a0") fd,
in("a1") buf,
in("a2") count,
lateout("a0") ret,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
ret as isize
}
} }
} }
@ -152,11 +195,13 @@ pub unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
lateout("r11") _, lateout("r11") _,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as isize ret as isize
} }
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe { unsafe {
let ret: i64; let ret: i64;
@ -169,14 +214,30 @@ pub unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
lateout("x0") ret, lateout("x0") ret,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as isize ret as isize
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{ #[cfg(target_arch = "riscv64")]
compile_error!("Unsupported architecture for inline assembly syscalls"); unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 64i64, // SYS_write
in("a0") fd,
in("a1") buf,
in("a2") count,
lateout("a0") ret,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
ret as isize
}
} }
} }
@ -184,7 +245,7 @@ pub unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
/// ///
/// # Safety /// # Safety
/// ///
/// The caller must ensure `fd` is a valid open file descriptor /// The caller must ensure that `fd` is a valid open file descriptor
#[inline] #[inline]
#[must_use] #[must_use]
pub unsafe fn sys_close(fd: i32) -> i32 { pub unsafe fn sys_close(fd: i32) -> i32 {
@ -205,6 +266,7 @@ pub unsafe fn sys_close(fd: i32) -> i32 {
ret as i32 ret as i32
} }
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe { unsafe {
let ret: i64; let ret: i64;
@ -220,9 +282,21 @@ pub unsafe fn sys_close(fd: i32) -> i32 {
ret as i32 ret as i32
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{ #[cfg(target_arch = "riscv64")]
compile_error!("Unsupported architecture for inline assembly syscalls"); unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 57i64, // SYS_close
in("a0") fd,
lateout("a0") ret,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
ret as i32
}
} }
} }
@ -250,7 +324,7 @@ pub struct UtsNameBuf {
/// ///
/// # Safety /// # Safety
/// ///
/// The caller must ensure `buf` points to a valid `UtsNameBuf`. /// The caller must ensure that `buf` points to a valid `UtsNameBuf`.
#[inline] #[inline]
#[allow(dead_code)] #[allow(dead_code)]
pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 { pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
@ -266,11 +340,13 @@ pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
lateout("r11") _, lateout("r11") _,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as i32 ret as i32
} }
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe { unsafe {
let ret: i64; let ret: i64;
@ -286,9 +362,22 @@ pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
ret as i32 ret as i32
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{ #[cfg(target_arch = "riscv64")]
compile_error!("Unsupported architecture for inline assembly syscalls"); unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 160i64, // SYS_uname
in("a0") buf,
lateout("a0") ret,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
ret as i32
}
} }
} }
@ -342,11 +431,13 @@ pub unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
lateout("r11") _, lateout("r11") _,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as i32 ret as i32
} }
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe { unsafe {
let ret: i64; let ret: i64;
@ -358,14 +449,29 @@ pub unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
lateout("x0") ret, lateout("x0") ret,
options(nostack) options(nostack)
); );
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
{ {
ret as i32 ret as i32
} }
} }
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{ #[cfg(target_arch = "riscv64")]
compile_error!("Unsupported architecture for inline assembly syscalls"); unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 43i64, // SYS_statfs
in("a0") path,
in("a1") buf,
lateout("a0") ret,
options(nostack)
);
#[allow(clippy::cast_possible_truncation)]
{
ret as i32
}
} }
} }
@ -379,7 +485,8 @@ pub unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> { pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
const O_RDONLY: i32 = 0; const O_RDONLY: i32 = 0;
// Use stack-allocated buffer for null-terminated path (max 256 bytes) // We use stack-allocated buffer for null-terminated path. The maximum
// is 256 bytes.
let path_bytes = path.as_bytes(); let path_bytes = path.as_bytes();
if path_bytes.len() >= 256 { if path_bytes.len() >= 256 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long")); return Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long"));
@ -408,3 +515,85 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
} }
} }
} }
/// Raw buffer for the `sysinfo(2)` syscall.
///
/// In the Linux ABI `uptime` is a `long` at offset 0. The remaining fields are
/// not needed, but are declared to give the struct its correct size (112 bytes
/// on 64-bit Linux).
///
/// The layout matches the kernel's `struct sysinfo` *exactly*:
/// `mem_unit` ends at offset 108, then 4 bytes of implicit padding to 112.
#[repr(C)]
pub struct SysInfo {
pub uptime: i64,
pub loads: [u64; 3],
pub totalram: u64,
pub freeram: u64,
pub sharedram: u64,
pub bufferram: u64,
pub totalswap: u64,
pub freeswap: u64,
pub procs: u16,
_pad: u16,
_pad2: u32, /* alignment padding to reach 8-byte boundary for
* totalhigh */
pub totalhigh: u64,
pub freehigh: u64,
pub mem_unit: u32,
// 4 bytes implicit trailing padding to reach 112 bytes total; no field
// needed
}
/// Direct `sysinfo(2)` syscall
///
/// # Returns
///
/// 0 on success, negative errno on error
///
/// # Safety
///
/// The caller must ensure that `info` points to a valid `SysInfo` buffer.
#[inline]
pub unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
#[cfg(target_arch = "x86_64")]
unsafe {
let ret: i64;
std::arch::asm!(
"syscall",
in("rax") 99_i64, // __NR_sysinfo
in("rdi") info,
out("rcx") _,
out("r11") _,
lateout("rax") ret,
options(nostack)
);
ret
}
#[cfg(target_arch = "aarch64")]
unsafe {
let ret: i64;
std::arch::asm!(
"svc #0",
in("x8") 179_i64, // __NR_sysinfo
in("x0") info,
lateout("x0") ret,
options(nostack)
);
ret
}
#[cfg(target_arch = "riscv64")]
unsafe {
let ret: i64;
std::arch::asm!(
"ecall",
in("a7") 179_i64, // __NR_sysinfo
in("a0") info,
lateout("a0") ret,
options(nostack)
);
ret
}
}

View file

@ -0,0 +1,21 @@
[package]
name = "microfetch-bench"
description = "Benchmarks for microfetch"
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
license.workspace = true
publish = false
[dependencies]
criterion.workspace = true
criterion-cycles-per-byte.workspace = true
microfetch-lib.workspace = true
[[bench]]
harness = false
name = "microfetch"
[lints]
workspace = true

20
crates/lib/Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "microfetch-lib"
description = "Microfetch library crate - exports all functionality including main function"
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
license.workspace = true
publish = false
[dependencies]
hotpath = { optional = true, version = "0.14.0" }
microfetch-asm.workspace = true
[features]
hotpath = [ "dep:hotpath", "hotpath/hotpath" ]
hotpath-alloc = [ "hotpath/hotpath-alloc" ]
[lints]
workspace = true

View file

@ -1,41 +1,66 @@
use std::io::{self, Cursor, Write}; pub mod colors;
pub mod desktop;
pub mod release;
pub mod system;
pub mod uptime;
use microfetch_lib::{ use std::{
UtsName, ffi::CStr,
colors::{COLORS, print_dots}, io::{self, Cursor, Write},
desktop::get_desktop_info, mem::MaybeUninit,
release::{get_os_pretty_name, get_system_info},
syscall::sys_write,
system::{
get_memory_usage,
get_root_disk_usage,
get_shell,
get_username_and_hostname,
},
uptime::get_current,
}; };
#[cfg_attr(feature = "hotpath", hotpath::main)] pub use microfetch_asm as syscall;
fn main() -> Result<(), Box<dyn std::error::Error>> { pub use microfetch_asm::{
if Some("--version") == std::env::args().nth(1).as_deref() { StatfsBuf,
println!("Microfetch {}", env!("CARGO_PKG_VERSION")); SysInfo,
} else { UtsNameBuf,
let utsname = UtsName::uname()?; read_file_fast,
let fields = Fields { sys_close,
user_info: get_username_and_hostname(&utsname), sys_open,
os_name: get_os_pretty_name()?, sys_read,
kernel_version: get_system_info(&utsname), sys_statfs,
shell: get_shell(), sys_sysinfo,
desktop: get_desktop_info(), sys_uname,
uptime: get_current()?, sys_write,
memory_usage: get_memory_usage()?, };
storage: get_root_disk_usage()?,
colors: print_dots(), /// Wrapper for `utsname` with safe accessor methods
}; pub struct UtsName(UtsNameBuf);
print_system_info(&fields)?;
impl UtsName {
/// Calls `uname(2)` syscall and returns a `UtsName` wrapper
///
/// # Errors
///
/// Returns an error if the `uname` syscall fails
pub fn uname() -> Result<Self, std::io::Error> {
let mut uts = MaybeUninit::uninit();
if unsafe { sys_uname(uts.as_mut_ptr()) } != 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Self(unsafe { uts.assume_init() }))
} }
Ok(()) #[must_use]
pub const fn nodename(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.nodename.as_ptr().cast()) }
}
#[must_use]
pub const fn sysname(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.sysname.as_ptr().cast()) }
}
#[must_use]
pub const fn release(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.release.as_ptr().cast()) }
}
#[must_use]
pub const fn machine(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.machine.as_ptr().cast()) }
}
} }
// Struct to hold all the fields we need in order to print the fetch. This // Struct to hold all the fields we need in order to print the fetch. This
@ -69,9 +94,9 @@ fn print_system_info(
colors, colors,
} = fields; } = fields;
let cyan = COLORS.cyan; let cyan = colors::COLORS.cyan;
let blue = COLORS.blue; let blue = colors::COLORS.blue;
let reset = COLORS.reset; let reset = colors::COLORS.reset;
let mut buf = [0u8; 2048]; let mut buf = [0u8; 2048];
let mut cursor = Cursor::new(&mut buf[..]); let mut cursor = Cursor::new(&mut buf[..]);
@ -106,3 +131,32 @@ fn print_system_info(
} }
Ok(()) Ok(())
} }
/// Main entry point for microfetch - can be called by the binary crate
/// or by other consumers of the library
///
/// # Errors
///
/// Returns an error if any system call fails
#[cfg_attr(feature = "hotpath", hotpath::main)]
pub fn run() -> Result<(), Box<dyn std::error::Error>> {
if Some("--version") == std::env::args().nth(1).as_deref() {
println!("Microfetch {}", env!("CARGO_PKG_VERSION"));
} else {
let utsname = UtsName::uname()?;
let fields = Fields {
user_info: system::get_username_and_hostname(&utsname),
os_name: release::get_os_pretty_name()?,
kernel_version: release::get_system_info(&utsname),
shell: system::get_shell(),
desktop: desktop::get_desktop_info(),
uptime: uptime::get_current()?,
memory_usage: system::get_memory_usage()?,
storage: system::get_root_disk_usage()?,
colors: colors::print_dots(),
};
print_system_info(&fields)?;
}
Ok(())
}

70
crates/lib/src/uptime.rs Normal file
View file

@ -0,0 +1,70 @@
use std::{io, mem::MaybeUninit};
use crate::syscall::sys_sysinfo;
/// Faster integer to string conversion without the formatting overhead.
#[inline]
fn itoa(mut n: u64, buf: &mut [u8]) -> &str {
if n == 0 {
return "0";
}
let mut i = buf.len();
while n > 0 {
i -= 1;
buf[i] = b'0' + (n % 10) as u8;
n /= 10;
}
unsafe { std::str::from_utf8_unchecked(&buf[i..]) }
}
/// Gets the current system uptime.
///
/// # Errors
///
/// Returns an error if the system uptime cannot be retrieved.
#[cfg_attr(feature = "hotpath", hotpath::measure)]
pub fn get_current() -> Result<String, io::Error> {
let uptime_seconds = {
let mut info = MaybeUninit::uninit();
if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 {
return Err(io::Error::last_os_error());
}
#[allow(clippy::cast_sign_loss)]
unsafe {
info.assume_init().uptime as u64
}
};
let days = uptime_seconds / 86400;
let hours = (uptime_seconds / 3600) % 24;
let minutes = (uptime_seconds / 60) % 60;
let mut result = String::with_capacity(32);
let mut buf = [0u8; 20]; // Enough for u64::MAX
if days > 0 {
result.push_str(itoa(days, &mut buf));
result.push_str(if days == 1 { " day" } else { " days" });
}
if hours > 0 {
if !result.is_empty() {
result.push_str(", ");
}
result.push_str(itoa(hours, &mut buf));
result.push_str(if hours == 1 { " hour" } else { " hours" });
}
if minutes > 0 {
if !result.is_empty() {
result.push_str(", ");
}
result.push_str(itoa(minutes, &mut buf));
result.push_str(if minutes == 1 { " minute" } else { " minutes" });
}
if result.is_empty() {
result.push_str("less than a minute");
}
Ok(result)
}

22
microfetch/Cargo.toml Normal file
View file

@ -0,0 +1,22 @@
[package]
name = "microfetch"
description = "Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed"
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
license.workspace = true
readme = "../docs/README.md"
repository = "https://github.com/notashelf/microfetch"
publish = false
[dependencies]
hotpath = { optional = true, version = "0.14.0" }
microfetch-lib.workspace = true
[features]
hotpath = [ "dep:hotpath" ]
hotpath-alloc = [ "hotpath/hotpath-alloc" ]
[lints]
workspace = true

3
microfetch/src/main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
microfetch_lib::run()
}

View file

@ -1,48 +0,0 @@
pub mod colors;
pub mod desktop;
pub mod release;
pub mod syscall;
pub mod system;
pub mod uptime;
use std::{ffi::CStr, mem::MaybeUninit};
use crate::syscall::{UtsNameBuf, sys_uname};
/// Wrapper for `utsname` with safe accessor methods
pub struct UtsName(UtsNameBuf);
impl UtsName {
/// Calls `uname(2)` syscall and returns a `UtsName` wrapper
///
/// # Errors
///
/// Returns an error if the `uname` syscall fails
pub fn uname() -> Result<Self, std::io::Error> {
let mut uts = MaybeUninit::uninit();
if unsafe { sys_uname(uts.as_mut_ptr()) } != 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Self(unsafe { uts.assume_init() }))
}
#[must_use]
pub const fn nodename(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.nodename.as_ptr().cast()) }
}
#[must_use]
pub const fn sysname(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.sysname.as_ptr().cast()) }
}
#[must_use]
pub const fn release(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.release.as_ptr().cast()) }
}
#[must_use]
pub const fn machine(&self) -> &CStr {
unsafe { CStr::from_ptr(self.0.machine.as_ptr().cast()) }
}
}

View file

@ -1,141 +0,0 @@
use std::{io, mem::MaybeUninit};
/// Faster integer to string conversion without the formatting overhead.
#[inline]
fn itoa(mut n: u64, buf: &mut [u8]) -> &str {
if n == 0 {
return "0";
}
let mut i = buf.len();
while n > 0 {
i -= 1;
buf[i] = b'0' + (n % 10) as u8;
n /= 10;
}
unsafe { std::str::from_utf8_unchecked(&buf[i..]) }
}
/// Raw buffer for the `sysinfo(2)` syscall.
///
/// In the Linux ABI `uptime` is a `long` at offset 0. The remaining fields are
/// not needed, but are declared to give the struct its correct size (112 bytes
/// on 64-bit Linux).
///
/// The layout matches the kernel's `struct sysinfo` *exactly*:
/// `mem_unit` ends at offset 108, then 4 bytes of implicit padding to 112.
#[repr(C)]
struct SysInfo {
uptime: i64,
loads: [u64; 3],
totalram: u64,
freeram: u64,
sharedram: u64,
bufferram: u64,
totalswap: u64,
freeswap: u64,
procs: u16,
_pad: u16,
_pad2: u32, // alignment padding to reach 8-byte boundary for totalhigh
totalhigh: u64,
freehigh: u64,
mem_unit: u32,
// 4 bytes implicit trailing padding to reach 112 bytes total; no field
// needed
}
/// Direct `sysinfo(2)` syscall using inline assembly
///
/// # Safety
///
/// The caller must ensure the sysinfo pointer is valid.
#[inline]
unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
#[cfg(target_arch = "x86_64")]
{
let ret: i64;
unsafe {
std::arch::asm!(
"syscall",
in("rax") 99_i64, // __NR_sysinfo
in("rdi") info,
out("rcx") _,
out("r11") _,
lateout("rax") ret,
options(nostack)
);
}
ret
}
#[cfg(target_arch = "aarch64")]
{
let ret: i64;
unsafe {
std::arch::asm!(
"svc #0",
in("x8") 179_i64, // __NR_sysinfo
in("x0") info,
lateout("x0") ret,
options(nostack)
);
}
ret
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{
compile_error!("Unsupported architecture for inline assembly syscalls");
}
}
/// Gets the current system uptime.
///
/// # Errors
///
/// Returns an error if the system uptime cannot be retrieved.
#[cfg_attr(feature = "hotpath", hotpath::measure)]
pub fn get_current() -> Result<String, io::Error> {
let uptime_seconds = {
let mut info = MaybeUninit::uninit();
if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 {
return Err(io::Error::last_os_error());
}
#[allow(clippy::cast_sign_loss)]
unsafe {
info.assume_init().uptime as u64
}
};
let days = uptime_seconds / 86400;
let hours = (uptime_seconds / 3600) % 24;
let minutes = (uptime_seconds / 60) % 60;
let mut result = String::with_capacity(32);
let mut buf = [0u8; 20]; // Enough for u64::MAX
if days > 0 {
result.push_str(itoa(days, &mut buf));
result.push_str(if days == 1 { " day" } else { " days" });
}
if hours > 0 {
if !result.is_empty() {
result.push_str(", ");
}
result.push_str(itoa(hours, &mut buf));
result.push_str(if hours == 1 { " hour" } else { " hours" });
}
if minutes > 0 {
if !result.is_empty() {
result.push_str(", ");
}
result.push_str(itoa(minutes, &mut buf));
result.push_str(if minutes == 1 { " minute" } else { " minutes" });
}
if result.is_empty() {
result.push_str("less than a minute");
}
Ok(result)
}