Full Code of rust-random/getrandom for AI

master 4a01cb2c02b2 cached
58 files
203.2 KB
58.5k tokens
180 symbols
1 requests
Download .txt
Showing preview only (218K chars total). Download the full file or copy to clipboard to get everything.
Repository: rust-random/getrandom
Branch: master
Commit: 4a01cb2c02b2
Files: 58
Total size: 203.2 KB

Directory structure:
gitextract_26_m99a6/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── build.yml
│       ├── nopanic.yaml
│       ├── release.yml
│       ├── tests.yml
│       └── workspace.yml
├── .gitignore
├── .typos.toml
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── SECURITY.md
├── benches/
│   └── buffer.rs
├── build.rs
├── custom_impl_test/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── nopanic_check/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── src/
│   ├── backends/
│   │   ├── apple_other.rs
│   │   ├── custom.rs
│   │   ├── efi_rng.rs
│   │   ├── esp_idf.rs
│   │   ├── extern_impl.rs
│   │   ├── fuchsia.rs
│   │   ├── getentropy.rs
│   │   ├── getrandom.rs
│   │   ├── hermit.rs
│   │   ├── linux_android_with_fallback.rs
│   │   ├── linux_raw.rs
│   │   ├── netbsd.rs
│   │   ├── rdrand.rs
│   │   ├── rndr.rs
│   │   ├── solaris.rs
│   │   ├── solid.rs
│   │   ├── unsupported.rs
│   │   ├── use_file.rs
│   │   ├── vxworks.rs
│   │   ├── wasi_p1.rs
│   │   ├── wasi_p2_3.rs
│   │   ├── wasm_js.rs
│   │   ├── windows.rs
│   │   └── windows_legacy.rs
│   ├── backends.rs
│   ├── error.rs
│   ├── error_std_impls.rs
│   ├── lib.rs
│   ├── sys_rng.rs
│   ├── util.rs
│   └── utils/
│       ├── get_errno.rs
│       ├── lazy_bool.rs
│       ├── lazy_ptr.rs
│       ├── sanitizer.rs
│       └── sys_fill_exact.rs
└── tests/
    ├── mod.rs
    └── sys_rng.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
# Allow normal use of "cargo run" and "cargo test" on these wasm32 platforms.
[target.wasm32-unknown-unknown]
runner = 'wasm-bindgen-test-runner'
[target.wasm32-wasip1]
runner = 'wasmtime'
[target.wasm32-wasip2]
runner = 'wasmtime'
[target.wasm32-wasip3]
runner = 'wasmtime'

# Just run on node by default (that's where emscripten is tested)
[target.'cfg(target_os = "emscripten")']
runner = 'node'

[resolver]
incompatible-rust-versions = "allow"


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: cargo
  directory: "/"
  versioning-strategy: lockfile-only
  allow:
    - dependency-type: "all"
  schedule:
    interval: weekly
  groups:
    all-deps:
      patterns:
        - "*"
- package-ecosystem: "github-actions"
  directory: "/"
  schedule:
    interval: weekly


================================================
FILE: .github/workflows/build.yml
================================================
name: Build

on:
  push:
    branches: master
  pull_request:
    branches: master
  schedule:
    - cron: "0 12 * * 1"

permissions:
  contents: read

env:
  CARGO_INCREMENTAL: 0
  RUSTFLAGS: "-Dwarnings"

jobs:
  macos:
    name: Apple Other
    # visionOS requires Xcode 15.2+, which is only available on the arm64 runners.
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly
        with:
          targets: aarch64-apple-darwin, aarch64-apple-ios
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --no-run --target=aarch64-apple-darwin --features=std
      - run: cargo test --no-run --target=aarch64-apple-ios --features=std
      - run: cargo test --no-run --target=aarch64-apple-tvos -Zbuild-std --features=std
      - run: cargo test --no-run --target=aarch64-apple-watchos -Zbuild-std --features=std
      # visionOS requires Xcode 15.2+, GitHub Actions defaults to an older version.
      - run: sudo xcode-select -switch /Applications/Xcode_15.2.app
      # std is broken on visionOS right now
      #- run: cargo test --no-run --target=aarch64-apple-visionos -Zbuild-std --features=std

  cross:
    name: Cross
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          # This target is currently broken:
          # https://github.com/rust-random/getrandom/actions/runs/12949235456/job/36119544880
          # sparcv9-sun-solaris,
          x86_64-unknown-illumos,
        ]
    steps:
      - uses: actions/checkout@v6
      - name: Install precompiled cross
        run: |
          VERSION=v0.2.5
          URL=https://github.com/cross-rs/cross/releases/download/${VERSION}/cross-x86_64-unknown-linux-gnu.tar.gz
          wget -O - $URL | tar -xz -C ~/.cargo/bin
          cross --version
      - name: Build Tests
        run: cross test --no-run --target=${{ matrix.target }} --features=std

  tier2:
    name: Tier 2
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          aarch64-linux-android,
          x86_64-unknown-fuchsia,
          x86_64-unknown-redox,
          x86_64-fortanix-unknown-sgx,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
      - name: Build
        run: cargo build --target=${{ matrix.target }} --features=std

  tier3:
    name: Tier 3
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          aarch64-kmc-solid_asp3,
          aarch64-unknown-nto-qnx710,
          armv6k-nintendo-3ds,
          armv7-sony-vita-newlibeabihf,
          i686-unknown-hurd-gnu,
          riscv32imc-esp-espidf,
          x86_64-unknown-hermit,
          x86_64-wrs-vxworks,
          x86_64-unknown-dragonfly,
          x86_64-unknown-haiku,
          x86_64-unknown-linux-none,
          x86_64-pc-cygwin,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly # Required to build libcore
        with:
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - run: cargo build -Z build-std=core --target=${{ matrix.target }}

  # Ubuntu does not support running x32 binaries:
  # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1994516/comments/21
  linux-x32:
    name: Linux x32
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [x86_64-unknown-linux-gnux32]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - name: Install libc and libgcc
        run: |
          sudo apt-get update
          sudo apt-get install --no-install-recommends libc6-dev-x32 libx32gcc-11-dev
      - uses: Swatinem/rust-cache@v2
      - run: cargo build --target=${{ matrix.target }} --features=std
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
        run: cargo build --target=${{ matrix.target }} --features=std
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback
        run: cargo build --features=std
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
        run: cargo build --features=std

  linux-raw:
    name: Build Raw Linux
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          arm-unknown-linux-gnueabihf,
          aarch64-unknown-linux-gnu,
          loongarch64-unknown-linux-gnu,
          riscv32gc-unknown-linux-gnu,
          riscv64gc-unknown-linux-gnu,
          s390x-unknown-linux-gnu,
          i686-unknown-linux-gnu,
          x86_64-unknown-linux-gnu,
          x86_64-unknown-linux-gnux32,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-09-28
          components: rust-src
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
        run: cargo build -Zbuild-std=core --target=${{ matrix.target }}

  web:
    name: ${{ matrix.target.description }} ${{ matrix.feature.description }} ${{ matrix.atomic.description }}
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        target: [
          { description: Web, target: wasm32-unknown-unknown },
          { description: WasmV1, target: wasm32v1-none },
        ]
        feature: [
          { description: no_std, feature: "--features wasm_js", build-std: "core,alloc", std: false },
          { feature: "--features wasm_js,std", build-std: "panic_abort,std", std: true },
        ]
        atomic: [
          { flags: "" },
          { description: with Atomics, flags: "-Ctarget-feature=+atomics,bulk-memory" },
        ]
        exclude:
          - target: { target: wasm32v1-none }
            feature: { std: true }
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          targets: ${{ matrix.target.target }}
          toolchain: nightly-2025-09-28
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - name: Build
        run: cargo build --target ${{ matrix.target.target }} ${{ matrix.feature.feature }} -Zbuild-std=${{ matrix.feature.build-std }}

  efi-rng:
    name: UEFI RNG Protocol
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          aarch64-unknown-uefi,
          x86_64-unknown-uefi,
          i686-unknown-uefi,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly # Required to build libstd
        with:
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="efi_rng"
        run: cargo build -Z build-std=std --target=${{ matrix.target }} --features std

  rdrand-uefi:
    name: RDRAND UEFI
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          x86_64-unknown-uefi,
          i686-unknown-uefi,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly # Required to build libcore
        with:
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
        run: cargo build -Z build-std=core --target=${{ matrix.target }}
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
        run: cargo build -Z build-std=std --target=${{ matrix.target }} --features std

  rndr:
    name: RNDR
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          targets: aarch64-unknown-linux-gnu, aarch64-apple-darwin
      - uses: Swatinem/rust-cache@v2
      - name: RNDR enabled at compile time (Linux)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rndr" -C target-feature=+rand
        run: cargo build --target=aarch64-unknown-linux-gnu
      - name: Runtime RNDR detection without std (Linux)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rndr"
        run: cargo build --target=aarch64-unknown-linux-gnu
      - name: Runtime RNDR detection with std (macOS)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rndr"
        run: cargo build --target=aarch64-unknown-linux-gnu --features std

  no-atomics:
    name: No Atomics
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: riscv32i-unknown-none-elf
      - uses: Swatinem/rust-cache@v2
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="unsupported"
        run: cargo build --target riscv32i-unknown-none-elf

  unsupported:
    name: Runtime error
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: wasm32-unknown-unknown
      - uses: Swatinem/rust-cache@v2
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="unsupported"
        run: cargo build --target wasm32-unknown-unknown


================================================
FILE: .github/workflows/nopanic.yaml
================================================
# This CI config checks that  getrandom's backend implementation
# do not contain potential panics.
#
# It is unclear how to implement a no-panic check for esp_idf, fuchsia,
# vxworks, hermit, and solid backends, so we do not check them here,
# but they still should be panic-free. We do not check wasm_js backend
# since glue code generated by wasm-bindgen contains potential panics,
# so resulting WASM files inevitably contain potential panics for any
# code which non-trivially interacts with the JS enviroment.
name: No panic

on:
  push:
    branches: master
  pull_request:
    branches: master

permissions:
  contents: read

defaults:
  run:
    working-directory: nopanic_check

env:
  RUSTFLAGS: "-Dwarnings"

jobs:
  linux:
    name: Linux
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          targets: wasm32-wasip1, wasm32-wasip2
      - uses: Swatinem/rust-cache@v2
      
      - name: Build (linux_android_with_fallback.rs)
        run: cargo build --release
      - name: Check (linux_android_with_fallback.rs)
        run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so ))

      - name: Build (getrandom.rs)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
        run: cargo build --release
      - name: Check (getrandom.rs)
        run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so ))

      - name: Build (linux_raw.rs)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
        run: cargo build --release
      - name: Check (linux_raw.rs)
        run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so ))

      - name: Build (rdrand.rs)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
        run: cargo build --release
      - name: Check (rdrand.rs)
        run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so ))

      - name: Build (custom.rs)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
        run: cargo build --release
      - name: Check (custom.rs)
        run: (exit $( grep -c panic target/release/libgetrandom_wrapper.so ))

      - name: Build (wasi.rs, preview 1)
        run: cargo build --release --target wasm32-wasip1
      - name: Check (wasi.rs, preview 1)
        run: (exit $( grep -c panic target/wasm32-wasip1/release/getrandom_wrapper.wasm ))

      - name: Build (wasi.rs, preview 2)
        run: cargo build --release --target wasm32-wasip2
      - name: Check (wasi.rs, preview 2)
        run: (exit $( grep -c panic target/wasm32-wasip2/release/getrandom_wrapper.wasm ))

  cross:
    name: Cross
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          components: rust-src
          targets: aarch64-unknown-linux-gnu,x86_64-unknown-netbsd,x86_64-unknown-freebsd,x86_64-pc-solaris
      - uses: Swatinem/rust-cache@v2
      # TODO: use pre-compiled cross after a new (post-0.2.5) release
      - name: Install cross
        env:
          # Allow compiler warnings during cross installation
          RUSTFLAGS:
        run: cargo install cross --force --git https://github.com/cross-rs/cross

      - name: Build (rndr.rs)
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rndr"
        run: cross build --release --target=aarch64-unknown-linux-gnu
      - name: Check (rndr.rs)
        run: (exit $( grep -c panic target/aarch64-unknown-linux-gnu/release/libgetrandom_wrapper.so ))

      - name: Build (netbsd.rs)
        run: cross build --release --target=x86_64-unknown-netbsd
      - name: Check (netbsd.rs)
        run: (exit $( grep -c panic target/x86_64-unknown-netbsd/release/libgetrandom_wrapper.so ))

      - name: Build (solaris.rs)
        run: cross build --release --target=x86_64-pc-solaris
      - name: Check (solaris.rs)
        run: (exit $( grep -c panic target/x86_64-pc-solaris/release/libgetrandom_wrapper.so ))

  macos:
    name: macOS
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          targets: aarch64-apple-ios
      - uses: Swatinem/rust-cache@v2
      
      # We do not need the grep check since linker fails
      # if `panic_nonexistent` can not be eliminated
      - name: Build (getentropy.rs)
        run: cargo build --release --target=aarch64-apple-darwin
      - name: Build (apple-other.rs)
        run: cargo build --release --target=aarch64-apple-ios

  windows:
    name: Windows
    runs-on: windows-2022
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-09-28
          components: rust-src
      - run: cargo build --release
      - run: cargo build --release --target=x86_64-win7-windows-msvc -Zbuild-std="std,panic_abort"


================================================
FILE: .github/workflows/release.yml
================================================
name: Publish to crates.io
on:
  push:
    tags: ['v*']  # Triggers when pushing tags starting with 'v'
jobs:
  publish:
    runs-on: ubuntu-latest
    environment: release  # Optional: for enhanced security
    permissions:
      id-token: write     # Required for OIDC token exchange
    steps:
    - uses: actions/checkout@v6
    - uses: rust-lang/crates-io-auth-action@v1
      id: auth
    - run: cargo publish
      env:
        CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}


================================================
FILE: .github/workflows/tests.yml
================================================
name: Test

on:
  push:
    branches: master
  pull_request:
    branches: master
  schedule:
    - cron: "0 12 * * 1"

permissions:
  contents: read

env:
  CARGO_INCREMENTAL: 0
  RUST_BACKTRACE: 1
  RUSTFLAGS: "-Dwarnings"

jobs:
  tier1:
    name: Tier 1
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-24.04, windows-2022]
        toolchain: [nightly, beta, stable, "1.85"]
        # Only Test macOS on stable to reduce macOS CI jobs
        include:
          # aarch64-apple-darwin.
          - os: macos-14
            toolchain: stable
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.toolchain }}
      - uses: Swatinem/rust-cache@v2
      - run: cargo test
      # Make sure enabling the std feature doesn't break anything
      - run: |
          cargo test --features=std
          cargo test --features=sys_rng
          cargo test --features=std,sys_rng
      - if: ${{ matrix.toolchain == 'nightly' }}
        run: cargo test --benches

  linux:
    name: Linux
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [x86_64-unknown-linux-musl, i686-unknown-linux-musl]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --target=${{ matrix.target }} --features=std,sys_rng
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
          RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
        run: cargo test --target=${{ matrix.target }} --features=std,sys_rng
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
          RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
        run: cargo test --target=${{ matrix.target }} --features=std,sys_rng
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback
          RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback
        run: cargo test --features=std,sys_rng
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback
          RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback
        run: cargo test --features=std,sys_rng
      - env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
          RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
        run: cargo test --features=std,sys_rng

  custom_impl:
    name: Custom and External Implementations
    runs-on: ubuntu-24.04
    defaults:
      run:
        working-directory: custom_impl_test
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly
      - uses: Swatinem/rust-cache@v2
      - name: Test getrandom_backend="custom"
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
        run: cargo test
      - name: Test getrandom_backend="extern_impl"
        env:
          RUSTFLAGS: -Dwarnings --cfg getrandom_backend="extern_impl"
        run: cargo test

  ios:
    name: iOS Simulator
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: 1.88.0
          targets: aarch64-apple-ios-sim
      - name: Install precompiled cargo-dinghy
        run: |
          VERSION=0.8.1
          URL="https://github.com/sonos/dinghy/releases/download/${VERSION}/cargo-dinghy-macos-${VERSION}.tgz"
          wget -O - $URL | tar -xz --strip-components=1 -C ~/.cargo/bin
      - name: Check cargo-dinghy version.
        run: cargo dinghy --version
      - name: Setup Simulator
        # Use the first installed iOS runtime and the first (i.e. oldest) supported iPhone device.
        run: |
          RUNTIME=$(xcrun simctl list runtimes --json | jq '.runtimes | map(select(.name | contains("iOS"))) | .[0]')
          RUNTIME_ID=$(echo $RUNTIME | jq -r '.identifier')
          echo "Using runtime:" $RUNTIME_ID
          DEVICE_ID=$(echo $RUNTIME | jq -r '.supportedDeviceTypes | map(select(.productFamily == "iPhone")) | .[0].identifier')
          echo "Using device:" $DEVICE_ID
          SIM_ID=$(xcrun simctl create Test-iPhone $DEVICE_ID $RUNTIME_ID)
          echo "Created simulator:" $SIM_ID
          xcrun simctl boot $SIM_ID
          echo "device=$SIM_ID" >> $GITHUB_ENV
      - uses: Swatinem/rust-cache@v2
      - name: Run tests
        run: cargo dinghy -p auto-ios-aarch64-sim -d ${{ env.device }} test

  windows:
    name: Windows
    runs-on: windows-2022
    strategy:
      matrix:
        toolchain: [
          stable-x86_64-gnu,
          stable-i686-gnu,
          stable-i686-msvc,
        ]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.toolchain }}
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --features=std,sys_rng

  windows7:
    name: Windows 7 (on Windows 10)
    runs-on: windows-2022
    steps:
      - uses: actions/checkout@v6
      # Win7 targets are Tier3, so pin a nightly where libstd builds.
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-09-28
          components: rust-src
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --target=x86_64-win7-windows-msvc -Z build-std --features=std,sys_rng
      - run: cargo test --target=i686-win7-windows-msvc -Z build-std --features=std,sys_rng

  sanitizer-linux:
    name: Sanitizer Linux
    runs-on: ${{ matrix.runner }}
    strategy:
      matrix:
        include:
          # MemorySanitizer won't run in QEMU so we can't run it in cross:
          # https://github.com/llvm/llvm-project/issues/65144
          - arch: aarch64
            runner: ubuntu-24.04-arm
          - arch: x86_64
            runner: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-09-28
          components: rust-src
      # Use --all-targets to skip doctests, which don't work with the -Zsanitizer=memory flag.
      # See: https://github.com/rust-lang/rust/issues/134172
      - name: default configuration
        env:
          RUSTFLAGS: -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - name: --cfg getrandom_backend="linux_getrandom"
        env:
          RUSTFLAGS: --cfg getrandom_backend="linux_getrandom" -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - name: --cfg getrandom_backend="linux_raw"
        env:
          RUSTFLAGS: --cfg getrandom_backend="linux_raw" -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - name: --cfg getrandom_backend="linux_fallback"
        env:
          RUSTFLAGS: --cfg getrandom_backend="linux_fallback" -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - if: ${{ matrix.arch == 'x86_64' }}
        name: --cfg getrandom_backend="rdrand"
        env:
          RUSTFLAGS: --cfg getrandom_backend="rdrand" -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - name: --cfg getrandom_test_linux_fallback
        env:
          RUSTFLAGS: --cfg getrandom_test_linux_fallback -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu
      - name: --cfg getrandom_test_linux_without_fallback
        env:
          RUSTFLAGS: --cfg getrandom_test_linux_without_fallback -Dwarnings -Zsanitizer=memory
        run: cargo test --all-targets -Zbuild-std --target=${{ matrix.arch }}-unknown-linux-gnu

  cross:
    name: Cross
    runs-on: ubuntu-24.04
    strategy:
      matrix:
        target: [
          aarch64-unknown-linux-gnu,
          # TODO: add Android tests back when the cross cuts a new release.
          # See: https://github.com/cross-rs/cross/issues/1222
          # aarch64-linux-android,
          # This target is currently broken:
          # https://github.com/rust-random/getrandom/actions/runs/15109500597/job/42465556156
          #powerpc-unknown-linux-gnu,
          riscv64gc-unknown-linux-gnu,
          # This target is currently broken:
          # https://github.com/rust-random/getrandom/actions/runs/12949235459/job/36119546920
          #wasm32-unknown-emscripten,
        ]
    steps:
      - uses: actions/checkout@v6
      - name: Install precompiled cross
        run: |
          VERSION=v0.2.5
          URL=https://github.com/cross-rs/cross/releases/download/${VERSION}/cross-x86_64-unknown-linux-gnu.tar.gz
          wget -O - $URL | tar -xz -C ~/.cargo/bin
          cross --version
      - name: Test
        run: cross test --no-fail-fast --target=${{ matrix.target }} --features=std,sys_rng

  freebsd:
    name: FreeBSD VM
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - name: Test in FreeBSD
        uses: vmactions/freebsd-vm@v1
        with:
          envs: 'RUSTFLAGS'
          usesh: true
          prepare: |
            pkg install -y rust
          run: cargo test

  openbsd:
    name: OpenBSD VM
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - name: Test in OpenBSD
        uses: vmactions/openbsd-vm@v1
        with:
          envs: 'RUSTFLAGS'
          usesh: true
          prepare: |
            pkg_add rust
          run: cargo test

  netbsd:
    name: NetBSD VM
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - name: Test in NetBSD
        uses: vmactions/netbsd-vm@v1
        with:
          envs: 'RUSTFLAGS'
          usesh: true
          prepare: |
            /usr/sbin/pkg_add rust
          run: |
            cargo test
            RUSTFLAGS="--cfg getrandom_test_netbsd_fallback -D warnings" cargo test

  web:
    name: ${{ matrix.rust.description }}
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        rust:
          - {
              description: Web,
              version: stable,
              flags: '-Dwarnings',
              args: '--features=std,sys_rng,wasm_js',
            }
          - {
              description: Web with Atomics,
              version: nightly,
              components: rust-src,
              flags: '-Dwarnings -Ctarget-feature=+atomics,+bulk-memory',
              args: '--features=std,sys_rng,wasm_js -Zbuild-std=panic_abort,std',
            }
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust.version }}
          components: ${{ matrix.rust.components }}
      - name: Install precompiled wasm-pack
        shell: bash
        run: |
          VERSION=v0.13.1
          URL=https://github.com/rustwasm/wasm-pack/releases/download/${VERSION}/wasm-pack-${VERSION}-x86_64-unknown-linux-musl.tar.gz
          wget -O - $URL | tar -xz --strip-components=1 -C ~/.cargo/bin
          wasm-pack --version
      - uses: Swatinem/rust-cache@v2
      - name: Test (Node)
        env:
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        run: wasm-pack test --node -- ${{ matrix.rust.args }}
      - name: Test (Firefox)
        env:
          WASM_BINDGEN_USE_BROWSER: 1
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        run: wasm-pack test --headless --firefox -- ${{ matrix.rust.args }}
      - name: Test (Chrome)
        env:
          WASM_BINDGEN_USE_BROWSER: 1
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        run: wasm-pack test --headless --chrome -- ${{ matrix.rust.args }}
      - name: Test (dedicated worker)
        env:
          WASM_BINDGEN_USE_DEDICATED_WORKER: 1
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        run: wasm-pack test --headless --firefox -- ${{ matrix.rust.args }}
      - name: Test (shared worker)
        env:
          WASM_BINDGEN_USE_SHARED_WORKER: 1
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        run: wasm-pack test --headless --firefox -- ${{ matrix.rust.args }}
      - name: Test (service worker)
        env:
          WASM_BINDGEN_USE_SERVICE_WORKER: 1
          RUSTFLAGS: ${{ matrix.rust.flags }}
          RUSTDOCFLAGS: ${{ matrix.rust.flags }}
        # Firefox doesn't support module service workers and therefor can't import scripts
        run: wasm-pack test --headless --chrome -- ${{ matrix.rust.args }}

  wasi_p1:
    name: WASIp1
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: 1.85
          targets: wasm32-wasip1
      - name: Install Wasmtime
        run: |
          VERSION=v40.0.0
          URL=https://github.com/bytecodealliance/wasmtime/releases/download/${VERSION}/wasmtime-${VERSION}-x86_64-linux.tar.xz
          wget -O - $URL | tar -xJ --strip-components=1 -C ~/.cargo/bin
          wasmtime --version
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --target wasm32-wasip1

  wasi_p2:
    name: WASIp2
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: 1.85
          targets: wasm32-wasip2
      - name: Install Wasmtime
        run: |
          VERSION=v40.0.0
          URL=https://github.com/bytecodealliance/wasmtime/releases/download/${VERSION}/wasmtime-${VERSION}-x86_64-linux.tar.xz
          wget -O - $URL | tar -xJ --strip-components=1 -C ~/.cargo/bin
          wasmtime --version
      - uses: Swatinem/rust-cache@v2
      # TODO(MSRV-1.87): Remove this step.
      - name: Generate MSRV-compatible Cargo.lock
        env:
          CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: "fallback"
        run: cargo update -p wasip2
      - run: cargo test --target wasm32-wasip2

  # TODO: enable after pre-built std will be provided by Rust 
  # wasi_p3:
  #   name: WASIp3
  #   runs-on: ubuntu-24.04
  #   steps:
  #     - uses: actions/checkout@v6
  #     - uses: dtolnay/rust-toolchain@master
  #       with:
  #         toolchain: 1.90
  #         targets: wasm32-wasip3
  #     - name: Install Wasmtime
  #       run: |
  #         VERSION=v40.0.0
  #         URL=https://github.com/bytecodealliance/wasmtime/releases/download/${VERSION}/wasmtime-${VERSION}-x86_64-linux.tar.xz
  #         wget -O - $URL | tar -xJ --strip-components=1 -C ~/.cargo/bin
  #         wasmtime --version
  #     - uses: Swatinem/rust-cache@v2
  #     - run: cargo test --target wasm32-wasip3


================================================
FILE: .github/workflows/workspace.yml
================================================
name: Workspace

on:
  push:
    branches: master
  pull_request:
    branches: master

permissions:
  contents: read

jobs:
  clippy:
    name: Clippy
    runs-on: ubuntu-24.04
    env:
      RUSTFLAGS: "-Dwarnings"
    steps:
    - uses: actions/checkout@v6
    - uses: dtolnay/rust-toolchain@master
      with:
        # We need Nightly for -Zbuild-std.
        # Fixed Nigthly version is used to prevent
        # CI failures which are not relevant to PR changes
        # on introduction of new Clippy lints.
        toolchain: nightly-2025-09-28
        components: clippy,rust-src
    - name: std feature
      run: cargo clippy --features std
    - name: custom backend
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="custom"
      run: cargo clippy -Zbuild-std=core --target riscv32i-unknown-none-elf
    - name: iOS (apple-other.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-apple-ios
    - name: ESP-IDF (espidf.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="esp_idf"
      run: cargo clippy -Zbuild-std=core --target riscv32imc-esp-espidf
    - name: Fuchsia (fuchsia.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-unknown-fuchsia
    - name: OpenBSD (getentropy.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-unknown-openbsd
    - name: Hermit (hermit.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-unknown-hermit
    - name: Web WASM (wasm_js.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
      run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown --features wasm_js
    - name: Web WASM with atomics (wasm_js.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
      run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown --features wasm_js
    - name: Linux (getrandom.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
      run: cargo clippy --target x86_64-unknown-linux-gnu
    - name: Linux (linux_android_with_fallback.rs)
      run: cargo clippy --target x86_64-unknown-linux-gnu
    - name: Linux (linux_raw.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw"
      run: cargo clippy --target x86_64-unknown-linux-gnu
    - name: NetBSD (netbsd.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-unknown-netbsd
    - name: Fortranix SGX (rdrand.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-fortanix-unknown-sgx
    - name: RNDR (rndr.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rndr"
      run: cargo clippy -Zbuild-std=core --target aarch64-unknown-linux-gnu
    - name: EFI RNG (efi_rng.rs)
      env:
        RUSTFLAGS: -Dwarnings --cfg getrandom_backend="efi_rng"
      run: cargo clippy -Zbuild-std=std --target x86_64-unknown-uefi
    - name: Solaris (solaris.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-pc-solaris
    - name: SOLID (solid.rs)
      run: cargo clippy -Zbuild-std=core --target aarch64-kmc-solid_asp3
    - name: Redox (use_file.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-unknown-redox
    - name: VxWorks (vxworks.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-wrs-vxworks
    - name: WASI preview 1 (wasi.rs)
      run: cargo clippy -Zbuild-std=core --target wasm32-wasip1
    - name: WASI preview 2 (wasi.rs)
      run: cargo clippy -Zbuild-std=core,alloc --target wasm32-wasip2
    - name: Windows 7 (windows7.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-win7-windows-msvc
    - name: Windows (windows.rs)
      run: cargo clippy -Zbuild-std=core --target x86_64-pc-windows-msvc

  fmt:
    name: rustfmt
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - uses: Swatinem/rust-cache@v2
      - name: fmt
        run: cargo fmt --all -- --check

  doc:
    name: rustdoc
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@master
        with:
          # We need Nightly for doc_cfg
          toolchain: nightly-2026-01-25
      - uses: Swatinem/rust-cache@v2
      - name: Generate Docs
        env:
          RUSTDOCFLAGS: -Dwarnings --cfg docsrs --cfg getrandom_backend="extern_impl"
        run: cargo doc --no-deps --features std,sys_rng

  typos:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: crate-ci/typos@v1

  lockfile:
    name: Check Cargo.lock
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo check --workspace --locked


================================================
FILE: .gitignore
================================================
/target
**/*.rs.bk
nopanic_check/Cargo.lock
nopanic_check/target/
custom_impl_test/Cargo.lock
custom_impl_test/target/


================================================
FILE: .typos.toml
================================================
[files]
extend-exclude = [
    ".git/"
]

[default.extend-words]
"nto" = "nto"


================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- Restore MSRV to 1.85 for wasm32-wasip3 targets. [#824]

[Unreleased]: https://github.com/rust-random/getrandom/compare/v0.4.2...master
[#824]: https://github.com/rust-random/getrandom/pull/824

## [0.4.2] - 2026-03-03

### Changed
- Bump `r-efi` dependency to v6 [#814]

### Fixed
- Read `errno` only when it is set [#810]
- Check the return value of `ProcessPrng` on Windows [#811]

[0.4.2]: https://github.com/rust-random/getrandom/compare/v0.4.1...v0.4.2
[#810]: https://github.com/rust-random/getrandom/pull/810
[#811]: https://github.com/rust-random/getrandom/pull/811
[#814]: https://github.com/rust-random/getrandom/pull/814

## [0.4.1] - 2026-02-03

### Fixed
- Documentation build on docs.rs [#801]

[0.4.1]: https://github.com/rust-random/getrandom/compare/v0.4.0...v0.4.1
[#801]: https://github.com/rust-random/getrandom/pull/801

## [0.4.0] - 2026-02-02

### Added
- `RawOsError` type alias [#739]
- `SysRng` behind new feature `sys_rng` [#751]
- WASIp3 support [#779]
- `extern_impl` opt-in backend [#786] [#794]
- Motor OS support [#797]

### Changed
- Use Edition 2024 and MSRV 1.85 [#749]

[0.4.0]: https://github.com/rust-random/getrandom/compare/v0.3.4...v0.4.0
[#739]: https://github.com/rust-random/getrandom/pull/739
[#749]: https://github.com/rust-random/getrandom/pull/749
[#751]: https://github.com/rust-random/getrandom/pull/751
[#779]: https://github.com/rust-random/getrandom/pull/779
[#786]: https://github.com/rust-random/getrandom/pull/786
[#794]: https://github.com/rust-random/getrandom/pull/794
[#797]: https://github.com/rust-random/getrandom/pull/797

## [0.3.4] - 2025-10-14

### Major change to `wasm_js` backend

Now, when the `wasm_js` feature is enabled, the `wasm_js` backend will be used
by default. Users of `wasm32-unknown-unknown` targeting JavaScript environments
like the Web and Node.js will no longer need to specify:
```
--cfg getrandom_backend="wasm_js"
```
in `RUSTFLAGS` for the crate to compile. They can now simple enable a feature.

Note: this should not affect non-JS users of the `wasm32-unknown-unknown`
target. Using `--cfg getrandom_backend` will still override the source of
randomness _even if_ the `wasm_js` feature is enabled. This includes
`--cfg getrandom_backend=custom` and `--cfg getrandom_backend=unsupported`.

For more information, see the discussions in [#671], [#675], and [#730].

### Added
- `unsupported` opt-in backend [#667]
- `windows_legacy` opt-in backend [#724]

### Changed
- Implement Memory Sanitizer unpoisoning more precisely [#678]
- Relax MSRV for the `linux_raw` opt-in backend on ARM targets [#688]
- Use `getrandom` syscall on all RISC-V Linux targets [#699]
- Replaced `wasi` dependency with `wasip2` [#721]
- Enable `wasm_js` backend by default if the `wasm_js` feature is enabled [#730]

### Removed
- Unstable `rustc-dep-of-std` crate feature [#694]

[0.3.4]: https://github.com/rust-random/getrandom/compare/v0.3.3...v0.3.4
[#667]: https://github.com/rust-random/getrandom/pull/667
[#671]: https://github.com/rust-random/getrandom/issues/671
[#675]: https://github.com/rust-random/getrandom/pull/675
[#678]: https://github.com/rust-random/getrandom/pull/678
[#688]: https://github.com/rust-random/getrandom/pull/688
[#694]: https://github.com/rust-random/getrandom/pull/694
[#699]: https://github.com/rust-random/getrandom/pull/699
[#721]: https://github.com/rust-random/getrandom/pull/721
[#724]: https://github.com/rust-random/getrandom/pull/724
[#730]: https://github.com/rust-random/getrandom/pull/730

## [0.3.3] - 2025-05-09

### Changed
- Doc improvements [#632] [#634] [#635]
- Add crate version to docs.rs links used in `compile_error!`s [#639]

### Fixed
- Error handling in WASI p1 [#661]

[0.3.3]: https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3
[#632]: https://github.com/rust-random/getrandom/pull/632
[#634]: https://github.com/rust-random/getrandom/pull/634
[#635]: https://github.com/rust-random/getrandom/pull/635
[#639]: https://github.com/rust-random/getrandom/pull/639
[#661]: https://github.com/rust-random/getrandom/pull/661

## [0.3.2] - 2025-03-17

### Added
- `efi_rng` opt-in backend [#570]
- `linux_raw` opt-in backend [#572]
- `.cargo/config.toml` example in the crate-level docs [#591]
- `getrandom_test_linux_without_fallback` configuration flag to test that file fallback
  is not triggered in the `linux_android_with_fallback` backend [#605]
- Built-in support for `*-linux-none` targets [#618]
- Cygwin support [#626]

### Changed
- Update `wasi` dependency to v0.14 [#594]
- Add `#[inline]` attribute to the inner functions [#596]
- Update WASI and Emscripten links in the crate-level docs [#597]
- Do not use `dlsym` on MUSL targets in the `linux_android_with_fallback` backend [#602]
- Remove `linux_android.rs` and use `getrandom.rs` instead [#603]
- Always use `RtlGenRandom` on Windows targets when compiling with pre-1.78 Rust [#610]
- Internal representation of the `Error` type [#614]
- Remove `windows-targets` dependency and use [`raw-dylib`] directly [#627]

### Removed
- `Error::INTERNAL_START` and `Error::CUSTOM_START` associated constants [#614]

[0.3.2]: https://github.com/rust-random/getrandom/compare/v0.3.1...v0.3.2
[#570]: https://github.com/rust-random/getrandom/pull/570
[#572]: https://github.com/rust-random/getrandom/pull/572
[#591]: https://github.com/rust-random/getrandom/pull/591
[#594]: https://github.com/rust-random/getrandom/pull/594
[#596]: https://github.com/rust-random/getrandom/pull/596
[#597]: https://github.com/rust-random/getrandom/pull/597
[#602]: https://github.com/rust-random/getrandom/pull/602
[#603]: https://github.com/rust-random/getrandom/pull/603
[#605]: https://github.com/rust-random/getrandom/pull/605
[#610]: https://github.com/rust-random/getrandom/pull/610
[#614]: https://github.com/rust-random/getrandom/pull/614
[#618]: https://github.com/rust-random/getrandom/pull/618
[#626]: https://github.com/rust-random/getrandom/pull/626
[#627]: https://github.com/rust-random/getrandom/pull/627
[`raw-dylib`]: https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=link#dylib-versus-raw-dylib

## [0.3.1] - 2025-01-28

### Fixed
- Build error on Android [#588]

[0.3.1]: https://github.com/rust-random/getrandom/compare/v0.3.0...v0.3.1
[#588]: https://github.com/rust-random/getrandom/pull/588

## [0.3.0] - 2025-01-25

### Breaking Changes

#### Changed
- Bump MSRV to 1.63 [#542]
- Rename `getrandom` and `getrandom_uninit` functions to `fill` and `fill_uninit` respectively [#532]

#### Removed
- `wasm32-wasi` target support (use `wasm32-wasip1` or `wasm32-wasip2` instead) [#499]
- `linux_disable_fallback`, `rdrand`, `js`, `test-in-browser`, and `custom` crate features
  in favor of configuration flags [#504]
- `register_custom_getrandom!` macro [#504]
- Implementation of `From<NonZeroU32>` for `Error` and `Error::code` method [#507]
- Internet Explorer 11 support [#554]
- Target-specific associated `Error` constants [#562]

### Changed
- Use `ProcessPrng` on Windows 10 and up, and use `RtlGenRandom` on older Windows versions [#415]
- Do not use locale-specific `strerror_r` for retrieving error code descriptions [#440]
- Avoid assuming `usize` is the native word size in the `rdrand` backend [#442]
- Do not read from `errno` when `libc` did not indicate error on Solaris [#448]
- Switch from `libpthread`'s mutex to `futex` on Linux and to `nanosleep`-based wait loop
  on other targets in the `use_file` backend [#490]
- Do not retry on `EAGAIN` while polling `/dev/random` on Linux [#522]
- Remove separate codepath for Node.js in the `wasm_js` backend
  (bumps minimum supported Node.js version to v19) [#557]
- Use `js_namespace` in the `wasm_js` backend [#559]
 
### Added
- `wasm32-wasip1` and `wasm32-wasip2` support [#499]
- `getrandom_backend` configuration flag for selection of opt-in backends [#504]
- `Error::new_custom` method [#507]
- `rndr` opt-in backend [#512]
- Automatic MemorySanitizer support [#521] [#571]
- `u32` and `u64` functions for generating random values of the respective type [#544]
- `wasm32v1-none` support in the `wasm_js` backend [#560]
- `wasm_js` crate feature which allows users to enable the `wasm_js` opt-in backend [#574]

### Fixed
- NetBSD fallback code based on `KERN_ARND` [#555]

[0.3.0]: https://github.com/rust-random/getrandom/compare/v0.2.15...v0.3.0
[#415]: https://github.com/rust-random/getrandom/pull/415
[#440]: https://github.com/rust-random/getrandom/pull/440
[#442]: https://github.com/rust-random/getrandom/pull/442
[#448]: https://github.com/rust-random/getrandom/pull/448
[#490]: https://github.com/rust-random/getrandom/pull/490
[#499]: https://github.com/rust-random/getrandom/pull/499
[#504]: https://github.com/rust-random/getrandom/pull/504
[#507]: https://github.com/rust-random/getrandom/pull/507
[#512]: https://github.com/rust-random/getrandom/pull/512
[#521]: https://github.com/rust-random/getrandom/pull/521
[#522]: https://github.com/rust-random/getrandom/pull/522
[#532]: https://github.com/rust-random/getrandom/pull/532
[#542]: https://github.com/rust-random/getrandom/pull/542
[#544]: https://github.com/rust-random/getrandom/pull/544
[#554]: https://github.com/rust-random/getrandom/pull/554
[#555]: https://github.com/rust-random/getrandom/pull/555
[#557]: https://github.com/rust-random/getrandom/pull/557
[#559]: https://github.com/rust-random/getrandom/pull/559
[#560]: https://github.com/rust-random/getrandom/pull/560
[#562]: https://github.com/rust-random/getrandom/pull/562
[#571]: https://github.com/rust-random/getrandom/pull/571
[#574]: https://github.com/rust-random/getrandom/pull/574

## [0.2.17] - 2026-01-12
### Fixed
- Use `doc_cfg` instead of `doc_auto_cfg` (partial backport of [#732]) [#768]
- `BCryptGenRandom` signature [#778]

[0.2.17]: https://github.com/rust-random/getrandom/compare/v0.2.16...v0.2.17
[#732]: https://github.com/rust-random/getrandom/pull/732
[#768]: https://github.com/rust-random/getrandom/pull/768
[#778]: https://github.com/rust-random/getrandom/pull/778

## [0.2.16] - 2025-04-22
### Added
- Cygwin support (backport of [#626]) [#654]

[0.2.16]: https://github.com/rust-random/getrandom/compare/v0.2.15...v0.2.16
[#654]: https://github.com/rust-random/getrandom/pull/654

## [0.2.15] - 2024-05-06
### Added
- Apple visionOS support [#410]

### Changed
- Use `libc::getrandom` on DragonflyBSD, FreeBSD, illumos, and Solaris [#411] [#416] [#417] [#420]
- Unify `libc::getentropy`-based implementations [#418]

[0.2.15]: https://github.com/rust-random/getrandom/compare/v0.2.14...v0.2.15
[#410]: https://github.com/rust-random/getrandom/pull/410
[#411]: https://github.com/rust-random/getrandom/pull/411
[#416]: https://github.com/rust-random/getrandom/pull/416
[#417]: https://github.com/rust-random/getrandom/pull/417
[#418]: https://github.com/rust-random/getrandom/pull/418
[#420]: https://github.com/rust-random/getrandom/pull/420

## [0.2.14] - 2024-04-08
### Fixed
- Enable `/dev/urandom` fallback for MUSL-based Linux targets [#408]

[0.2.14]: https://github.com/rust-random/getrandom/compare/v0.2.13...v0.2.14
[#408]: https://github.com/rust-random/getrandom/pull/408

## [0.2.13] - 2024-04-06
### Added
- `linux_disable_fallback` crate feature to disable `/dev/urandom`-based fallback on Linux and
  Android targets. Enabling this feature bumps minimum supported Linux kernel version to 3.17 and
  Android API level to 23 (Marshmallow). [#396]

### Changed
- Disable `/dev/urandom` fallback for Linux targets outside of the following `target_arch`es:
  `aarch64`, `arm`, `powerpc`, `powerpc64`, `s390x`, `x86`, `x86_64` [#396]
- Do not catch `EPERM` error code on Android while checking availability of
  the `getrandom` syscall [#396]

[0.2.13]: https://github.com/rust-random/getrandom/compare/v0.2.12...v0.2.13
[#396]: https://github.com/rust-random/getrandom/pull/396

## [0.2.12] - 2024-01-09
### Fixed
- Custom backend for targets without atomics [#385]

### Changed
- Improve robustness of the Hermit backend and `sys_fill_exact` [#386]
- Raise minimum supported Apple OS versions to macOS 10.12 and iOS 10 [#388]

### Added
- Document platform support policy [#387]

[0.2.12]: https://github.com/rust-random/getrandom/compare/v0.2.11...v0.2.12
[#385]: https://github.com/rust-random/getrandom/pull/385
[#386]: https://github.com/rust-random/getrandom/pull/386
[#387]: https://github.com/rust-random/getrandom/pull/387
[#388]: https://github.com/rust-random/getrandom/pull/388

## [0.2.11] - 2023-11-08
### Added
- GNU/Hurd support [#370]

### Changed
- Renamed `__getrandom_internal` to `__GETRANDOM_INTERNAL`  [#369]
- Updated link to Hermit docs [#374]

[0.2.11]: https://github.com/rust-random/getrandom/compare/v0.2.10...v0.2.11
[#369]: https://github.com/rust-random/getrandom/pull/369
[#370]: https://github.com/rust-random/getrandom/pull/370
[#374]: https://github.com/rust-random/getrandom/pull/374

## [0.2.10] - 2023-06-06
### Added
- Support for PS Vita (`armv7-sony-vita-newlibeabihf`) [#359]

### Changed
- Use getentropy from libc on Emscripten targets [#362]

[0.2.10]: https://github.com/rust-random/getrandom/compare/v0.2.9...v0.2.10
[#359]: https://github.com/rust-random/getrandom/pull/359
[#362]: https://github.com/rust-random/getrandom/pull/362

## [0.2.9] - 2023-04-06
### Added
- AIX support [#282]
- `getrandom_uninit` function [#291]
- `wasm64-unknown-unknown` support [#303]
- tvOS and watchOS support [#317]
- QNX/nto support [#325]
- Support for `getrandom` syscall on NetBSD ≥ 10.0 [#331]
- `RtlGenRandom` fallback for non-UWP Windows [#337]

### Breaking Changes
- Update MSRV to 1.36 [#291]

### Fixed
- Solaris/OpenBSD/Dragonfly build [#301]

### Changed
- Update MSRV to 1.36 [#291]
- Use getentropy on Emscripten [#307]
- Solaris: consistently use `/dev/random` source [#310]
- Move 3ds selection above rdrand/js/custom fallback [#312]
- Remove buffer zeroing from Node.js implementation [#315]
- Use `open` instead of `open64` [#326]
- Remove #cfg from bsd_arandom.rs [#332]
- Hermit: use `sys_read_entropy` syscall [#333]
- Eliminate potential panic in sys_fill_exact [#334]
- rdrand: Remove checking for 0 and !0 and instead check CPU family and do a self-test [#335]
- Move `__getrandom_custom` definition into a const block [#344]
- Switch the custom backend to Rust ABI [#347]

[0.2.9]: https://github.com/rust-random/getrandom/compare/v0.2.8...v0.2.9
[#282]: https://github.com/rust-random/getrandom/pull/282
[#291]: https://github.com/rust-random/getrandom/pull/291
[#301]: https://github.com/rust-random/getrandom/pull/301
[#303]: https://github.com/rust-random/getrandom/pull/303
[#307]: https://github.com/rust-random/getrandom/pull/307
[#310]: https://github.com/rust-random/getrandom/pull/310
[#312]: https://github.com/rust-random/getrandom/pull/312
[#315]: https://github.com/rust-random/getrandom/pull/315
[#317]: https://github.com/rust-random/getrandom/pull/317
[#325]: https://github.com/rust-random/getrandom/pull/325
[#326]: https://github.com/rust-random/getrandom/pull/326
[#331]: https://github.com/rust-random/getrandom/pull/331
[#332]: https://github.com/rust-random/getrandom/pull/332
[#333]: https://github.com/rust-random/getrandom/pull/333
[#334]: https://github.com/rust-random/getrandom/pull/334
[#335]: https://github.com/rust-random/getrandom/pull/335
[#337]: https://github.com/rust-random/getrandom/pull/337
[#344]: https://github.com/rust-random/getrandom/pull/344
[#347]: https://github.com/rust-random/getrandom/pull/347

## [0.2.8] - 2022-10-20
### Changed
- The [Web Cryptography API] will now be preferred on `wasm32-unknown-unknown`
  when using the `"js"` feature, even on Node.js [#284] [#295]

### Added
- Added benchmarks to track buffer initialization cost [#272]

### Fixed
- Use `$crate` in `register_custom_getrandom!` [#270]

### Documentation
- Add information about enabling `"js"` feature [#280]
- Fix link to `wasm-bindgen` [#278]
- Document the varied implementations for underlying randomness sources [#276]

[0.2.8]: https://github.com/rust-random/getrandom/compare/v0.2.7...v0.2.8
[#284]: https://github.com/rust-random/getrandom/pull/284
[#295]: https://github.com/rust-random/getrandom/pull/295
[#272]: https://github.com/rust-random/getrandom/pull/272
[#270]: https://github.com/rust-random/getrandom/pull/270
[#280]: https://github.com/rust-random/getrandom/pull/280
[#278]: https://github.com/rust-random/getrandom/pull/278
[#276]: https://github.com/rust-random/getrandom/pull/276
[Web Cryptography API]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

## [0.2.7] - 2022-06-14
### Changed
- Update `wasi` dependency to `0.11` [#253]

### Fixed
- Use `AtomicPtr` instead of `AtomicUsize` for Strict Provenance compatibility. [#263]

### Documentation
- Add comments explaining use of fallback mechanisms [#257] [#260]

[0.2.7]: https://github.com/rust-random/getrandom/compare/v0.2.6...v0.2.7
[#263]: https://github.com/rust-random/getrandom/pull/263
[#260]: https://github.com/rust-random/getrandom/pull/260
[#253]: https://github.com/rust-random/getrandom/pull/253
[#257]: https://github.com/rust-random/getrandom/pull/257

## [0.2.6] - 2022-03-28
### Added
- Nintendo 3DS (`armv6k-nintendo-3ds`) support [#248]

### Changed
- Retry `open` when interrupted [#252]

[0.2.6]: https://github.com/rust-random/getrandom/compare/v0.2.5...v0.2.6
[#248]: https://github.com/rust-random/getrandom/pull/248
[#252]: https://github.com/rust-random/getrandom/pull/252

## [0.2.5] - 2022-02-22
### Added
- ESP-IDF targets (`*‑espidf`) support [#245]

### Fixed
- Webpack warning caused by dynamic require [#234]
- Error checking on iOS for `SecRandomCopyBytes` [#244]

[0.2.5]: https://github.com/rust-random/getrandom/compare/v0.2.4...v0.2.5
[#234]: https://github.com/rust-random/getrandom/pull/234
[#244]: https://github.com/rust-random/getrandom/pull/244
[#245]: https://github.com/rust-random/getrandom/pull/245

## [0.2.4] - 2021-12-13
### Changed
- Use explicit imports in the `js` backend [#220]
- Use `/dev/urandom` on Redox instead of `rand:` [#222]
- Use `NonZeroU32::new_unchecked` to convert wasi error [#233]

### Added
- SOLID targets (`*-kmc-solid_*`) support [#235]
- Limited Hermit (`x86_64-unknown-hermit`) support [#236]

[0.2.4]: https://github.com/rust-random/getrandom/compare/v0.2.3...v0.2.4
[#220]: https://github.com/rust-random/getrandom/pull/220
[#222]: https://github.com/rust-random/getrandom/pull/222
[#233]: https://github.com/rust-random/getrandom/pull/233
[#235]: https://github.com/rust-random/getrandom/pull/235
[#236]: https://github.com/rust-random/getrandom/pull/236

## [0.2.3] - 2021-04-10
### Changed
- Replace build.rs with link attributes. [#205]
- Add support for getrandom syscall on DragonFly BSD. [#210]
- Improve Node.js detection. [#215]

[0.2.3]: https://github.com/rust-random/getrandom/compare/v0.2.2...v0.2.3
[#205]: https://github.com/rust-random/getrandom/pull/205
[#210]: https://github.com/rust-random/getrandom/pull/210
[#215]: https://github.com/rust-random/getrandom/pull/215

## [0.2.2] - 2021-01-19
### Changed
- Forward `rustc-dep-of-std` to dependencies. [#198]
- Highlight feature-dependent functionality in documentation using the `doc_cfg` feature. [#200]

[0.2.2]: https://github.com/rust-random/getrandom/compare/v0.2.1...v0.2.2
[#198]: https://github.com/rust-random/getrandom/pull/198
[#200]: https://github.com/rust-random/getrandom/pull/200

## [0.2.1] - 2021-01-03
### Changed
- Update `cfg-if` to v1.0. [#166]
- Update `wasi` to v0.10. [#167]

### Fixed
- Multithreaded WASM support. [#165]

### Removed
- Windows XP support. [#177]
- Direct `stdweb` support. [#178]
- CloudABI support. [#184]

[0.2.1]: https://github.com/rust-random/getrandom/compare/v0.2.0...v0.2.1
[#165]: https://github.com/rust-random/getrandom/pull/165
[#166]: https://github.com/rust-random/getrandom/pull/166
[#167]: https://github.com/rust-random/getrandom/pull/167
[#177]: https://github.com/rust-random/getrandom/pull/177
[#178]: https://github.com/rust-random/getrandom/pull/178
[#184]: https://github.com/rust-random/getrandom/pull/184

## [0.2.0] - 2020-09-10
### Features for using getrandom on unsupported targets

The following (off by default) Cargo features have been added:
- `"rdrand"` - use the RDRAND instruction on `no_std` `x86`/`x86_64` targets [#133]
- `"js"` - use JavaScript calls on `wasm32-unknown-unknown` [#149]
  - Replaces the `stdweb` and `wasm-bindgen` features (which are removed)
- `"custom"` - allows a user to specify a custom implementation [#109]

### Breaking Changes
- Unsupported targets no longer compile [#107]
- Change/Add `Error` constants [#120]
- Only impl `std` traits when the `"std"` Cargo feature is specified [#106]
- Remove official support for Hermit, L4Re, and UEFI [#133]
- Remove optional `"log"` dependency [#131]
- Update minimum supported Linux kernel to 2.6.32 [#153]
- Update MSRV to 1.34 [#159]

[0.2.0]: https://github.com/rust-random/getrandom/compare/v0.1.16...v0.2.0
[#106]: https://github.com/rust-random/getrandom/pull/106
[#107]: https://github.com/rust-random/getrandom/pull/107
[#109]: https://github.com/rust-random/getrandom/pull/109
[#120]: https://github.com/rust-random/getrandom/pull/120
[#131]: https://github.com/rust-random/getrandom/pull/131
[#133]: https://github.com/rust-random/getrandom/pull/133
[#149]: https://github.com/rust-random/getrandom/pull/149
[#153]: https://github.com/rust-random/getrandom/pull/153
[#159]: https://github.com/rust-random/getrandom/pull/159

## [0.1.16] - 2020-12-31
### Changed
- Update `cfg-if` to v1.0. [#173]
- Implement `std::error::Error` for the `Error` type on additional targets. [#169]

### Fixed
- Multithreaded WASM support. [#171]

[0.1.16]: https://github.com/rust-random/getrandom/compare/v0.1.15...v0.1.16
[#173]: https://github.com/rust-random/getrandom/pull/173
[#171]: https://github.com/rust-random/getrandom/pull/171
[#169]: https://github.com/rust-random/getrandom/pull/169

## [0.1.15] - 2020-09-10
### Changed
- Added support for Internet Explorer 11 [#139]
- Fix Webpack require warning with `wasm-bindgen` [#137]

[0.1.15]: https://github.com/rust-random/getrandom/compare/v0.1.14...v0.1.15
[#137]: https://github.com/rust-random/getrandom/pull/137
[#139]: https://github.com/rust-random/getrandom/pull/139

## [0.1.14] - 2020-01-07
### Changed
- Remove use of spin-locks in the `use_file` module. [#125]
- Update `wasi` to v0.9. [#126]
- Do not read errno value on DragonFlyBSD to fix compilation failure. [#129]

[0.1.14]: https://github.com/rust-random/getrandom/compare/v0.1.13...v0.1.14
[#125]: https://github.com/rust-random/getrandom/pull/125
[#126]: https://github.com/rust-random/getrandom/pull/126
[#129]: https://github.com/rust-random/getrandom/pull/129

## [0.1.13] - 2019-08-25
### Added
- VxWorks targets support. [#86]

### Changed
- If zero-length slice is passed to the `getrandom` function, always return
`Ok(())` immediately without doing any calls to the underlying operating
system. [#104]
- Use the `kern.arandom` sysctl on NetBSD. [#115]

### Fixed
- Bump `cfg-if` minimum version from 0.1.0 to 0.1.2. [#112]
- Typos and bad doc links. [#117]

[0.1.13]: https://github.com/rust-random/getrandom/compare/v0.1.12...v0.1.13
[#86]: https://github.com/rust-random/getrandom/pull/86
[#104]: https://github.com/rust-random/getrandom/pull/104
[#112]: https://github.com/rust-random/getrandom/pull/112
[#115]: https://github.com/rust-random/getrandom/pull/115
[#117]: https://github.com/rust-random/getrandom/pull/117

## [0.1.12] - 2019-08-18
### Changed
- Update wasi dependency from v0.5 to v0.7. [#100]

[0.1.12]: https://github.com/rust-random/getrandom/compare/v0.1.11...v0.1.12
[#100]: https://github.com/rust-random/getrandom/pull/100

## [0.1.11] - 2019-08-25
### Fixed
- Implement `std`-dependent traits for selected targets even if `std`
feature is disabled. (backward compatibility with v0.1.8) [#96]

[0.1.11]: https://github.com/rust-random/getrandom/compare/v0.1.10...v0.1.11
[#96]: https://github.com/rust-random/getrandom/pull/96

## [0.1.10] - 2019-08-18 [YANKED]
### Changed
- Use the dummy implementation on `wasm32-unknown-unknown` even with the
disabled `dummy` feature. [#90]

### Fixed
- Fix CSP error for `wasm-bindgen`. [#92]

[0.1.10]: https://github.com/rust-random/getrandom/compare/v0.1.9...v0.1.10
[#90]: https://github.com/rust-random/getrandom/pull/90
[#92]: https://github.com/rust-random/getrandom/pull/92

## [0.1.9] - 2019-08-14 [YANKED]
### Changed
- Remove `std` dependency for opening and reading files. [#58]
- Use `wasi` instead of `libc` on WASI target. [#64]
- By default emit a compile-time error when built for an unsupported target.
This behaviour can be disabled by using the `dummy` feature. [#71]

### Added
- Add support for UWP targets. [#69]
- Add unstable `rustc-dep-of-std` feature. [#78]

[0.1.9]: https://github.com/rust-random/getrandom/compare/v0.1.8...v0.1.9
[#58]: https://github.com/rust-random/getrandom/pull/58
[#64]: https://github.com/rust-random/getrandom/pull/64
[#69]: https://github.com/rust-random/getrandom/pull/69
[#71]: https://github.com/rust-random/getrandom/pull/71
[#78]: https://github.com/rust-random/getrandom/pull/78

## [0.1.8] - 2019-07-29
### Changed
- Explicitly specify types to arguments of 'libc::syscall'. [#74]

[0.1.8]: https://github.com/rust-random/getrandom/compare/v0.1.7...v0.1.8
[#74]: https://github.com/rust-random/getrandom/pull/74

## [0.1.7] - 2019-07-29
### Added
- Support for hermit and l4re. [#61]
- `Error::raw_os_error` method, `Error::INTERNAL_START` and
`Error::CUSTOM_START` constants. Use `libc` for retrieving OS error descriptions. [#54]

### Changed
- Remove `lazy_static` dependency and use custom structures for lock-free
initialization. [#51] [#52]
- Try `getrandom()` first on FreeBSD. [#57]

### Removed
-  Bitrig support. [#56]

### Deprecated
- `Error::UNKNOWN`, `Error::UNAVAILABLE`. [#54]

[0.1.7]: https://github.com/rust-random/getrandom/compare/v0.1.6...v0.1.7
[#51]: https://github.com/rust-random/getrandom/pull/51
[#52]: https://github.com/rust-random/getrandom/pull/52
[#54]: https://github.com/rust-random/getrandom/pull/54
[#56]: https://github.com/rust-random/getrandom/pull/56
[#57]: https://github.com/rust-random/getrandom/pull/57
[#61]: https://github.com/rust-random/getrandom/pull/61

## [0.1.6] - 2019-06-30
### Changed
- Minor change of RDRAND AMD bug handling. [#48]

[0.1.6]: https://github.com/rust-random/getrandom/compare/v0.1.5...v0.1.6
[#48]: https://github.com/rust-random/getrandom/pull/48

## [0.1.5] - 2019-06-29
### Fixed
- Use shared `File` instead of shared file descriptor. [#44]
- Workaround for RDRAND hardware bug present on some AMD CPUs. [#43]

### Changed
- Try `getentropy` and then fallback to `/dev/random` on macOS. [#38]

[0.1.5]: https://github.com/rust-random/getrandom/compare/v0.1.4...v0.1.5
[#38]: https://github.com/rust-random/getrandom/issues/38
[#43]: https://github.com/rust-random/getrandom/pull/43
[#44]: https://github.com/rust-random/getrandom/issues/44

## [0.1.4] - 2019-06-28
### Added
- Add support for `x86_64-unknown-uefi` target by using RDRAND with CPUID
feature detection. [#30]

### Fixed
- Fix long buffer issues on Windows and Linux. [#31] [#32]
- Check `EPERM` in addition to `ENOSYS` on Linux. [#37]

### Changed
- Improve efficiency by sharing file descriptor across threads. [#13]
- Remove `cloudabi`, `winapi`, and `fuchsia-cprng` dependencies. [#40]
- Improve RDRAND implementation. [#24]
- Don't block during syscall detection on Linux. [#26]
- Increase consistency with libc implementation on FreeBSD. [#36]
- Apply `rustfmt`. [#39]

[0.1.4]: https://github.com/rust-random/getrandom/compare/v0.1.3...v0.1.4
[#30]: https://github.com/rust-random/getrandom/pull/30
[#13]: https://github.com/rust-random/getrandom/issues/13
[#40]: https://github.com/rust-random/getrandom/pull/40
[#26]: https://github.com/rust-random/getrandom/pull/26
[#24]: https://github.com/rust-random/getrandom/pull/24
[#39]: https://github.com/rust-random/getrandom/pull/39
[#36]: https://github.com/rust-random/getrandom/pull/36
[#31]: https://github.com/rust-random/getrandom/issues/31
[#32]: https://github.com/rust-random/getrandom/issues/32
[#37]: https://github.com/rust-random/getrandom/issues/37

## [0.1.3] - 2019-05-15
- Update for `wasm32-unknown-wasi` being renamed to `wasm32-wasi`, and for
  WASI being categorized as an OS.

[0.1.3]: https://github.com/rust-random/getrandom/compare/v0.1.2...v0.1.3

## [0.1.2] - 2019-04-06
- Add support for `wasm32-unknown-wasi` target.

[0.1.2]: https://github.com/rust-random/getrandom/compare/v0.1.1...v0.1.2

## [0.1.1] - 2019-04-05
- Enable std functionality for CloudABI by default.

[0.1.1]: https://github.com/rust-random/getrandom/compare/v0.1.0...v0.1.1

## [0.1.0] - 2019-03-23
Publish initial implementation.

[0.1.0]: https://github.com/rust-random/getrandom/compare/v0.0.0...v0.1.0

## [0.0.0] - 2019-01-19
Publish an empty template library.

[0.0.0]: https://github.com/rust-random/getrandom/releases/tag/v0.0.0


================================================
FILE: Cargo.toml
================================================
[package]
name = "getrandom"
version = "0.4.2"
edition = "2024"
rust-version = "1.85" # Sync tests.yml and README.md.
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
description = "A small cross-platform library for retrieving random data from system source"
documentation = "https://docs.rs/getrandom"
repository = "https://github.com/rust-random/getrandom"
categories = ["os", "no-std"]
exclude = [".*"]

[package.metadata.docs.rs]
features = ["std", "sys_rng"]
rustdoc-args = ["--cfg", "getrandom_backend=\"extern_impl\""]

[features]
# Implement From<getrandom::Error> for std::io::Error and
# use std to retrieve OS error descriptions
std = []

# Optional backend: wasm_js
#
# This flag enables the wasm_js backend and uses it by default on wasm32 where
# the target_os is unknown. The getrandom_backend cfg may override this.
#
# WARNING: We strongly recommend against enabling this feature in libraries (except for tests)
# since it is known to break non-Web WASM builds and further since the usage of `wasm-bindgen`
# causes significant bloat to `Cargo.lock` (on all targets).
#
# The only exception to this rule: if your crate already unconditionally depends on `wasm-bindgen`
# or `js-sys` on "unknown" WASM targets then it's acceptable to enable this feature unconditionally.
wasm_js = ["dep:wasm-bindgen", "dep:js-sys"]

# Provide SysRng over rand_core
sys_rng = ["dep:rand_core"]

[dependencies]
cfg-if = "1"
rand_core = { version = "0.10.0", optional = true }

# getrandom / linux_android_with_fallback
[target.'cfg(all(any(target_os = "linux", target_os = "android"), not(any(all(target_os = "linux", target_env = ""), getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))'.dependencies]
libc = { version = "0.2.154", default-features = false }

# apple-other
[target.'cfg(any(target_os = "ios", target_os = "visionos", target_os = "watchos", target_os = "tvos"))'.dependencies]
libc = { version = "0.2.154", default-features = false }

# efi_rng
[target.'cfg(all(target_os = "uefi", getrandom_backend = "efi_rng"))'.dependencies]
r-efi = { version = "6", default-features = false }

# getentropy
[target.'cfg(any(target_os = "macos", target_os = "openbsd", target_os = "vita", target_os = "emscripten"))'.dependencies]
libc = { version = "0.2.154", default-features = false }

# getrandom
[target.'cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", target_os = "illumos", target_os = "cygwin", all(target_os = "horizon", target_arch = "arm")))'.dependencies]
libc = { version = "0.2.154", default-features = false }

# netbsd
[target.'cfg(target_os = "netbsd")'.dependencies]
libc = { version = "0.2.154", default-features = false }

# solaris
[target.'cfg(target_os = "solaris")'.dependencies]
libc = { version = "0.2.154", default-features = false }

# use_file
[target.'cfg(any(target_os = "haiku", target_os = "redox", target_os = "nto", target_os = "aix"))'.dependencies]
libc = { version = "0.2.154", default-features = false }

# vxworks
[target.'cfg(target_os = "vxworks")'.dependencies]
libc = { version = "0.2.154", default-features = false }

# wasi_p2_3
[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))'.dependencies]
wasip2 = { version = "1", default-features = false }

# wasi_p2_3
[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p3"))'.dependencies]
# TODO: remove 0.3 after MSRV bumped to 1.87+.
wasip3 = ">=0.3, <=0.4"

# wasm_js
[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dependencies]
wasm-bindgen = { version = "0.2.98", default-features = false, optional = true }
[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), target_feature = "atomics"))'.dependencies]
js-sys = { version = "0.3.77", default-features = false, optional = true }
[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies]
wasm-bindgen-test = "0.3"

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
  'cfg(getrandom_backend, values("custom", "efi_rng", "rdrand", "rndr", "linux_getrandom", "linux_raw", "windows_legacy", "unsupported", "extern_impl"))',
  'cfg(getrandom_msan)',
  'cfg(getrandom_test_linux_fallback)',
  'cfg(getrandom_test_linux_without_fallback)',
  'cfg(getrandom_test_netbsd_fallback)',
  'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this.
  'cfg(target_os, values("motor"))',
]

[lints.rust]
unused_lifetimes = "warn"
missing_docs = "warn"

[lints.clippy]
cast_lossless = "warn"
cast_possible_truncation = "warn"
cast_possible_wrap = "warn"
cast_precision_loss = "warn"
cast_ptr_alignment = "warn"
cast_sign_loss = "warn"
char_lit_as_u8 = "warn"
checked_conversions = "warn"
fn_to_numeric_cast = "warn"
fn_to_numeric_cast_with_truncation = "warn"
ptr_as_ptr = "warn"
unnecessary_cast = "warn"
useless_conversion = "warn"

# workaround for https://github.com/cross-rs/cross/issues/1345
[package.metadata.cross.target.x86_64-unknown-netbsd]
pre-build = [
  "mkdir -p /tmp/netbsd",
  "curl -fO https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/amd64/binary/sets/base.tar.xz",
  "tar -C /tmp/netbsd -xJf base.tar.xz",
  "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib",
  "rm base.tar.xz",
  "rm -rf /tmp/netbsd",
]


================================================
FILE: LICENSE-APACHE
================================================
                              Apache License
                        Version 2.0, January 2004
                     https://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf
   of any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don't include
   the brackets!)  The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: LICENSE-MIT
================================================
Copyright (c) 2018-2026 The rust-random Project Developers
Copyright (c) 2014 The Rust Project Developers

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# getrandom: system's random number generator

[![Build Status]][GitHub Actions]
[![Crate]][crates.io]
[![Documentation]][docs.rs]
[![Dependency Status]][deps.rs]
[![Downloads]][crates.io]
[![License]][LICENSE-MIT]

`getrandom` is a Rust library for retrieving random data from (operating) system sources.

It is assumed that the system always provides high-quality, cryptographically secure random
data, ideally backed by hardware entropy sources. This crate derives its name from
the Linux `getrandom` syscall but is cross-platform, roughly supporting the same set
of platforms as Rust's `std` library.

This is a low-level API. Most users should prefer using a higher-level random-number
library like [`rand`].

[`rand`]: https://crates.io/crates/rand

## Examples

```rust
fn get_random_u128() -> Result<u128, getrandom::Error> {
    let mut buf = [0u8; 16];
    getrandom::fill(&mut buf)?;
    Ok(u128::from_ne_bytes(buf))
}
```

## Supported targets

| Target             | Target Triple      | Implementation
| ------------------ | ------------------ | --------------
| Linux, Android     | `*‑linux‑*`        | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
| Windows 10+        | `*‑windows‑*`      | [`ProcessPrng`]
| Windows 7, 8       | `*-win7‑windows‑*` | [`RtlGenRandom`]
| macOS              | `*‑apple‑darwin`   | [`getentropy`][3]
| iOS, tvOS, watchOS | `*‑apple‑{ios,tvos,watchos}` | [`CCRandomGenerateBytes`]
| FreeBSD            | `*‑freebsd`        | [`getrandom`][5]
| OpenBSD            | `*‑openbsd`        | [`getentropy`][7]
| NetBSD             | `*‑netbsd`         | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
| Dragonfly BSD      | `*‑dragonfly`      | [`getrandom`][9]
| Solaris            | `*‑solaris`        | [`getrandom`][11] with `GRND_RANDOM`
| illumos            | `*‑illumos`        | [`getrandom`][12]
| Fuchsia OS         | `*‑fuchsia`        | [`cprng_draw`]
| Redox              | `*‑redox`          | `/dev/urandom`
| Haiku              | `*‑haiku`          | `/dev/urandom` (identical to `/dev/random`)
| Hermit             | `*-hermit`         | [`sys_read_entropy`]
| Hurd               | `*-hurd-*`         | [`getrandom`][17]
| SGX                | `x86_64‑*‑sgx`     | [`RDRAND`]
| VxWorks            | `*‑wrs‑vxworks‑*`  | `randABytes` after checking entropy pool initialization with `randSecure`
| Emscripten         | `*‑emscripten`     | [`getentropy`][13]
| WASI 0.1           | `wasm32‑wasip1`    | [`random_get`]
| WASI 0.2           | `wasm32‑wasip2`    | [`get-random-u64`]
| SOLID              | `*-kmc-solid_*`    | `SOLID_RNG_SampleRandomBytes`
| Nintendo 3DS       | `*-nintendo-3ds`   | [`getrandom`][18]
| ESP-IDF            | `*‑espidf`         | [`esp_fill_random`] WARNING: see "Early Boot" section below
| PS Vita            | `*-vita-*`         | [`getentropy`][19]
| QNX Neutrino       | `*‑nto-qnx*`       | [`/dev/urandom`][14] (identical to `/dev/random`)
| AIX                | `*-ibm-aix`        | [`/dev/urandom`][15]
| Cygwin             | `*-cygwin`         | [`getrandom`][20] (based on [`RtlGenRandom`])
| Motor OS           | `x86_64-unknown-motor` | [`RDRAND`]

Pull Requests that add support for new targets to `getrandom` are always welcome.

### WebAssembly support

This crate fully supports the [WASI] and [Emscripten] targets. However,
the `wasm32-unknown-unknown` target (i.e. the target used by `wasm-pack`)
is not automatically supported since, from the target name alone, we cannot deduce
which JavaScript interface should be used (or if JavaScript is available at all).

We do not include support for this target in the default configuration because our JS backend
(supporting web browsers, web workers and Node.js v19 or later) requires [`wasm-bindgen`],
**bloating `Cargo.lock`** and **potentially breaking builds** on non-web WASM platforms.

To enable `getrandom`'s functionality on `wasm32-unknown-unknown` using
[`Crypto.getRandomValues`] via [`wasm-bindgen`], enable the `wasm_js` crate feature.

WARNING: We strongly recommend against enabling this feature in libraries (except for tests)
since it is known to break non-Web WASM builds and further since the usage of `wasm-bindgen`
causes significant bloat to `Cargo.lock` (on all targets).

The only exception to this rule: if your crate already unconditionally depends on `wasm-bindgen`
or `js-sys` on "unknown" WASM targets then it's acceptable to enable this feature unconditionally.

### Opt-in backends

`getrandom` also provides optional (opt-in) backends, which allow users to customize the source
of randomness based on their specific needs:

| Backend name        | Target               | Target Triple            | Implementation
| ------------------- | -------------------- | ------------------------ | --------------
| `linux_getrandom`   | Linux, Android       | `*‑linux‑*`              | [`getrandom`][1] system call (without `/dev/urandom` fallback). Bumps minimum supported Linux kernel version to 3.17 and Android API level to 23 (Marshmallow).
| `linux_raw`         | Linux, Android       | `*‑linux‑*`              | Same as `linux_getrandom`, but uses raw `asm!`-based syscalls instead of `libc`.
| `rdrand`            | x86, x86-64          | `x86_64-*`, `i686-*`     | [`RDRAND`] instruction
| `rndr`              | AArch64              | `aarch64-*`              | [`RNDR`] register
| `efi_rng`           | UEFI                 | `*-unknown‑uefi`         | [`EFI_RNG_PROTOCOL`] with `EFI_RNG_ALGORITHM_RAW` (requires `std` and Nightly compiler)
| `windows_legacy`    | Windows              | `*-windows-*`            | [`RtlGenRandom`]
| `custom`            | All targets          | `*`                      | User-provided custom implementation (see [custom backend])
| `unsupported`       | All targets          | `*`                      | Always returns `Err(Error::UNSUPPORTED)` (see [unsupported backend])
| `extern_impl`       | All targets          | `*`                      | Externally-provided custom implementation (see [externally implemented interface])

Opt-in backends can be enabled using the `getrandom_backend` configuration flag.
The flag can be set either by specifying the `rustflags` field in [`.cargo/config.toml`]:
```toml
# It's recommended to set the flag on a per-target basis:
[target.'cfg(target_os = "linux")']
rustflags = ['--cfg', 'getrandom_backend="linux_getrandom"']
```

Or by using the `RUSTFLAGS` environment variable:

```sh
RUSTFLAGS='--cfg getrandom_backend="linux_getrandom"' cargo build
```

Enabling an opt-in backend will replace the backend used by default. Doing this for
an incorrect target (e.g. using `linux_getrandom` while compiling for a Windows target)
will result in a compilation error. Be extremely careful while using opt-in backends,
as incorrect configuration may result in vulnerable applications or applications
that always panic.

Note that using an opt-in backend in a library (e.g. for tests or benchmarks)
WILL NOT have any effect on its downstream users.

[`.cargo/config.toml`]: https://doc.rust-lang.org/cargo/reference/config.html

### Raw Linux syscall support

Currently the `linux_raw` backend supports only targets with stabilized `asm!` macro,
i.e. `arm`, `aarch64`, `loongarch64`, `riscv32`, `riscv64`, `s390x`, `x86`, and `x86_64`.

Note that the raw syscall backend may be slower than backends based on `libc::getrandom`,
e.g. it does not implement vDSO optimizations and on `x86` it uses the infamously slow
`int 0x80` instruction to perform syscall.

### Custom backend

If this crate does not support your target out of the box or you have to use
a non-default entropy source, then you can provide a custom implementation.
You need to enable the custom backend as described in the
[opt-in backends][opt-in] section.

Next, you need to define an `extern` function with the following signature:

```rust
use getrandom::Error;

#[unsafe(no_mangle)]
unsafe extern "Rust" fn __getrandom_v03_custom(
    dest: *mut u8,
    len: usize,
) -> Result<(), Error> {
    todo!()
}
```

This function should, ideally, be defined in the root crate of your project,
e.g. in your `main.rs`. This function MUST be defined only once for your
project, i.e. upstream library crates SHOULD NOT define it outside of
tests and benchmarks. Improper configuration of this backend may result
in linking errors.

The function accepts a pointer to a buffer that should be filled with random
data and its length in bytes. Note that the buffer MAY be uninitialized.
On success, the function should return `Ok(())` and fully fill the input buffer;
otherwise, it should return an error value.

While wrapping functions which work with byte slices you should fully initialize
the buffer before passing it to the function:
```rust
use getrandom::Error;

fn my_entropy_source(buf: &mut [u8]) -> Result<(), getrandom::Error> {
    // ...
    Ok(())
}

#[unsafe(no_mangle)]
unsafe extern "Rust" fn __getrandom_v03_custom(
    dest: *mut u8,
    len: usize,
) -> Result<(), Error> {
    let buf = unsafe {
        // fill the buffer with zeros
        core::ptr::write_bytes(dest, 0, len);
        // create mutable byte slice
        core::slice::from_raw_parts_mut(dest, len)
    };
    my_entropy_source(buf)
}
```

### Externally Implemented Interface

Using the nightly-only feature [`extern_item_impls`] it is possible to provide
a custom backend for `getrandom`, even to override an existing first-party implementation.
First, enable the `extern_impl` opt-in backend to allow usage of this nightly feature.
Then, you may provide implementations for `fill_uninit`, `u32`, and/or `u64`
with an attribute macro from the `implementation` module.

[`extern_item_impls`]: https://github.com/rust-lang/rust/issues/125418

```rust
use core::mem::MaybeUninit;

#[cfg(getrandom_backend = "extern_impl")]
#[getrandom::implementation::fill_uninit]
fn my_fill_uninit_implementation(
    dest: &mut [MaybeUninit<u8>]
) -> Result<(), getrandom::Error> {
    // ...
    Ok(())
}
```

For further details on what a suitable implementation for `fill_uninit` may look
like, see [custom backend].

`getrandom` will provide a default implementation for `u32` and `u64`, but does
not currently provide a default for `fill_uninit`, even if one is normally
available for the current target. If no implementation is available,
a compilation error will be raised with instructions for how to provide
an implementation.

### Unsupported backend

In some rare scenarios, you might be compiling this crate for an unsupported
target (e.g. `wasm32-unknown-unknown`), but this crate's functionality
is not actually used by your code. If you are confident that `getrandom` is
not used in your project, but it gets pulled nevertheless by one of your
dependencies, then you can enable the `unsupported` backend, which always
returns `Err(Error::UNSUPPORTED)`.

### Platform Support

This crate generally supports the same operating system and platform versions
that the Rust standard library does. Additional targets may be supported using
the opt-in custom backend.

This means that as Rust drops support for old versions of operating systems
(such as old Linux kernel versions, Android API levels, etc.) in stable releases,
`getrandom` may create new patch releases that remove support for
outdated platform versions.

### `/dev/urandom` fallback on Linux and Android

On Linux targets, the `/dev/urandom` fallback is present only if either `target_env`
is `musl`, or `target_arch` is one of the following: `aarch64`, `arm`, `powerpc`,
`powerpc64`, `s390x`, `x86`, `x86_64`. Other supported targets [require][platform-support]
kernel versions that support the `getrandom` system call, so the fallback is not needed.

On Android targets the fallback is present only for the following `target_arch`es:
`aarch64`, `arm`, `x86`, `x86_64`. Other `target_arch`es (e.g. RISC-V) require
sufficiently high API levels.

The fallback can be disabled by enabling the `linux_getrandom` opt-in backend.
Note that doing so will bump minimum supported Linux kernel version to 3.17
and Android API level to 23 (Marshmallow).

### Early boot

Sometimes, early in the boot process, the OS has not collected enough
entropy to securely seed its RNG. This is especially common on virtual
machines, where standard "random" events are hard to come by.

Some operating system interfaces always block until the RNG is securely
seeded. This can take anywhere from a few seconds to more than a minute.
A few (Linux, NetBSD and Solaris) offer a choice between blocking and
getting an error; in these cases, we always choose to block.

On Linux (when the `getrandom` system call is not available), reading from
`/dev/urandom` never blocks, even when the OS hasn't collected enough
entropy yet. To avoid returning low-entropy bytes, we first poll
`/dev/random` and only switch to `/dev/urandom` once this has succeeded.

On OpenBSD, this kind of entropy accounting isn't available, and on
NetBSD, blocking on it is discouraged. On these platforms, nonblocking
interfaces are used, even when reliable entropy may not be available.
On the platforms where it is used, the reliability of entropy accounting
itself isn't free from controversy. This library provides randomness
sourced according to the platform's best practices, but each platform has
its own limits on the grade of randomness it can promise in environments
with few sources of entropy.

On ESP-IDF, if `esp_fill_random` is used before enabling WiFi, BT, or the
voltage noise entropy source (SAR ADC), the Hardware RNG will only be seeded
via RC_FAST_CLK. This can occur during early boot unless
`bootloader_random_enable()` is called. For more information see the
[ESP-IDF RNG Docs][esp-idf-rng] or the
[RNG section of the ESP32 Technical Reference Manual][esp-trng-docs].

## Error handling

We always prioritize failure over returning known insecure "random" bytes.
Generally, on supported platforms, failure is highly unlikely, though not
impossible. If an error does occur, it is likely that it will occur
on every call to `getrandom`. Therefore, after the first successful call,
one can be reasonably confident that no errors will occur.

## Panic handling

We strive to eliminate all potential panics from our backend implementations.
In other words, when compiled with optimizations enabled, the generated
binary code for `getrandom` functions should not contain any panic branches.
Even if the platform misbehaves and returns an unexpected result,
our code should correctly handle it and return an error, e.g.
[`Error::UNEXPECTED`].

## Sanitizer support

If your code uses [`fill_uninit`] and you enable
[MemorySanitizer](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#memorysanitizer)
(i.e. `-Zsanitizer=memory`), we will automatically handle unpoisoning
of the destination buffer filled by `fill_uninit`.

You can run sanitizer tests for your crate dependent on `getrandom` like this:
```sh
RUSTFLAGS="-Zsanitizer=memory" cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu
```

## Minimum Supported Rust Version

This crate requires Rust 1.85 or later.

The most reliable way to get an MSRV-respecting behavior is to set
`CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS=fallback` when doing
`cargo update -p getrandom`, like so:
```sh
CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS=fallback cargo update -p getrandom
```

## License

The `getrandom` library is distributed under either of

 * [Apache License, Version 2.0][LICENSE-APACHE]
 * [MIT license][LICENSE-MIT]

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

[//]: # (badges)

[GitHub Actions]: https://github.com/rust-random/getrandom/actions?query=branch:master
[Build Status]: https://github.com/rust-random/getrandom/actions/workflows/tests.yml/badge.svg?branch=master
[crates.io]: https://crates.io/crates/getrandom
[Crate]: https://img.shields.io/crates/v/getrandom
[docs.rs]: https://docs.rs/getrandom
[Documentation]: https://docs.rs/getrandom/badge.svg
[deps.rs]: https://deps.rs/repo/github/rust-random/getrandom
[Dependency Status]: https://deps.rs/repo/github/rust-random/getrandom/status.svg
[Downloads]: https://img.shields.io/crates/d/getrandom
[License]: https://img.shields.io/crates/l/getrandom

[//]: # (supported targets)

[1]: https://manned.org/getrandom.2
[2]: https://manned.org/urandom.4
[3]: https://www.unix.com/man-page/mojave/2/getentropy/
[4]: https://www.unix.com/man-page/mojave/4/urandom/
[5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
[7]: https://man.openbsd.org/getentropy.2
[8]: https://man.netbsd.org/sysctl.7
[9]: https://leaf.dragonflybsd.org/cgi/web-man?command=getrandom
[11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
[12]: https://illumos.org/man/2/getrandom
[13]: https://github.com/emscripten-core/emscripten/pull/12240
[14]: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/r/random.html
[15]: https://www.ibm.com/docs/en/aix/7.3?topic=files-random-urandom-devices
[16]: https://man.netbsd.org/getrandom.2
[17]: https://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getrandom
[18]: https://github.com/rust3ds/shim-3ds/commit/b01d2568836dea2a65d05d662f8e5f805c64389d
[19]: https://github.com/vitasdk/newlib/blob/2d869fe47aaf02b8e52d04e9a2b79d5b210fd016/newlib/libc/sys/vita/getentropy.c
[20]: https://github.com/cygwin/cygwin/blob/main/winsup/cygwin/libc/getentropy.cc

[`ProcessPrng`]: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
[`RtlGenRandom`]: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
[`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
[`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
[`RNDR`]: https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers/RNDR--Random-Number
[`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html
[`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
[`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html#functions
[esp-idf-rng]: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html
[esp-trng-docs]: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#rng
[`EFI_RNG_PROTOCOL`]: https://uefi.org/specs/UEFI/2.10/37_Secure_Technologies.html#efi-rng-protocol
[`random_get`]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno
[`get-random-u64`]: https://github.com/WebAssembly/WASI/blob/v0.2.1/wasip2/random/random.wit#L23-L28
[configuration flags]: #configuration-flags
[custom backend]: #custom-backend
[unsupported backend]: #unsupported-backend
[`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
[`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html
[`sys_read_entropy`]: https://github.com/hermit-os/kernel/blob/315f58ff5efc81d9bf0618af85a59963ff55f8b1/src/syscalls/entropy.rs#L47-L55
[platform-support]: https://doc.rust-lang.org/stable/rustc/platform-support.html
[WASI]: https://github.com/WebAssembly/WASI
[Emscripten]: https://emscripten.org
[opt-in]: #opt-in-backends
[externally implemented interface]: #externally-implemented-interface

[//]: # (licenses)

[LICENSE-APACHE]: https://github.com/rust-random/getrandom/blob/master/LICENSE-APACHE
[LICENSE-MIT]: https://github.com/rust-random/getrandom/blob/master/LICENSE-MIT

[`Error::UNEXPECTED`]: https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.UNEXPECTED
[`fill_uninit`]: https://docs.rs/getrandom/latest/getrandom/fn.fill_uninit.html


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

Security updates are applied only to the latest release.

## Reporting a Vulnerability

If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.

Please disclose it at [security advisory](https://github.com/rust-random/getrandom/security/advisories/new).

This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.


================================================
FILE: benches/buffer.rs
================================================
//! Basic benchmarks
#![feature(test)]
extern crate test;

use std::{
    mem::{MaybeUninit, size_of},
    slice,
};

// Call getrandom on a zero-initialized stack buffer
#[inline(always)]
fn bench_fill<const N: usize>() {
    let mut buf = [0u8; N];
    getrandom::fill(&mut buf).unwrap();
    test::black_box(&buf[..]);
}

// Call fill_uninit on an uninitialized stack buffer
#[inline(always)]
fn bench_fill_uninit<const N: usize>() {
    let mut uninit = [MaybeUninit::uninit(); N];
    let buf: &[u8] = getrandom::fill_uninit(&mut uninit).unwrap();
    test::black_box(buf);
}

#[bench]
fn bench_u32(b: &mut test::Bencher) {
    #[inline(never)]
    fn inner() -> u32 {
        getrandom::u32().unwrap()
    }
    b.bytes = 4;
    b.iter(inner);
}

#[bench]
fn bench_u32_via_fill(b: &mut test::Bencher) {
    #[inline(never)]
    fn inner() -> u32 {
        let mut res = MaybeUninit::<u32>::uninit();
        let dst: &mut [MaybeUninit<u8>] =
            unsafe { slice::from_raw_parts_mut(res.as_mut_ptr().cast(), size_of::<u32>()) };
        getrandom::fill_uninit(dst).unwrap();
        unsafe { res.assume_init() }
    }
    b.bytes = 4;
    b.iter(inner);
}

#[bench]
fn bench_u64(b: &mut test::Bencher) {
    #[inline(never)]
    fn inner() -> u64 {
        getrandom::u64().unwrap()
    }
    b.bytes = 8;
    b.iter(inner);
}

#[bench]
fn bench_u64_via_fill(b: &mut test::Bencher) {
    #[inline(never)]
    fn inner() -> u64 {
        let mut res = MaybeUninit::<u64>::uninit();
        let dst: &mut [MaybeUninit<u8>] =
            unsafe { slice::from_raw_parts_mut(res.as_mut_ptr().cast(), size_of::<u64>()) };
        getrandom::fill_uninit(dst).unwrap();
        unsafe { res.assume_init() }
    }
    b.bytes = 8;
    b.iter(inner);
}

// We benchmark using #[inline(never)] "inner" functions for two reasons:
//  - Avoiding inlining reduces a source of variance when running benchmarks.
//  - It is _much_ easier to get the assembly or IR for the inner loop.
//
// For example, using cargo-show-asm (https://github.com/pacak/cargo-show-asm),
// we can get the assembly for a particular benchmark's inner loop by running:
//   cargo asm --bench buffer --release buffer::p384::bench_getrandom::inner
macro_rules! bench {
    ( $name:ident, $size:expr ) => {
        mod $name {
            #[bench]
            fn bench_fill(b: &mut test::Bencher) {
                #[inline(never)]
                fn inner() {
                    super::bench_fill::<{ $size }>()
                }

                b.bytes = $size as u64;
                b.iter(inner);
            }
            #[bench]
            fn bench_fill_uninit(b: &mut test::Bencher) {
                #[inline(never)]
                fn inner() {
                    super::bench_fill_uninit::<{ $size }>()
                }

                b.bytes = $size as u64;
                b.iter(inner);
            }
        }
    };
}

// 16 bytes (128 bits) is the size of an 128-bit AES key/nonce.
bench!(aes128, 128 / 8);

// 32 bytes (256 bits) is the seed sized used for rand::thread_rng
// and the `random` value in a ClientHello/ServerHello for TLS.
// This is also the size of a 256-bit AES/HMAC/P-256/Curve25519 key
// and/or nonce.
bench!(p256, 256 / 8);

// A P-384/HMAC-384 key and/or nonce.
bench!(p384, 384 / 8);

// Initializing larger buffers is not the primary use case of this library, as
// this should normally be done by a userspace CSPRNG. However, we have a test
// here to see the effects of a lower (amortized) syscall overhead.
bench!(page, 4096);


================================================
FILE: build.rs
================================================
//! Build script for memory sanitization support

fn main() {
    // Automatically detect cfg(sanitize = "memory") even if cfg(sanitize) isn't
    // supported. Build scripts get cfg() info, even if the cfg is unstable.
    println!("cargo:rerun-if-changed=build.rs");
    let sanitizers = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default();
    if sanitizers.contains("memory") {
        println!("cargo:rustc-cfg=getrandom_msan");
    }
}


================================================
FILE: custom_impl_test/Cargo.toml
================================================
[package]
name = "custom_impl_test"
description = "Helper crate for testing custom implementations"
version = "0.1.0"
edition = "2024"
publish = false

[workspace]

[dependencies]
getrandom = { path = ".." }

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
  'cfg(getrandom_backend, values("custom", "extern_impl"))',
]


================================================
FILE: custom_impl_test/src/lib.rs
================================================
use core::mem::MaybeUninit;
use getrandom::Error;

/// Chosen by fair dice roll.
const SEED: u64 = 0x9095_810F_1B2B_E175;

struct Xoshiro128PlusPlus {
    s: [u32; 4],
}

impl Xoshiro128PlusPlus {
    fn new(mut seed: u64) -> Self {
        const PHI: u64 = 0x9e3779b97f4a7c15;
        let mut s = [0u32; 4];
        for val in s.iter_mut() {
            seed = seed.wrapping_add(PHI);
            let mut z = seed;
            z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
            z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
            z = z ^ (z >> 31);
            *val = z as u32;
        }
        Self { s }
    }

    fn next_u32(&mut self) -> u32 {
        let res = self.s[0]
            .wrapping_add(self.s[3])
            .rotate_left(7)
            .wrapping_add(self.s[0]);

        let t = self.s[1] << 9;

        self.s[2] ^= self.s[0];
        self.s[3] ^= self.s[1];
        self.s[1] ^= self.s[2];
        self.s[0] ^= self.s[3];

        self.s[2] ^= t;

        self.s[3] = self.s[3].rotate_left(11);

        res
    }
}

pub fn custom_impl(dst: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let mut rng = Xoshiro128PlusPlus::new(SEED);

    let mut chunks = dst.chunks_exact_mut(4);
    for chunk in &mut chunks {
        let val = rng.next_u32();
        let dst_ptr = chunk.as_mut_ptr().cast::<u32>();
        unsafe { core::ptr::write_unaligned(dst_ptr, val) };
    }
    let rem = chunks.into_remainder();
    if !rem.is_empty() {
        let val = rng.next_u32();
        let src_ptr = &val as *const u32 as *const MaybeUninit<u8>;
        assert!(rem.len() <= 4);
        unsafe { core::ptr::copy(src_ptr, rem.as_mut_ptr(), rem.len()) };
    }
    Ok(())
}

#[cfg(getrandom_backend = "custom")]
#[unsafe(no_mangle)]
unsafe extern "Rust" fn __getrandom_v03_custom(dst_ptr: *mut u8, len: usize) -> Result<(), Error> {
    let dst = unsafe { core::slice::from_raw_parts_mut(dst_ptr.cast(), len) };
    custom_impl(dst)
}

#[cfg(getrandom_backend = "extern_impl")]
#[getrandom::implementation::fill_uninit]
fn my_fill_uninit_implementation(dst: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    custom_impl(dst)
}

#[test]
fn test_custom_fill() {
    let mut buf1 = [0u8; 256];
    getrandom::fill(&mut buf1).unwrap();

    let mut buf2 = [0u8; 256];
    custom_impl(unsafe { core::slice::from_raw_parts_mut(buf2.as_mut_ptr().cast(), buf2.len()) })
        .unwrap();

    assert_eq!(buf1, buf2);
}

#[test]
fn test_custom_u32() {
    let res = getrandom::u32().unwrap();
    assert_eq!(res, 0xEAD5_840A);
}

#[test]
fn test_custom_u64() {
    let res = getrandom::u64().unwrap();
    assert_eq!(res, 0xA856_FCC4_EAD5_840A);
}


================================================
FILE: nopanic_check/Cargo.toml
================================================
[package]
name = "nopanic_check"
description = "Helper crate for checking that getrandom implementation does not contain potential panics"
version = "0.1.0"
edition = "2024"
publish = false

[workspace]

[lib]
name = "getrandom_wrapper"
crate-type = ["cdylib"]

[dependencies]
getrandom = { path = ".." }

[profile.release]
panic = "abort"
strip = true
lto = "fat"

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
  'cfg(getrandom_backend, values("custom"))',
]


================================================
FILE: nopanic_check/src/lib.rs
================================================
// WASI preview 2 requires enabled std
#![cfg_attr(not(all(target_arch = "wasm32", target_env = "p2")), no_std)]

#[cfg(not(any(test, all(target_arch = "wasm32", target_env = "p2"))))]
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    unsafe extern "C" {
        fn panic_nonexistent() -> !;
    }
    unsafe { panic_nonexistent() }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn getrandom_wrapper(buf_ptr: *mut u8, buf_len: usize) -> u32 {
    let buf = unsafe { core::slice::from_raw_parts_mut(buf_ptr.cast(), buf_len) };
    let res = getrandom::fill_uninit(buf).map(|_| ());
    unsafe { core::mem::transmute(res) }
}

#[cfg(getrandom_backend = "custom")]
#[unsafe(no_mangle)]
unsafe extern "Rust" fn __getrandom_v03_custom(
    dest: *mut u8,
    len: usize,
) -> Result<(), getrandom::Error> {
    for i in 0..len {
        unsafe { core::ptr::write(dest.add(i), i as u8) };
    }
    Ok(())
}


================================================
FILE: src/backends/apple_other.rs
================================================
//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable.
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let dst_ptr = dest.as_mut_ptr().cast::<c_void>();
    let ret = unsafe { libc::CCRandomGenerateBytes(dst_ptr, dest.len()) };
    if ret == libc::kCCSuccess {
        Ok(())
    } else {
        Err(Error::IOS_RANDOM_GEN)
    }
}

impl Error {
    /// Call to `CCRandomGenerateBytes` failed.
    pub(crate) const IOS_RANDOM_GEN: Error = Self::new_internal(10);
}


================================================
FILE: src/backends/custom.rs
================================================
//! An implementation which calls out to an externally defined function.
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    unsafe extern "Rust" {
        fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), Error>;
    }
    unsafe { __getrandom_v03_custom(dest.as_mut_ptr().cast(), dest.len()) }
}


================================================
FILE: src/backends/efi_rng.rs
================================================
//! Implementation for UEFI using EFI_RNG_PROTOCOL
use crate::Error;
use core::{
    mem::MaybeUninit,
    ptr::{self, NonNull},
};
use r_efi::{
    efi::{BootServices, Handle},
    protocols::rng,
};

extern crate std;

pub use crate::util::{inner_u32, inner_u64};

#[cfg(not(target_os = "uefi"))]
compile_error!("`efi_rng` backend can be enabled only for UEFI targets!");

#[cold]
#[inline(never)]
fn init() -> Result<NonNull<rng::Protocol>, Error> {
    const HANDLE_SIZE: usize = size_of::<Handle>();

    let boot_services = std::os::uefi::env::boot_services()
        .ok_or(Error::BOOT_SERVICES_UNAVAILABLE)?
        .cast::<BootServices>();

    let mut handles = [ptr::null_mut(); 16];
    // `locate_handle` operates with length in bytes
    let mut buf_size = handles.len() * HANDLE_SIZE;
    let mut guid = rng::PROTOCOL_GUID;
    let ret = unsafe {
        ((*boot_services.as_ptr()).locate_handle)(
            r_efi::efi::BY_PROTOCOL,
            &mut guid,
            ptr::null_mut(),
            &mut buf_size,
            handles.as_mut_ptr(),
        )
    };

    if ret.is_error() {
        return Err(Error::from_uefi_code(ret.as_usize()));
    }

    let handles_len = buf_size / HANDLE_SIZE;
    let handles = handles.get(..handles_len).ok_or(Error::UNEXPECTED)?;

    let system_handle = std::os::uefi::env::image_handle();
    for &handle in handles {
        let mut protocol: MaybeUninit<*mut rng::Protocol> = MaybeUninit::uninit();

        let mut protocol_guid = rng::PROTOCOL_GUID;
        let ret = unsafe {
            ((*boot_services.as_ptr()).open_protocol)(
                handle,
                &mut protocol_guid,
                protocol.as_mut_ptr().cast(),
                system_handle.as_ptr(),
                ptr::null_mut(),
                r_efi::system::OPEN_PROTOCOL_GET_PROTOCOL,
            )
        };

        let protocol = if ret.is_error() {
            continue;
        } else {
            let protocol = unsafe { protocol.assume_init() };
            NonNull::new(protocol).ok_or(Error::UNEXPECTED)?
        };

        // Try to use the acquired protocol handle
        let mut buf = [0u8; 8];
        let mut alg_guid = rng::ALGORITHM_RAW;
        let ret = unsafe {
            ((*protocol.as_ptr()).get_rng)(
                protocol.as_ptr(),
                &mut alg_guid,
                buf.len(),
                buf.as_mut_ptr(),
            )
        };

        if ret.is_error() {
            continue;
        }

        return Ok(protocol);
    }
    Err(Error::NO_RNG_HANDLE)
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    #[path = "../utils/lazy_ptr.rs"]
    mod lazy;

    static RNG_PROTOCOL: lazy::LazyPtr<rng::Protocol> = lazy::LazyPtr::new();

    let protocol = RNG_PROTOCOL.try_unsync_init(init)?;

    let mut alg_guid = rng::ALGORITHM_RAW;
    let ret = unsafe {
        ((*protocol.as_ptr()).get_rng)(
            protocol.as_ptr(),
            &mut alg_guid,
            dest.len(),
            dest.as_mut_ptr().cast::<u8>(),
        )
    };

    if ret.is_error() {
        Err(Error::from_uefi_code(ret.as_usize()))
    } else {
        Ok(())
    }
}

impl Error {
    pub(crate) const BOOT_SERVICES_UNAVAILABLE: Error = Self::new_internal(10);
    pub(crate) const NO_RNG_HANDLE: Error = Self::new_internal(11);
}


================================================
FILE: src/backends/esp_idf.rs
================================================
//! Implementation for ESP-IDF
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};

unsafe extern "C" {
    fn esp_fill_random(buf: *mut c_void, len: usize) -> u32;
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // Not that NOT enabling WiFi, BT, or the voltage noise entropy source (via `bootloader_random_enable`)
    // will cause ESP-IDF to return pseudo-random numbers based on the voltage noise entropy, after the initial boot process:
    // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html
    //
    // However tracking if some of these entropy sources is enabled is way too difficult to implement here
    unsafe { esp_fill_random(dest.as_mut_ptr().cast(), dest.len()) };

    Ok(())
}


================================================
FILE: src/backends/extern_impl.rs
================================================
//! An implementation which calls out to an externally defined function.
use crate::Error;
use core::mem::MaybeUninit;

/// Declares this function as an external implementation of [`fill_uninit`](crate::fill_uninit).
#[eii(fill_uninit)]
pub(crate) fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>;

/// Declares this function as an external implementation of [`u32`](crate::u32).
#[eii(u32)]
pub(crate) fn inner_u32() -> Result<u32, crate::Error> {
    crate::util::inner_u32()
}

/// Declares this function as an external implementation of [`u64`](crate::u64).
#[eii(u64)]
pub(crate) fn inner_u64() -> Result<u64, crate::Error> {
    crate::util::inner_u64()
}


================================================
FILE: src/backends/fuchsia.rs
================================================
//! Implementation for Fuchsia Zircon
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

#[link(name = "zircon")]
unsafe extern "C" {
    fn zx_cprng_draw(buffer: *mut u8, length: usize);
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    unsafe { zx_cprng_draw(dest.as_mut_ptr().cast::<u8>(), dest.len()) }
    Ok(())
}


================================================
FILE: src/backends/getentropy.rs
================================================
//! Implementation using getentropy(2)
//!
//! When porting to a new target, ensure that its implementation follows the
//! POSIX conventions from
//! <https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html>.
//!
//! Available since:
//!   - macOS 10.12
//!   - OpenBSD 5.6
//!   - Emscripten 2.0.5
//!   - vita newlib since Dec 2021
//!
//! For these targets, we use getentropy(2) because getrandom(2) doesn't exist.
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};

#[path = "../utils/get_errno.rs"]
mod utils;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/limits.h.html
    // says `GETENTROPY_MAX` is at least 256.
    const GETENTROPY_MAX: usize = 256;

    for chunk in dest.chunks_mut(GETENTROPY_MAX) {
        let ret = unsafe { libc::getentropy(chunk.as_mut_ptr().cast::<c_void>(), chunk.len()) };
        match ret {
            0 => continue,
            -1 => return Err(Error::from_errno(utils::get_errno())),
            _ => return Err(Error::UNEXPECTED),
        }
    }
    Ok(())
}


================================================
FILE: src/backends/getrandom.rs
================================================
//! Implementation using getrandom(2).
//!
//! Available since:
//!   - Linux Kernel 3.17, Glibc 2.25, Musl 1.1.20
//!   - Android API level 23 (Marshmallow)
//!   - NetBSD 10.0
//!   - FreeBSD 12.0
//!   - illumos since Dec 2018
//!   - DragonFly 5.7
//!   - Hurd Glibc 2.31
//!   - shim-3ds since Feb 2022
//!
//! For these platforms, we always use the default pool and never set the
//! GRND_RANDOM flag to use the /dev/random pool. On Linux/Android/Hurd, using
//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does
//! nothing. On illumos, the default pool is used to implement getentropy(2),
//! so we assume it is acceptable here.
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

#[path = "../utils/sys_fill_exact.rs"]
mod utils;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    utils::sys_fill_exact(dest, |buf| unsafe {
        libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0)
    })
}


================================================
FILE: src/backends/hermit.rs
================================================
//! Implementation for Hermit
use crate::Error;
use core::mem::MaybeUninit;

unsafe extern "C" {
    fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
    // Note that `sys_secure_rand32/64` are implemented using `sys_read_entropy`:
    // https://github.com/hermit-os/kernel/blob/430da84/src/syscalls/entropy.rs#L62-L104
    // But this may change in future and can depend on compilation target,
    // so to future-proof we use these "syscalls".
    fn sys_secure_rand32(value: *mut u32) -> i32;
    fn sys_secure_rand64(value: *mut u64) -> i32;
}

#[inline]
pub fn inner_u32() -> Result<u32, Error> {
    let mut res = MaybeUninit::uninit();
    let ret = unsafe { sys_secure_rand32(res.as_mut_ptr()) };
    match ret {
        0 => Ok(unsafe { res.assume_init() }),
        -1 => Err(Error::UNSUPPORTED),
        _ => Err(Error::UNEXPECTED),
    }
}

#[inline]
pub fn inner_u64() -> Result<u64, Error> {
    let mut res = MaybeUninit::uninit();
    let ret = unsafe { sys_secure_rand64(res.as_mut_ptr()) };
    match ret {
        0 => Ok(unsafe { res.assume_init() }),
        -1 => Err(Error::UNSUPPORTED),
        _ => Err(Error::UNEXPECTED),
    }
}

#[inline]
pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    while !dest.is_empty() {
        let res = unsafe { sys_read_entropy(dest.as_mut_ptr().cast::<u8>(), dest.len(), 0) };
        match res {
            res if res > 0 => {
                let len = usize::try_from(res).map_err(|_| Error::UNEXPECTED)?;
                dest = dest.get_mut(len..).ok_or(Error::UNEXPECTED)?;
            }
            code => {
                let code = i32::try_from(code).map_err(|_| Error::UNEXPECTED)?;
                return Err(Error::from_neg_error_code(code));
            }
        }
    }
    Ok(())
}


================================================
FILE: src/backends/linux_android_with_fallback.rs
================================================
//! Implementation for Linux / Android with `/dev/urandom` fallback
use super::use_file;
use crate::Error;
use core::{
    ffi::c_void,
    mem::{MaybeUninit, transmute},
    ptr::{self, NonNull},
};
use use_file::utils;

pub use crate::util::{inner_u32, inner_u64};

type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;

/// Sentinel value which indicates that `libc::getrandom` either not available,
/// or not supported by kernel.
const NOT_AVAILABLE: NonNull<c_void> = unsafe { NonNull::new_unchecked(usize::MAX as *mut c_void) };

#[cold]
#[inline(never)]
fn init() -> NonNull<c_void> {
    // Use static linking to `libc::getrandom` on MUSL targets and `dlsym` everywhere else
    #[cfg(not(target_env = "musl"))]
    let raw_ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"getrandom".as_ptr()) };
    #[cfg(target_env = "musl")]
    let raw_ptr = {
        let fptr: GetRandomFn = libc::getrandom;
        unsafe { transmute::<GetRandomFn, *mut c_void>(fptr) }
    };

    let res_ptr = match NonNull::new(raw_ptr) {
        Some(fptr) => {
            let getrandom_fn = unsafe { transmute::<*mut c_void, GetRandomFn>(fptr.as_ptr()) };
            // Check that `getrandom` syscall is supported by kernel
            let res = unsafe { getrandom_fn(ptr::dangling_mut(), 0, 0) };
            if cfg!(getrandom_test_linux_fallback) {
                NOT_AVAILABLE
            } else if res.is_negative() {
                match utils::get_errno() {
                    libc::ENOSYS => NOT_AVAILABLE, // No kernel support
                    // The fallback on EPERM is intentionally not done on Android since this workaround
                    // seems to be needed only for specific Linux-based products that aren't based
                    // on Android. See https://github.com/rust-random/getrandom/issues/229.
                    #[cfg(target_os = "linux")]
                    libc::EPERM => NOT_AVAILABLE, // Blocked by seccomp
                    _ => fptr,
                }
            } else {
                fptr
            }
        }
        None => NOT_AVAILABLE,
    };

    #[cfg(getrandom_test_linux_without_fallback)]
    if res_ptr == NOT_AVAILABLE {
        panic!("Fallback is triggered with enabled `getrandom_test_linux_without_fallback`")
    }

    res_ptr
}

// Prevent inlining of the fallback implementation
#[inline(never)]
fn use_file_fallback(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    use_file::fill_inner(dest)
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    #[path = "../utils/lazy_ptr.rs"]
    mod lazy;

    static GETRANDOM_FN: lazy::LazyPtr<c_void> = lazy::LazyPtr::new();
    let fptr = GETRANDOM_FN.unsync_init(init);

    if fptr == NOT_AVAILABLE {
        use_file_fallback(dest)
    } else {
        // note: `transmute` is currently the only way to convert a pointer into a function reference
        let getrandom_fn = unsafe { transmute::<*mut c_void, GetRandomFn>(fptr.as_ptr()) };
        utils::sys_fill_exact(dest, |buf| unsafe {
            getrandom_fn(buf.as_mut_ptr().cast(), buf.len(), 0)
        })
    }
}


================================================
FILE: src/backends/linux_raw.rs
================================================
//! Implementation for Linux / Android using `asm!`-based syscalls.
pub use crate::util::{inner_u32, inner_u64};
use crate::{Error, MaybeUninit};

#[cfg(not(any(target_os = "android", target_os = "linux")))]
compile_error!("`linux_raw` backend can be enabled only for Linux/Android targets!");

#[path = "../utils/sanitizer.rs"]
mod utils;

#[allow(non_upper_case_globals)]
unsafe fn getrandom_syscall(buf: *mut u8, buflen: usize, flags: u32) -> isize {
    let r0;

    // Based on `rustix` and `linux-raw-sys` code.
    cfg_if! {
        if #[cfg(all(
            target_arch = "arm",
            any(target_abi = "eabi", target_abi = "eabihf"),
        ))] {
            const __NR_getrandom: u32 = 384;
            // In thumb-mode, r7 is the frame pointer and is not permitted to be used in
            // an inline asm operand, so we have to use a different register and copy it
            // into r7 inside the inline asm.
            // Theoretically, we could detect thumb mode in the build script, but several
            // register moves are cheap enough compared to the syscall cost, so we do not
            // bother with it.
            unsafe {
                core::arch::asm!(
                    "mov {tmp}, r7",
                    "mov r7, {nr}",
                    "svc 0",
                    "mov r7, {tmp}",
                    tmp = out(reg) _,
                    nr = const __NR_getrandom,
                    inlateout("r0") buf => r0,
                    in("r1") buflen,
                    in("r2") flags,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(all(
            target_arch = "aarch64",
            any(target_abi = "", target_abi = "ilp32"),
        ))] {
            // According to the ILP32 patch for the kernel that hasn't yet
            // been merged into the mainline, "AARCH64/ILP32 ABI uses standard
            // syscall table [...] with the exceptions listed below," where
            // getrandom is not mentioned as an exception.
            const __NR_getrandom: u32 = 278;
            unsafe {
                core::arch::asm!(
                    "svc 0",
                    in("x8") __NR_getrandom,
                    inlateout("x0") buf => r0,
                    in("x1") buflen,
                    in("x2") flags,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(all(
            target_arch = "loongarch64",
            any(target_abi = "", target_abi = "ilp32"),
        ))] {
            const __NR_getrandom: u32 = 278;
            unsafe {
                core::arch::asm!(
                    "syscall 0",
                    in("$a7") __NR_getrandom,
                    inlateout("$a0") buf => r0,
                    in("$a1") buflen,
                    in("$a2") flags,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
            const __NR_getrandom: u32 = 278;
            unsafe {
                core::arch::asm!(
                    "ecall",
                    in("a7") __NR_getrandom,
                    inlateout("a0") buf => r0,
                    in("a1") buflen,
                    in("a2") flags,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(target_arch = "s390x")] {
            const __NR_getrandom: u32 = 349;
            unsafe {
                core::arch::asm!(
                    "svc 0",
                    in("r1") __NR_getrandom,
                    inlateout("r2") buf => r0,
                    in("r3") buflen,
                    in("r4") flags,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(target_arch = "x86")] {
            const __NR_getrandom: u32 = 355;
            // `int 0x80` is famously slow, but implementing vDSO is too complex
            // and `sysenter`/`syscall` have their own portability issues,
            // so we use the simple "legacy" way of doing syscalls.
            unsafe {
                core::arch::asm!(
                    "int $$0x80",
                    in("eax") __NR_getrandom,
                    in("ebx") buf,
                    in("ecx") buflen,
                    in("edx") flags,
                    lateout("eax") r0,
                    options(nostack, preserves_flags)
                );
            }
        } else if #[cfg(all(
            target_arch = "x86_64",
            any(target_abi = "", target_abi = "x32"),
        ))] {
            const __X32_SYSCALL_BIT: u32 = 0x40000000;
            const OFFSET: u32 = if cfg!(target_pointer_width = "32") { __X32_SYSCALL_BIT } else { 0 };
            const __NR_getrandom: u32 = OFFSET + 318;

            unsafe {
                core::arch::asm!(
                    "syscall",
                    in("rax") __NR_getrandom,
                    in("rdi") buf,
                    in("rsi") buflen,
                    in("rdx") flags,
                    lateout("rax") r0,
                    lateout("rcx") _,
                    lateout("r11") _,
                    options(nostack, preserves_flags)
                );
            }
        } else {
            compile_error!("`linux_raw` backend does not support this target arch");
        }
    }

    r0
}

#[inline]
pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // Value of this error code is stable across all target arches.
    const EINTR: isize = -4;

    loop {
        let ret = unsafe { getrandom_syscall(dest.as_mut_ptr().cast(), dest.len(), 0) };
        match usize::try_from(ret) {
            Ok(0) => return Err(Error::UNEXPECTED),
            Ok(len) => {
                let (l, r) = dest.split_at_mut_checked(len).ok_or(Error::UNEXPECTED)?;
                unsafe { utils::unpoison(l) };
                dest = r;
                if dest.is_empty() {
                    return Ok(());
                }
            }
            Err(_) if ret == EINTR => continue,
            Err(_) => {
                let code = i32::try_from(ret).map_err(|_| Error::UNEXPECTED)?;
                return Err(Error::from_neg_error_code(code));
            }
        }
    }
}


================================================
FILE: src/backends/netbsd.rs
================================================
//! Implementation for NetBSD
//!
//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we
//! implement our own weak linkage to it, and provide a fallback based on the
//! KERN_ARND sysctl.
use crate::Error;
use core::{
    cmp,
    ffi::c_void,
    mem::{self, MaybeUninit},
    ptr::{self, NonNull},
};

pub use crate::util::{inner_u32, inner_u64};

#[path = "../utils/sys_fill_exact.rs"]
mod utils;

unsafe extern "C" fn polyfill_using_kern_arand(
    buf: *mut c_void,
    buflen: libc::size_t,
    flags: libc::c_uint,
) -> libc::ssize_t {
    debug_assert_eq!(flags, 0);

    const MIB_LEN: libc::c_uint = 2;
    static MIB: [libc::c_int; MIB_LEN as usize] = [libc::CTL_KERN, libc::KERN_ARND];

    // NetBSD will only return up to 256 bytes at a time, and
    // older NetBSD kernels will fail on longer buffers.
    let mut len = cmp::min(buflen, 256);
    let ret = unsafe { libc::sysctl(MIB.as_ptr(), MIB_LEN, buf, &mut len, ptr::null(), 0) };

    match ret {
        0 if len <= 256 => libc::ssize_t::try_from(len).expect("len is in the range of 0..=256"),
        -1 => -1,
        // Zero return result will be converted into `Error::UNEXPECTED` by `sys_fill_exact`
        _ => 0,
    }
}

type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;

#[cold]
#[inline(never)]
fn init() -> NonNull<c_void> {
    let ptr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"getrandom".as_ptr()) };
    if !cfg!(getrandom_test_netbsd_fallback) {
        if let Some(ptr) = NonNull::new(ptr) {
            return ptr;
        }
    }
    // Verify `polyfill_using_kern_arand` has the right signature.
    const POLYFILL: GetRandomFn = polyfill_using_kern_arand;
    unsafe { NonNull::new_unchecked(POLYFILL as *mut c_void) }
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    #[path = "../utils/lazy_ptr.rs"]
    mod lazy;

    static GETRANDOM_FN: lazy::LazyPtr<c_void> = lazy::LazyPtr::new();

    let fptr = GETRANDOM_FN.unsync_init(init);
    let fptr = unsafe { mem::transmute::<*mut c_void, GetRandomFn>(fptr.as_ptr()) };
    utils::sys_fill_exact(dest, |buf| unsafe {
        fptr(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
    })
}


================================================
FILE: src/backends/rdrand.rs
================================================
//! RDRAND backend for x86(-64) targets
use crate::{Error, util::slice_as_uninit};
use core::mem::{MaybeUninit, size_of};

#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
compile_error!("`rdrand` backend can be enabled only for x86 and x86-64 targets!");

cfg_if! {
    if #[cfg(target_arch = "x86_64")] {
        use core::arch::x86_64 as arch;
        use arch::_rdrand64_step as rdrand_step;
        type Word = u64;
    } else if #[cfg(target_arch = "x86")] {
        use core::arch::x86 as arch;
        use arch::_rdrand32_step as rdrand_step;
        type Word = u32;
    }
}

// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
const RETRY_LIMIT: usize = 10;

#[target_feature(enable = "rdrand")]
fn rdrand() -> Option<Word> {
    for _ in 0..RETRY_LIMIT {
        let mut val = 0;
        // SAFETY: this function is safe to call from a `[target_feature(enable
        // = "rdrand")]` context (it itself is annotated with
        // `target_feature(enable = "rdrand")`) but was marked unsafe until
        // https://github.com/rust-lang/stdarch/commit/59864cd which was pulled
        // in via https://github.com/rust-lang/rust/commit/f2eb88b which is
        // expected to be included in 1.93.0. Since our MSRV is 1.85, we need to
        // use unsafe here and suppress the lint.
        //
        // TODO(MSRV 1.93): remove allow(unused_unsafe) and the unsafe block.
        #[allow(unused_unsafe)]
        if unsafe { rdrand_step(&mut val) } == 1 {
            return Some(val);
        }
    }
    None
}

// "rdrand" target feature requires "+rdrand" flag, see https://github.com/rust-lang/rust/issues/49653.
#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))]
compile_error!(
    "SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrand."
);

// Run a small self-test to make sure we aren't repeating values
// Adapted from Linux's test in arch/x86/kernel/cpu/rdrand.c
// Fails with probability < 2^(-90) on 32-bit systems
#[target_feature(enable = "rdrand")]
fn self_test() -> bool {
    // On AMD, RDRAND returns 0xFF...FF on failure, count it as a collision.
    let mut prev = Word::MAX;
    let mut fails = 0;
    for _ in 0..8 {
        match rdrand() {
            Some(val) if val == prev => fails += 1,
            Some(val) => prev = val,
            None => return false,
        };
    }
    fails <= 2
}

#[cold]
#[inline(never)]
fn init() -> bool {
    #[cfg(not(target_feature = "rdrand"))]
    {
        // SAFETY: All Rust x86 targets are new enough to have CPUID, and we
        // check that leaf 1 is supported before using it.
        //
        // TODO(MSRV 1.94): remove allow(unused_unsafe) and the unsafe blocks for `__cpuid`.
        #[allow(unused_unsafe)]
        let cpuid0 = unsafe { arch::__cpuid(0) };
        if cpuid0.eax < 1 {
            return false;
        }
        #[allow(unused_unsafe)]
        let cpuid1 = unsafe { arch::__cpuid(1) };

        let vendor_id = [
            cpuid0.ebx.to_le_bytes(),
            cpuid0.edx.to_le_bytes(),
            cpuid0.ecx.to_le_bytes(),
        ];
        if vendor_id == [*b"Auth", *b"enti", *b"cAMD"] {
            let mut family = (cpuid1.eax >> 8) & 0xF;
            if family == 0xF {
                family += (cpuid1.eax >> 20) & 0xFF;
            }
            // AMD CPUs families before 17h (Zen) sometimes fail to set CF when
            // RDRAND fails after suspend. Don't use RDRAND on those families.
            // See https://bugzilla.redhat.com/show_bug.cgi?id=1150286
            if family < 0x17 {
                return false;
            }
        }

        const RDRAND_FLAG: u32 = 1 << 30;
        if cpuid1.ecx & RDRAND_FLAG == 0 {
            return false;
        }
    }

    // SAFETY: We have already checked that rdrand is available.
    unsafe { self_test() }
}

fn is_rdrand_good() -> bool {
    #[path = "../utils/lazy_bool.rs"]
    mod lazy;

    static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new();

    RDRAND_GOOD.unsync_init(init)
}

#[target_feature(enable = "rdrand")]
fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
    // We use chunks_exact_mut instead of chunks_mut as it allows almost all
    // calls to memcpy to be elided by the compiler.
    let mut chunks = dest.chunks_exact_mut(size_of::<Word>());
    for chunk in chunks.by_ref() {
        let src = rdrand()?.to_ne_bytes();
        chunk.copy_from_slice(slice_as_uninit(&src));
    }

    let tail = chunks.into_remainder();
    let n = tail.len();
    if n > 0 {
        let src = rdrand()?.to_ne_bytes();
        tail.copy_from_slice(slice_as_uninit(&src[..n]));
    }
    Some(())
}

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "rdrand")]
fn rdrand_u32() -> Option<u32> {
    rdrand().map(crate::util::truncate)
}

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "rdrand")]
fn rdrand_u64() -> Option<u64> {
    rdrand()
}

#[cfg(target_arch = "x86")]
#[target_feature(enable = "rdrand")]
fn rdrand_u32() -> Option<u32> {
    rdrand()
}

#[cfg(target_arch = "x86")]
#[target_feature(enable = "rdrand")]
fn rdrand_u64() -> Option<u64> {
    let a = rdrand()?;
    let b = rdrand()?;
    Some((u64::from(a) << 32) | u64::from(b))
}

#[inline]
pub fn inner_u32() -> Result<u32, Error> {
    if !is_rdrand_good() {
        return Err(Error::NO_RDRAND);
    }
    // SAFETY: After this point, we know rdrand is supported.
    unsafe { rdrand_u32() }.ok_or(Error::FAILED_RDRAND)
}

#[inline]
pub fn inner_u64() -> Result<u64, Error> {
    if !is_rdrand_good() {
        return Err(Error::NO_RDRAND);
    }
    // SAFETY: After this point, we know rdrand is supported.
    unsafe { rdrand_u64() }.ok_or(Error::FAILED_RDRAND)
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    if !is_rdrand_good() {
        return Err(Error::NO_RDRAND);
    }
    // SAFETY: After this point, we know rdrand is supported.
    unsafe { rdrand_exact(dest) }.ok_or(Error::FAILED_RDRAND)
}

impl Error {
    /// RDRAND instruction failed due to a hardware issue.
    pub(crate) const FAILED_RDRAND: Error = Self::new_internal(10);
    /// RDRAND instruction unsupported on this target.
    pub(crate) const NO_RDRAND: Error = Self::new_internal(11);
}


================================================
FILE: src/backends/rndr.rs
================================================
//! RNDR register backend for aarch64 targets
//!
//! Arm Architecture Reference Manual for A-profile architecture:
//! ARM DDI 0487K.a, ID032224, D23.2.147 RNDR, Random Number
use crate::{
    Error,
    util::{slice_as_uninit, truncate},
};
use core::arch::asm;
use core::mem::{MaybeUninit, size_of};

#[cfg(not(target_arch = "aarch64"))]
compile_error!("the `rndr` backend can be enabled only for AArch64 targets!");

const RETRY_LIMIT: usize = 5;

/// Read a random number from the aarch64 RNDR register
///
/// Callers must ensure that FEAT_RNG is available on the system
/// The function assumes that the RNDR register is available
/// If it fails to read a random number, it will retry up to 5 times
/// After 5 failed reads the function will return `None`
#[target_feature(enable = "rand")]
unsafe fn rndr() -> Option<u64> {
    for _ in 0..RETRY_LIMIT {
        let mut x: u64;
        let mut nzcv: u64;

        // AArch64 RNDR register is accessible by s3_3_c2_c4_0
        unsafe {
            asm!(
                "mrs {x}, RNDR",
                "mrs {nzcv}, NZCV",
                x = out(reg) x,
                nzcv = out(reg) nzcv,
            );
        }

        // If the hardware returns a genuine random number, PSTATE.NZCV is set to 0b0000
        if nzcv == 0 {
            return Some(x);
        }
    }

    None
}

#[target_feature(enable = "rand")]
unsafe fn rndr_fill(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
    let mut chunks = dest.chunks_exact_mut(size_of::<u64>());
    for chunk in chunks.by_ref() {
        let src = unsafe { rndr() }?.to_ne_bytes();
        chunk.copy_from_slice(slice_as_uninit(&src));
    }

    let tail = chunks.into_remainder();
    let n = tail.len();
    if n > 0 {
        let src = unsafe { rndr() }?.to_ne_bytes();
        tail.copy_from_slice(slice_as_uninit(&src[..n]));
    }
    Some(())
}

#[cfg(target_feature = "rand")]
fn is_rndr_available() -> bool {
    true
}

#[cfg(not(target_feature = "rand"))]
fn is_rndr_available() -> bool {
    #[path = "../utils/lazy_bool.rs"]
    mod lazy;

    static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();

    cfg_if::cfg_if! {
        if #[cfg(feature = "std")] {
            extern crate std;
            RNDR_GOOD.unsync_init(|| std::arch::is_aarch64_feature_detected!("rand"))
        } else if #[cfg(target_os = "linux")] {
            /// Check whether FEAT_RNG is available on the system
            ///
            /// Requires the caller either be running in EL1 or be on a system supporting MRS
            /// emulation. Due to the above, the implementation is currently restricted to Linux.
            ///
            /// Relying on runtime detection bumps minimum supported Linux kernel version to 4.11.
            fn mrs_check() -> bool {
                let mut id_aa64isar0: u64;

                // If FEAT_RNG is implemented, ID_AA64ISAR0_EL1.RNDR (bits 60-63) are 0b0001
                // This is okay to do from EL0 in Linux because Linux will emulate MRS as per
                // https://docs.kernel.org/arch/arm64/cpu-feature-registers.html
                unsafe {
                    asm!(
                        "mrs {id}, ID_AA64ISAR0_EL1",
                        id = out(reg) id_aa64isar0,
                    );
                }

                (id_aa64isar0 >> 60) & 0xf >= 1
            }

            RNDR_GOOD.unsync_init(mrs_check)
        } else {
            compile_error!(
                "RNDR `no_std` runtime detection is currently supported only on Linux targets. \
                Either enable the `std` crate feature, or `rand` target feature at compile time."
            );
        }
    }
}

#[inline]
pub fn inner_u32() -> Result<u32, Error> {
    if !is_rndr_available() {
        return Err(Error::RNDR_NOT_AVAILABLE);
    }
    // SAFETY: after this point, we know the `rand` target feature is enabled
    let res = unsafe { rndr() };
    res.map(truncate).ok_or(Error::RNDR_FAILURE)
}

#[inline]
pub fn inner_u64() -> Result<u64, Error> {
    if !is_rndr_available() {
        return Err(Error::RNDR_NOT_AVAILABLE);
    }
    // SAFETY: after this point, we know the `rand` target feature is enabled
    let res = unsafe { rndr() };
    res.ok_or(Error::RNDR_FAILURE)
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    if !is_rndr_available() {
        return Err(Error::RNDR_NOT_AVAILABLE);
    }
    // SAFETY: after this point, we know the `rand` target feature is enabled
    unsafe { rndr_fill(dest).ok_or(Error::RNDR_FAILURE) }
}

impl Error {
    /// RNDR register read failed due to a hardware issue.
    pub(crate) const RNDR_FAILURE: Error = Self::new_internal(10);
    /// RNDR register is not supported on this target.
    pub(crate) const RNDR_NOT_AVAILABLE: Error = Self::new_internal(11);
}


================================================
FILE: src/backends/solaris.rs
================================================
//! Solaris implementation using getrandom(2).
//!
//! While getrandom(2) has been available since Solaris 11.3, it has a few
//! quirks not present on other OSes. First, on Solaris 11.3, calls will always
//! fail if bufsz > 1024. Second, it will always either fail or completely fill
//! the buffer (returning bufsz). Third, error is indicated by returning 0,
//! rather than by returning -1. Finally, "if GRND_RANDOM is not specified
//! then getrandom(2) is always a non blocking call". This _might_ imply that
//! in early-boot scenarios with low entropy, getrandom(2) will not properly
//! block. To be safe, we set GRND_RANDOM, mirroring the man page examples.
//!
//! For more information, see the man page linked in lib.rs and this blog post:
//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2
//! which also explains why this crate should not use getentropy(2).
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};
use libc::___errno as errno_location;

pub use crate::util::{inner_u32, inner_u64};

const MAX_BYTES: usize = 1024;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    for chunk in dest.chunks_mut(MAX_BYTES) {
        let ptr = chunk.as_mut_ptr().cast::<c_void>();
        let ret = unsafe { libc::getrandom(ptr, chunk.len(), libc::GRND_RANDOM) };
        // In case the man page has a typo, we also check for negative ret.
        // If getrandom(2) succeeds, it should have completely filled chunk.
        match usize::try_from(ret) {
            // Good. Keep going.
            Ok(ret) if ret == chunk.len() => {}
            // The syscall failed.
            Ok(0) => {
                let errno = unsafe { core::ptr::read(errno_location()) };
                return Err(Error::from_errno(errno));
            }
            // All other cases should be impossible.
            _ => return Err(Error::UNEXPECTED),
        }
    }
    Ok(())
}


================================================
FILE: src/backends/solid.rs
================================================
//! Implementation for SOLID
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

unsafe extern "C" {
    pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> i32;
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr().cast::<u8>(), dest.len()) };
    if ret >= 0 {
        Ok(())
    } else {
        Err(Error::from_neg_error_code(ret))
    }
}


================================================
FILE: src/backends/unsupported.rs
================================================
//! Implementation that errors at runtime.
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

pub fn fill_inner(_dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    Err(Error::UNSUPPORTED)
}


================================================
FILE: src/backends/use_file.rs
================================================
//! Implementations that just need to read from a file
use crate::Error;
use core::{
    ffi::{CStr, c_void},
    mem::MaybeUninit,
    sync::atomic::{AtomicI32, Ordering},
};

#[cfg(not(any(target_os = "android", target_os = "linux")))]
pub use crate::util::{inner_u32, inner_u64};

#[path = "../utils/sys_fill_exact.rs"]
pub(super) mod utils;

/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
/// For more information see the linked man pages in lib.rs.
///   - On Linux, "/dev/urandom is preferred and sufficient in all use cases".
///   - On Redox, only /dev/urandom is provided.
///   - On AIX, /dev/urandom will "provide cryptographically secure output".
///   - On Haiku and QNX Neutrino they are identical.
const FILE_PATH: &CStr = c"/dev/urandom";

// File descriptor is a "nonnegative integer", so we can safely use negative sentinel values.
const FD_UNINIT: libc::c_int = -1;
const FD_ONGOING_INIT: libc::c_int = -2;

// In theory `libc::c_int` could be something other than `i32`, but for the
// targets we currently support that use `use_file`, it is always `i32`.
// If/when we add support for a target where that isn't the case, we may
// need to use a different atomic type or make other accommodations. The
// compiler will let us know if/when that is the case, because the
// `FD.store(fd)` would fail to compile.
//
// The opening of the file, by libc/libstd/etc. may write some unknown
// state into in-process memory. (Such state may include some sanitizer
// bookkeeping, or we might be operating in a unikernal-like environment
// where all the "kernel" file descriptor bookkeeping is done in our
// process.) `get_fd_locked` stores into FD using `Ordering::Release` to
// ensure any such state is synchronized. `get_fd` loads from `FD` with
// `Ordering::Acquire` to synchronize with it.
static FD: AtomicI32 = AtomicI32::new(FD_UNINIT);

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let mut fd = FD.load(Ordering::Acquire);
    if fd == FD_UNINIT || fd == FD_ONGOING_INIT {
        fd = open_or_wait()?;
    }
    utils::sys_fill_exact(dest, |buf| unsafe {
        libc::read(fd, buf.as_mut_ptr().cast::<c_void>(), buf.len())
    })
}

/// Open a file in read-only mode.
fn open_readonly(path: &CStr) -> Result<libc::c_int, Error> {
    loop {
        let fd = unsafe { libc::open(path.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC) };
        if fd >= 0 {
            return Ok(fd);
        }
        let errno = utils::get_errno();
        // We should try again if open() was interrupted.
        if errno != libc::EINTR {
            return Err(Error::from_errno(errno));
        }
    }
}

#[cold]
#[inline(never)]
fn open_or_wait() -> Result<libc::c_int, Error> {
    loop {
        match FD.load(Ordering::Acquire) {
            FD_UNINIT => {
                let res = FD.compare_exchange_weak(
                    FD_UNINIT,
                    FD_ONGOING_INIT,
                    Ordering::AcqRel,
                    Ordering::Relaxed,
                );
                if res.is_ok() {
                    break;
                }
            }
            FD_ONGOING_INIT => sync::wait(),
            fd => return Ok(fd),
        }
    }

    let res = open_fd();
    let val = match res {
        Ok(fd) => fd,
        Err(_) => FD_UNINIT,
    };
    FD.store(val, Ordering::Release);

    // On non-Linux targets `wait` is just 1 ms sleep,
    // so we don't need any explicit wake up in addition
    // to updating value of `FD`.
    #[cfg(any(target_os = "android", target_os = "linux"))]
    sync::wake();

    res
}

fn open_fd() -> Result<libc::c_int, Error> {
    #[cfg(any(target_os = "android", target_os = "linux"))]
    sync::wait_until_rng_ready()?;
    let fd = open_readonly(FILE_PATH)?;
    debug_assert!(fd >= 0);
    Ok(fd)
}

#[cfg(not(any(target_os = "android", target_os = "linux")))]
mod sync {
    /// Sleep 1 ms before checking `FD` again.
    ///
    /// On non-Linux targets the critical section only opens file,
    /// which should not block, so in the unlikely contended case,
    /// we can sleep-wait for the opening operation to finish.
    pub(super) fn wait() {
        let rqtp = libc::timespec {
            tv_sec: 0,
            tv_nsec: 1_000_000,
        };
        let mut rmtp = libc::timespec {
            tv_sec: 0,
            tv_nsec: 0,
        };
        // We do not care if sleep gets interrupted, so the return value is ignored
        unsafe {
            libc::nanosleep(&rqtp, &mut rmtp);
        }
    }
}

#[cfg(any(target_os = "android", target_os = "linux"))]
mod sync {
    use super::{Error, FD, FD_ONGOING_INIT, open_readonly, utils};

    /// Wait for atomic `FD` to change value from `FD_ONGOING_INIT` to something else.
    ///
    /// Futex syscall with `FUTEX_WAIT` op puts the current thread to sleep
    /// until futex syscall with `FUTEX_WAKE` op gets executed for `FD`.
    ///
    /// For more information read: https://www.man7.org/linux/man-pages/man2/futex.2.html
    pub(super) fn wait() {
        let op = libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG;
        let timeout_ptr = core::ptr::null::<libc::timespec>();
        let ret = unsafe { libc::syscall(libc::SYS_futex, &FD, op, FD_ONGOING_INIT, timeout_ptr) };
        // FUTEX_WAIT should return either 0 or EAGAIN error
        debug_assert!({
            match ret {
                0 => true,
                -1 => utils::get_errno() == libc::EAGAIN,
                _ => false,
            }
        });
    }

    /// Wake up all threads which wait for value of atomic `FD` to change.
    pub(super) fn wake() {
        let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG;
        let ret = unsafe { libc::syscall(libc::SYS_futex, &FD, op, libc::INT_MAX) };
        debug_assert!(ret >= 0);
    }

    // Polls /dev/random to make sure it is ok to read from /dev/urandom.
    //
    // Polling avoids draining the estimated entropy from /dev/random;
    // short-lived processes reading even a single byte from /dev/random could
    // be problematic if they are being executed faster than entropy is being
    // collected.
    //
    // OTOH, reading a byte instead of polling is more compatible with
    // sandboxes that disallow `poll()` but which allow reading /dev/random,
    // e.g. sandboxes that assume that `poll()` is for network I/O. This way,
    // fewer applications will have to insert pre-sandbox-initialization logic.
    // Often (blocking) file I/O is not allowed in such early phases of an
    // application for performance and/or security reasons.
    //
    // It is hard to write a sandbox policy to support `libc::poll()` because
    // it may invoke the `poll`, `ppoll`, `ppoll_time64` (since Linux 5.1, with
    // newer versions of glibc), and/or (rarely, and probably only on ancient
    // systems) `select`. depending on the libc implementation (e.g. glibc vs
    // musl), libc version, potentially the kernel version at runtime, and/or
    // the target architecture.
    //
    // BoringSSL and libstd don't try to protect against insecure output from
    // `/dev/urandom'; they don't open `/dev/random` at all.
    //
    // OpenSSL uses `libc::select()` unless the `dev/random` file descriptor
    // is too large; if it is too large then it does what we do here.
    //
    // libsodium uses `libc::poll` similarly to this.
    pub(super) fn wait_until_rng_ready() -> Result<(), Error> {
        let fd = open_readonly(c"/dev/random")?;
        let mut pfd = libc::pollfd {
            fd,
            events: libc::POLLIN,
            revents: 0,
        };

        let res = loop {
            // A negative timeout means an infinite timeout.
            let res = unsafe { libc::poll(&mut pfd, 1, -1) };
            if res >= 0 {
                // We only used one fd, and cannot timeout.
                debug_assert_eq!(res, 1);
                break Ok(());
            }
            let errno = utils::get_errno();
            // Assuming that `poll` is called correctly,
            // on Linux it can return only EINTR and ENOMEM errors.
            match errno {
                libc::EINTR => continue,
                _ => break Err(Error::from_errno(errno)),
            }
        };
        unsafe { libc::close(fd) };
        res
    }
}


================================================
FILE: src/backends/vxworks.rs
================================================
//! Implementation for VxWorks
use crate::Error;
use core::{
    cmp::Ordering::{Equal, Greater, Less},
    mem::MaybeUninit,
    sync::atomic::{AtomicBool, Ordering::Relaxed},
};

pub use crate::util::{inner_u32, inner_u64};

static RNG_INIT: AtomicBool = AtomicBool::new(false);

#[cold]
fn init() -> Result<(), Error> {
    let ret = unsafe { libc::randSecure() };
    match ret.cmp(&0) {
        Greater => RNG_INIT.store(true, Relaxed),
        Equal => unsafe {
            libc::usleep(10);
        },
        Less => return Err(Error::VXWORKS_RAND_SECURE),
    }
    Ok(())
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    while !RNG_INIT.load(Relaxed) {
        init()?;
    }

    // Prevent overflow of i32
    let chunk_size = usize::try_from(i32::MAX).expect("VxWorks does not support 16-bit targets");
    for chunk in dest.chunks_mut(chunk_size) {
        let chunk_len: libc::c_int = chunk
            .len()
            .try_into()
            .expect("chunk size is bounded by i32::MAX");
        let p: *mut libc::c_uchar = chunk.as_mut_ptr().cast();
        let ret = unsafe { libc::randABytes(p, chunk_len) };
        match ret {
            0 => continue,
            -1 => {
                let errno = unsafe { libc::errnoGet() };
                return Err(Error::from_errno(errno));
            }
            _ => return Err(Error::UNEXPECTED),
        }
    }
    Ok(())
}

impl Error {
    /// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
    pub(crate) const VXWORKS_RAND_SECURE: Error = Self::new_internal(10);
}


================================================
FILE: src/backends/wasi_p1.rs
================================================
//! Implementation for WASI Preview 1
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

// This linking is vendored from the wasi crate:
// https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2344-2350
#[link(wasm_import_module = "wasi_snapshot_preview1")]
unsafe extern "C" {
    fn random_get(arg0: i32, arg1: i32) -> i32;
}

/// WASI p1 uses `u16` for error codes in its witx definitions:
/// https://github.com/WebAssembly/WASI/blob/38454e9e/legacy/preview1/witx/typenames.witx#L34-L39
const MAX_ERROR_CODE: i32 = u16::MAX as i32;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // Based on the wasi code:
    // https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2046-2062
    // Note that size of an allocated object can not be bigger than isize::MAX bytes.
    // WASI 0.1 supports only 32-bit WASM, so casting length to `i32` is safe.
    #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
    let ret = unsafe { random_get(dest.as_mut_ptr() as i32, dest.len() as i32) };
    match ret {
        0 => Ok(()),
        // WASI functions should return positive error codes which are smaller than `MAX_ERROR_CODE`
        code if code <= MAX_ERROR_CODE => Err(Error::from_neg_error_code(-code)),
        _ => Err(Error::UNEXPECTED),
    }
}


================================================
FILE: src/backends/wasi_p2_3.rs
================================================
//! Implementation for WASIp2 and WASIp3.
use crate::Error;
use core::{mem::MaybeUninit, ptr::copy_nonoverlapping};

#[cfg(target_env = "p2")]
use wasip2 as wasi;

// Workaround to silence `unexpected_cfgs` warning
// on Rust version between 1.85 and 1.91
#[cfg(not(target_env = "p2"))]
#[cfg(target_env = "p3")]
use wasip3 as wasi;

#[cfg(not(target_env = "p2"))]
#[cfg(not(target_env = "p3"))]
compile_error!("Unknown version of WASI (only previews 1, 2 and 3 are supported)");

use wasi::random::random::get_random_u64;

#[inline]
pub fn inner_u32() -> Result<u32, Error> {
    let val = get_random_u64();
    Ok(crate::util::truncate(val))
}

#[inline]
pub fn inner_u64() -> Result<u64, Error> {
    Ok(get_random_u64())
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let (prefix, chunks, suffix) = unsafe { dest.align_to_mut::<MaybeUninit<u64>>() };

    // We use `get_random_u64` instead of `get_random_bytes` because the latter creates
    // an allocation due to the Wit IDL [restrictions][0]. This should be fine since
    // the main use case of `getrandom` is seed generation.
    //
    // [0]: https://github.com/WebAssembly/wasi-random/issues/27
    if !prefix.is_empty() {
        let val = get_random_u64();
        let src = (&val as *const u64).cast();
        unsafe {
            copy_nonoverlapping(src, prefix.as_mut_ptr(), prefix.len());
        }
    }

    for dst in chunks {
        dst.write(get_random_u64());
    }

    if !suffix.is_empty() {
        let val = get_random_u64();
        let src = (&val as *const u64).cast();
        unsafe {
            copy_nonoverlapping(src, suffix.as_mut_ptr(), suffix.len());
        }
    }

    Ok(())
}


================================================
FILE: src/backends/wasm_js.rs
================================================
//! Implementation for WASM based on Web and Node.js
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");

use wasm_bindgen::{prelude::wasm_bindgen, JsValue};

// Maximum buffer size allowed in `Crypto.getRandomValuesSize` is 65536 bytes.
// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
const MAX_BUFFER_SIZE: usize = 65536;

#[cfg(not(target_feature = "atomics"))]
#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    for chunk in dest.chunks_mut(MAX_BUFFER_SIZE) {
        if get_random_values(chunk).is_err() {
            return Err(Error::WEB_CRYPTO);
        }
    }
    Ok(())
}

#[cfg(target_feature = "atomics")]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // getRandomValues does not work with all types of WASM memory,
    // so we initially write to browser memory to avoid exceptions.
    let buf_len = usize::min(dest.len(), MAX_BUFFER_SIZE);
    let buf_len_u32 = buf_len
        .try_into()
        .expect("buffer length is bounded by MAX_BUFFER_SIZE");
    let buf = js_sys::Uint8Array::new_with_length(buf_len_u32);
    for chunk in dest.chunks_mut(buf_len) {
        let chunk_len = chunk
            .len()
            .try_into()
            .expect("chunk length is bounded by MAX_BUFFER_SIZE");
        // The chunk can be smaller than buf's length, so we call to
        // JS to create a smaller view of buf without allocation.
        let sub_buf = if chunk_len == buf_len_u32 {
            &buf
        } else {
            &buf.subarray(0, chunk_len)
        };

        if get_random_values(sub_buf).is_err() {
            return Err(Error::WEB_CRYPTO);
        }

        sub_buf.copy_to_uninit(chunk);
    }
    Ok(())
}

#[wasm_bindgen]
unsafe extern "C" {
    // Crypto.getRandomValues()
    #[cfg(not(target_feature = "atomics"))]
    #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
    fn get_random_values(buf: &mut [MaybeUninit<u8>]) -> Result<(), JsValue>;
    #[cfg(target_feature = "atomics")]
    #[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
    fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
}

impl Error {
    /// The environment does not support the Web Crypto API.
    pub(crate) const WEB_CRYPTO: Error = Self::new_internal(10);
}


================================================
FILE: src/backends/windows.rs
================================================
//! Implementation for Windows 10 and later
//!
//! On Windows 10 and later, ProcessPrng "is the primary interface to the
//! user-mode per-processor PRNGs" and only requires bcryptprimitives.dll,
//! making it a better option than the other Windows RNG APIs:
//!   - BCryptGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
//!     - Requires bcrypt.dll (which loads bcryptprimitives.dll anyway)
//!     - Can cause crashes/hangs as BCrypt accesses the Windows Registry:
//!       https://github.com/rust-lang/rust/issues/99341
//!     - Causes issues inside sandboxed code:
//!       https://issues.chromium.org/issues/40277768
//!   - CryptGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
//!     - Deprecated and not available on UWP targets
//!     - Requires advapi32.lib/advapi32.dll (in addition to bcryptprimitives.dll)
//!     - Thin wrapper around ProcessPrng
//!   - RtlGenRandom: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//!     - Deprecated and not available on UWP targets
//!     - Requires advapi32.dll (in addition to bcryptprimitives.dll)
//!     - Requires using name "SystemFunction036"
//!     - Thin wrapper around ProcessPrng
//!
//! For more information see the Windows RNG Whitepaper: https://aka.ms/win10rng
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};

// Binding to the Windows.Win32.Security.Cryptography.ProcessPrng API. As
// bcryptprimitives.dll lacks an import library, we use "raw-dylib".
#[cfg_attr(
    target_arch = "x86",
    link(
        name = "bcryptprimitives",
        kind = "raw-dylib",
        import_name_type = "undecorated"
    )
)]
#[cfg_attr(
    not(target_arch = "x86"),
    link(name = "bcryptprimitives", kind = "raw-dylib")
)]
unsafe extern "system" {
    fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL;
}
#[expect(clippy::upper_case_acronyms)]
type BOOL = core::ffi::c_int;
const TRUE: BOOL = 1;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    let result = unsafe { ProcessPrng(dest.as_mut_ptr().cast::<u8>(), dest.len()) };
    // On Windows 10 and later, `ProcessPrng` is documented to always return
    // TRUE. All potential errors are handled during loading of
    // `BCryptPrimitive.dll`. See the "Process base PRNG" section in the
    // aforementioned Windows RNG whitepaper for more information.
    //
    // The Zig project found that Windows 8 implements `ProcessPrng` in a way
    // that may fail and return a value other than `TRUE`. Although recent
    // versions of the Rust toolchain do not support Windows 8, we cannot rule
    // out this backend being used in an executable that will run on Windows 8
    // (e.g. a fork of this crate backported to have an MSRV lower than 1.76,
    // or a fork of the Rust toolchain to support older Windows versions, or
    // other build hacks).
    //
    // Further, Wine's implementation of `ProcessPrng` CAN fail, in every
    // version through Wine 11.2, and this may be the case for any other Windows
    // emulation layers.
    if result == TRUE {
        Ok(())
    } else {
        Err(Error::UNEXPECTED)
    }
}


================================================
FILE: src/backends/windows_legacy.rs
================================================
//! Legacy implementation for Windows XP and later
//!
//! For targets where we cannot use ProcessPrng (added in Windows 10), we use
//! RtlGenRandom. See windows.rs for a more detailed discussion of the Windows
//! RNG APIs (and why we don't use BCryptGenRandom). On versions prior to
//! Windows 10, this implementation is secure. On Windows 10 and later, this
//! implementation behaves identically to the windows.rs implementation, except
//! that it forces the loading of an additional DLL (advapi32.dll).
//!
//! This implementation will not work on UWP targets (which lack advapi32.dll),
//! but such targets require Windows 10, so can use the standard implementation.
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};

#[cfg(not(windows))]
compile_error!("`windows_legacy` backend can be enabled only for Windows targets!");

// Binding to the Windows.Win32.Security.Authentication.Identity.RtlGenRandom
// API. Don't use windows-targets as it doesn't support Windows 7 targets.
#[link(name = "advapi32")]
unsafe extern "system" {
    #[link_name = "SystemFunction036"]
    fn RtlGenRandom(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN;
}
#[allow(clippy::upper_case_acronyms)]
type BOOLEAN = u8;
const TRUE: BOOLEAN = 1u8;

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    // Prevent overflow of u32
    let chunk_size = usize::try_from(i32::MAX).expect("Windows does not support 16-bit targets");
    for chunk in dest.chunks_mut(chunk_size) {
        let chunk_len = u32::try_from(chunk.len()).expect("chunk size is bounded by i32::MAX");
        let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr().cast::<c_void>(), chunk_len) };
        if ret != TRUE {
            return Err(Error::WINDOWS_RTL_GEN_RANDOM);
        }
    }
    Ok(())
}

impl Error {
    /// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
    pub(crate) const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(10);
}


================================================
FILE: src/backends.rs
================================================
//! System-specific implementations.
//!
//! This module should provide `fill_inner` with the signature
//! `fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>`.
//! The function MUST fully initialize `dest` when `Ok(())` is returned;
//! the function may need to use `sanitizer::unpoison` as well.
//! The function MUST NOT ever write uninitialized bytes into `dest`,
//! regardless of what value it returns.

cfg_if! {
    if #[cfg(getrandom_backend = "custom")] {
        mod custom;
        pub use custom::*;
    } else if #[cfg(getrandom_backend = "linux_getrandom")] {
        mod getrandom;
        pub use getrandom::*;
    } else if #[cfg(getrandom_backend = "linux_raw")] {
        mod linux_raw;
        pub use linux_raw::*;
    } else if #[cfg(getrandom_backend = "rdrand")] {
        mod rdrand;
        pub use rdrand::*;
    } else if #[cfg(getrandom_backend = "rndr")] {
        mod rndr;
        pub use rndr::*;
    } else if #[cfg(getrandom_backend = "efi_rng")] {
        mod efi_rng;
        pub use efi_rng::*;
    } else if #[cfg(getrandom_backend = "windows_legacy")] {
        mod windows_legacy;
        pub use windows_legacy::*;
    } else if #[cfg(getrandom_backend = "unsupported")] {
        mod unsupported;
        pub use unsupported::*;
    } else if #[cfg(getrandom_backend = "extern_impl")] {
        pub(crate) mod extern_impl;
        pub use extern_impl::*;
    } else if #[cfg(all(target_os = "linux", target_env = ""))] {
        mod linux_raw;
        pub use linux_raw::*;
    } else if #[cfg(target_os = "espidf")] {
        mod esp_idf;
        pub use esp_idf::*;
    } else if #[cfg(any(
        target_os = "haiku",
        target_os = "redox",
        target_os = "nto",
        target_os = "aix",
    ))] {
        mod use_file;
        pub use use_file::*;
    } else if #[cfg(any(
        target_os = "macos",
        target_os = "openbsd",
        target_os = "vita",
        target_os = "emscripten",
    ))] {
        mod getentropy;
        pub use getentropy::*;
    } else if #[cfg(any(
        // Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets
        // level 21 (Lollipop) [1], while `getrandom(2)` was added only in
        // level 23 (Marshmallow). Note that it applies only to the "old" `target_arch`es,
        // RISC-V Android targets sufficiently new API level, same will apply for potential
        // new Android `target_arch`es.
        // [0]: https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html
        // [1]: https://github.com/rust-lang/rust/pull/120593
        all(
            target_os = "android",
            any(
                target_arch = "aarch64",
                target_arch = "arm",
                target_arch = "x86",
                target_arch = "x86_64",
            ),
        ),
        // Only on these `target_arch`es Rust supports Linux kernel versions (3.2+)
        // that precede the version (3.17) in which `getrandom(2)` was added:
        // https://doc.rust-lang.org/stable/rustc/platform-support.html
        all(
            target_os = "linux",
            any(
                target_arch = "aarch64",
                target_arch = "arm",
                target_arch = "powerpc",
                target_arch = "powerpc64",
                target_arch = "s390x",
                target_arch = "x86",
                target_arch = "x86_64",
                // Minimum supported Linux kernel version for MUSL targets
                // is not specified explicitly (as of Rust 1.77) and they
                // are used in practice to target pre-3.17 kernels.
                all(
                    target_env = "musl",
                    not(
                        any(
                            target_arch = "riscv64",
                            target_arch = "riscv32",
                        ),
                    ),
                ),
            ),
        )
    ))] {
        mod use_file;
        mod linux_android_with_fallback;
        pub use linux_android_with_fallback::*;
    } else if #[cfg(any(
        target_os = "android",
        target_os = "linux",
        target_os = "dragonfly",
        target_os = "freebsd",
        target_os = "hurd",
        target_os = "illumos",
        target_os = "cygwin",
        // Check for target_arch = "arm" to only include the 3DS. Does not
        // include the Nintendo Switch (which is target_arch = "aarch64").
        all(target_os = "horizon", target_arch = "arm"),
    ))] {
        mod getrandom;
        pub use getrandom::*;
    } else if #[cfg(target_os = "solaris")] {
        mod solaris;
        pub use solaris::*;
    } else if #[cfg(target_os = "netbsd")] {
        mod netbsd;
        pub use netbsd::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(any(
        target_os = "ios",
        target_os = "visionos",
        target_os = "watchos",
        target_os = "tvos",
    ))] {
        mod apple_other;
        pub use apple_other::*;
    } else if #[cfg(all(target_arch = "wasm32", target_os = "wasi"))] {
        cfg_if! {
            if #[cfg(target_env = "p1")] {
                mod wasi_p1;
                pub use wasi_p1::*;
            } else {
                mod wasi_p2_3;
                pub use wasi_p2_3::*;
            }
        }
    } else if #[cfg(target_os = "hermit")] {
        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_arch = "x86_64", target_os = "motor"))] {
        mod rdrand;
        pub use rdrand::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(target_os = "solid_asp3")] {
        mod solid;
        pub use solid::*;
    } else if #[cfg(all(windows, target_vendor = "win7"))] {
        mod windows_legacy;
        pub use windows_legacy::*;
    } else if #[cfg(windows)] {
        mod windows;
        pub use windows::*;
    } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
        mod rdrand;
        pub use rdrand::*;
    } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] {
        cfg_if! {
            if #[cfg(feature = "wasm_js")] {
                mod wasm_js;
                pub use wasm_js::*;
            } else {
                compile_error!(concat!(
                    "The wasm32-unknown-unknown targets are not supported by default; \
                    you may need to enable the \"wasm_js\" crate feature. \
                    For more information see: \
                    https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#webassembly-support"
                ));
            }
        }
    } else {
        compile_error!(concat!(
            "target is not supported. You may need to define a custom backend see: \
            https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#custom-backend"
        ));
    }
}


================================================
FILE: src/error.rs
================================================
#[cfg(feature = "std")]
extern crate std;

use core::fmt;

cfg_if::cfg_if!(
    if #[cfg(target_os = "uefi")] {
        // See the UEFI spec for more information:
        // https://uefi.org/specs/UEFI/2.10/Apx_D_Status_Codes.html

        /// Raw error code.
        ///
        /// This alias mirrors unstable [`std::io::RawOsError`].
        ///
        /// [`std::io::RawOsError`]: https://doc.rust-lang.org/std/io/type.RawOsError.html
        pub type RawOsError = usize;
        type NonZeroRawOsError = core::num::NonZeroUsize;
        const UEFI_ERROR_FLAG: RawOsError = 1 << (RawOsError::BITS - 1);
    } else {
        /// Raw error code.
        ///
        /// This alias mirrors unstable [`std::io::RawOsError`].
        ///
        /// [`std::io::RawOsError`]: https://doc.rust-lang.org/std/io/type.RawOsError.html
        pub type RawOsError = i32;
        type NonZeroRawOsError = core::num::NonZeroI32;
    }
);

/// A small and `no_std` compatible error type
///
/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and
/// if so, which error code the OS gave the application. If such an error is
/// encountered, please consult with your system documentation.
///
/// *If this crate's `"std"` Cargo feature is enabled*, then:
/// - [`getrandom::Error`][Error] implements
///   [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html)
/// - [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) implements
///   [`From<getrandom::Error>`](https://doc.rust-lang.org/std/convert/trait.From.html).

// note: on non-UEFI targets OS errors are represented as negative integers,
// while on UEFI targets OS errors have the highest bit set to 1.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Error(NonZeroRawOsError);

impl Error {
    /// This target/platform is not supported by `getrandom`.
    pub const UNSUPPORTED: Error = Self::new_internal(0);
    /// The platform-specific `errno` returned a non-positive value.
    pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1);
    /// Encountered an unexpected situation which should not happen in practice.
    pub const UNEXPECTED: Error = Self::new_internal(2);

    /// Internal errors can be in the range of 2^16..2^17
    const INTERNAL_START: RawOsError = 1 << 16;
    /// Custom errors can be in the range of 2^17..(2^17 + 2^16)
    const CUSTOM_START: RawOsError = 1 << 17;

    /// Creates a new `Error` instance from a positive error code.
    ///
    /// Returns [`Error::ERRNO_NOT_POSITIVE`] for zero and negative error codes.
    #[cfg(not(target_os = "uefi"))]
    #[allow(dead_code)]
    pub(super) fn from_errno(errno: i32) -> Self {
        if errno > 0 {
            let code = errno
                .checked_neg()
                .expect("Positive number can be always negated");
            Error::from_neg_error_code(code)
        } else {
            Error::ERRNO_NOT_POSITIVE
        }
    }

    /// Creates a new `Error` instance from a negative error code.
    ///
    /// Returns [`Error::UNEXPECTED`] for zero and positive error codes.
    #[cfg(not(target_os = "uefi"))]
    #[allow(dead_code)]
    pub(super) fn from_neg_error_code(code: RawOsError) -> Self {
        if code < 0 {
            let code = NonZeroRawOsError::new(code).expect("`code` is negative");
            Self(code)
        } else {
            Error::UNEXPECTED
        }
    }

    /// Creates a new instance of an `Error` from an UEFI error code.
    #[cfg(target_os = "uefi")]
    #[allow(dead_code)]
    pub(super) fn from_uefi_code(code: RawOsError) -> Self {
        if code & UEFI_ERROR_FLAG != 0 {
            let code = NonZeroRawOsError::new(code).expect("The highest bit of `code` is set to 1");
            Self(code)
        } else {
            Self::UNEXPECTED
        }
    }

    /// Extract the raw OS error code (if this error came from the OS)
    ///
    /// This method is identical to [`std::io::Error::raw_os_error()`][1], except
    /// that it works in `no_std` contexts. On most targets this method returns
    /// `Option<i32>`, but some platforms (e.g. UEFI) may use a different primitive
    /// type like `usize`. Consult with the [`RawOsError`] docs for more information.
    ///
    /// If this method returns `None`, the error value can still be formatted via
    /// the `Display` implementation.
    ///
    /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error
    /// [`RawOsError`]: https://doc.rust-lang.org/std/io/type.RawOsError.html
    #[inline]
    pub fn raw_os_error(self) -> Option<RawOsError> {
        let code = self.0.get();

        // note: in this method we need to cover only backends which rely on
        // `Error::{from_error_code, from_errno, from_uefi_code}` methods,
        // on all other backends this method always returns `None`.

        #[cfg(target_os = "uefi")]
        {
            if code & UEFI_ERROR_FLAG != 0 {
                Some(code)
            } else {
                None
            }
        }

        #[cfg(not(target_os = "uefi"))]
        {
            // On most targets `std` expects positive error codes while retrieving error strings:
            // - `libc`-based targets use `strerror_r` which expects positive error codes.
            // - Hermit relies on the `hermit-abi` crate, which expects positive error codes:
            //   https://docs.rs/hermit-abi/0.4.0/src/hermit_abi/errno.rs.html#400-532
            // - WASIp1 uses the same conventions as `libc`:
            //   https://github.com/rust-lang/rust/blob/1.85.0/library/std/src/sys/pal/wasi/os.rs#L57-L67
            //
            // The only exception is Solid, `std` expects negative system error codes, see:
            // https://github.com/rust-lang/rust/blob/1.85.0/library/std/src/sys/pal/solid/error.rs#L5-L31
            if code >= 0 {
                None
            } else if cfg!(not(target_os = "solid_asp3")) {
                code.checked_neg()
            } else {
                Some(code)
            }
        }
    }

    /// Creates a new instance of an `Error` from a particular custom error code.
    pub const fn new_custom(n: u16) -> Error {
        // SAFETY: code > 0 as CUSTOM_START > 0 and adding `n` won't overflow `RawOsError`.
        let code = Error::CUSTOM_START + (n as RawOsError);
        Error(unsafe { NonZeroRawOsError::new_unchecked(code) })
    }

    /// Creates a new instance of an `Error` from a particular internal error code.
    pub(crate) const fn new_internal(n: u16) -> Error {
        // SAFETY: code > 0 as INTERNAL_START > 0 and adding `n` won't overflow `RawOsError`.
        let code = Error::INTERNAL_START + (n as RawOsError);
        Error(unsafe { NonZeroRawOsError::new_unchecked(code) })
    }

    fn internal_desc(&self) -> Option<&'static str> {
        let desc = match *self {
            Error::UNSUPPORTED => "getrandom: this target is not supported",
            Error::ERRNO_NOT_POSITIVE => "errno: did not return a positive value",
            Error::UNEXPECTED => "unexpected situation",
            #[cfg(any(
                target_os = "ios",
                target_os = "visionos",
                target_os = "watchos",
                target_os = "tvos",
            ))]
            Error::IOS_RANDOM_GEN => "SecRandomCopyBytes: iOS Security framework failure",
            #[cfg(all(windows, target_vendor = "win7"))]
            Error::WINDOWS_RTL_GEN_RANDOM => "RtlGenRandom: Windows system function failure",
            #[cfg(all(
                feature = "wasm_js",
                target_arch = "wasm32",
                any(target_os = "unknown", target_os = "none")
            ))]
            Error::WEB_CRYPTO => "Web Crypto API is unavailable",
            #[cfg(target_os = "vxworks")]
            Error::VXWORKS_RAND_SECURE => "randSecure: VxWorks RNG module is not initialized",

            #[cfg(any(
                getrandom_backend = "rdrand",
                all(target_arch = "x86_64", target_env = "sgx")
            ))]
            Error::FAILED_RDRAND => "RDRAND: failed multiple times: CPU issue likely",
            #[cfg(any(
                getrandom_backend = "rdrand",
                all(target_arch = "x86_64", target_env = "sgx")
            ))]
            Error::NO_RDRAND => "RDRAND: instruction not supported",

            #[cfg(getrandom_backend = "rndr")]
            Error::RNDR_FAILURE => "RNDR: Could not generate a random number",
            #[cfg(getrandom_backend = "rndr")]
            Error::RNDR_NOT_AVAILABLE => "RNDR: Register not supported",
            _ => return None,
        };
        Some(desc)
    }
}

impl core::error::Error for Error {}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut dbg = f.debug_struct("Error");
        if let Some(errno) = self.raw_os_error() {
            dbg.field("os_error", &errno);
            #[cfg(feature = "std")]
            dbg.field("description", &std::io::Error::from_raw_os_error(errno));
        } else if let Some(desc) = self.internal_desc() {
            dbg.field("internal_code", &self.0.get());
            dbg.field("description", &desc);
        } else {
            dbg.field("unknown_code", &self.0.get());
        }
        dbg.finish()
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(errno) = self.raw_os_error() {
            cfg_if! {
                if #[cfg(feature = "std")] {
                    std::io::Error::from_raw_os_error(errno).fmt(f)
                } else {
                    write!(f, "OS Error: {errno}")
                }
            }
        } else if let Some(desc) = self.internal_desc() {
            f.write_str(desc)
        } else {
            write!(f, "Unknown Error: {}", self.0.get())
        }
    }
}


================================================
FILE: src/error_std_impls.rs
================================================
extern crate std;

use crate::Error;
use std::io;

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        match err.raw_os_error() {
            Some(errno) => io::Error::from_raw_os_error(errno),
            None => io::Error::other(err),
        }
    }
}


================================================
FILE: src/lib.rs
================================================
// Overwrite links to crate items with intra-crate links
//! [`Error::UNEXPECTED`]: Error::UNEXPECTED
//! [`fill_uninit`]: fill_uninit

#![no_std]
#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico"
)]
#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(getrandom_backend = "efi_rng", feature(uefi_std))]
#![cfg_attr(getrandom_backend = "extern_impl", feature(extern_item_impls))]

#[macro_use]
extern crate cfg_if;

use core::mem::MaybeUninit;

mod backends;
mod error;
mod util;

#[cfg(feature = "std")]
mod error_std_impls;

/// `rand_core` adapter
#[cfg(feature = "sys_rng")]
mod sys_rng;

#[cfg(feature = "sys_rng")]
pub use rand_core;
#[cfg(feature = "sys_rng")]
pub use sys_rng::SysRng;

pub use crate::error::{Error, RawOsError};

/// Attribute macros for overwriting the core functionality of this crate.
///
/// This allows `getrandom` to provide a default implementation and a common interface
/// for all crates to use, while giving users a safe way to override that default where required.
///
/// Must be enabled via the `extern_impl` opt-in backend, as this functionality
/// is currently limited to nightly.
///
/// # Examples
///
/// ```rust
/// # use core::mem::MaybeUninit;
/// # #[cfg(getrandom_backend = "extern_impl")]
/// #[getrandom::implementation::fill_uninit]
/// fn my_fill_uninit_implementation(
///     dest: &mut [MaybeUninit<u8>]
/// ) -> Result<(), getrandom::Error> {
///     // ...
/// #   let _ = dest;
/// #   Err(Error::UNSUPPORTED)
/// }
/// ```
#[cfg(getrandom_backend = "extern_impl")]
pub mod implementation {
    pub use crate::backends::extern_impl::{fill_uninit, u32, u64};
}

/// Fill `dest` with random bytes from the system's preferred random number source.
///
/// This function returns an error on any failure, including partial reads. We
/// make no guarantees regarding the contents of `dest` on error. If `dest` is
/// empty, `getrandom` immediately returns success, making no calls to the
/// underlying operating system.
///
/// Blocking is possible, at least during early boot; see module documentation.
///
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), getrandom::Error> {
/// let mut buf = [0u8; 32];
/// getrandom::fill(&mut buf)?;
/// # Ok(()) }
/// ```
#[inline]
pub fn fill(dest: &mut [u8]) -> Result<(), Error> {
    // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape,
    // and `fill_uninit` guarantees it will never de-initialize
    // any part of `dest`.
    fill_uninit(unsafe { util::slice_as_uninit_mut(dest) })?;
    Ok(())
}

/// Fill potentially uninitialized buffer `dest` with random bytes from
/// the system's preferred random number source and return a mutable
/// reference to those bytes.
///
/// On successful completion this function is guaranteed to return a slice
/// which points to the same memory as `dest` and has the same length.
/// In other words, it's safe to assume that `dest` is initialized after
/// this function has returned `Ok`.
///
/// No part of `dest` will ever be de-initialized at any point, regardless
/// of what is returned.
///
/// # Examples
///
/// ```ignore
/// # // We ignore this test since `uninit_array` is unstable.
/// #![feature(maybe_uninit_uninit_array)]
/// # fn main() -> Result<(), getrandom::Error> {
/// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>();
/// let buf: &mut [u8] = getrandom::fill_uninit(&mut buf)?;
/// # Ok(()) }
/// ```
#[inline]
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
    if !dest.is_empty() {
        backends::fill_inner(dest)?;
    }

    #[cfg(getrandom_msan)]
    unsafe extern "C" {
        fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);
    }

    // SAFETY: `dest` has been fully initialized by `imp::fill_inner`
    // since it returned `Ok`.
    Ok(unsafe { util::slice_assume_init_mut(dest) })
}

/// Get random `u32` from the system's preferred random number source.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), getrandom::Error> {
/// let rng_seed = getrandom::u32()?;
/// # Ok(()) }
/// ```
#[inline]
pub fn u32() -> Result<u32, Error> {
    backends::inner_u32()
}

/// Get random `u64` from the system's preferred random number source.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), getrandom::Error> {
/// let rng_seed = getrandom::u64()?;
/// # Ok(()) }
/// ```
#[inline]
pub fn u64() -> Result<u64, Error> {
    backends::inner_u64()
}


================================================
FILE: src/sys_rng.rs
================================================
use crate::Error;
use rand_core::{TryCryptoRng, TryRng};

/// A [`TryRng`] interface over the system's preferred random number source
///
/// This is a zero-sized struct. It can be freely constructed with just `SysRng`.
///
/// This struct is also available as [`rand::rngs::SysRng`] when using [rand].
///
/// # Usage example
///
/// `SysRng` implements [`TryRng`]:
/// ```
/// use getrandom::{rand_core::TryRng, SysRng};
///
/// let mut key = [0u8; 32];
/// SysRng.try_fill_bytes(&mut key).unwrap();
/// ```
///
/// Using it as an [`Rng`] is possible using [`UnwrapErr`]:
/// ```
/// use getrandom::rand_core::{Rng, UnwrapErr};
/// use getrandom::SysRng;
///
/// let mut rng = UnwrapErr(SysRng);
/// let random_u64 = rng.next_u64();
/// ```
///
/// [rand]: https://crates.io/crates/rand
/// [`rand::rngs::SysRng`]: https://docs.rs/rand/latest/rand/rngs/struct.SysRng.html
/// [`Rng`]: rand_core::Rng
/// [`UnwrapErr`]: rand_core::UnwrapErr
#[derive(Clone, Copy, Debug, Default)]
pub struct SysRng;

impl TryRng for SysRng {
    type Error = Error;

    #[inline]
    fn try_next_u32(&mut self) -> Result<u32, Error> {
        crate::u32()
    }

    #[inline]
    fn try_next_u64(&mut self) -> Result<u64, Error> {
        crate::u64()
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        crate::fill(dest)
    }
}

impl TryCryptoRng for SysRng {}


================================================
FILE: src/util.rs
================================================
#![allow(dead_code)]
use crate::Error;
use core::{mem::MaybeUninit, ptr, slice};

/// Polyfill for `maybe_uninit_slice` feature's
/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have
/// been initialized.
#[inline(always)]
pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
    let ptr = ptr::from_mut(slice) as *mut [T];
    // SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
    unsafe { &mut *ptr }
}

#[inline]
pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
    unsafe { ptr::write_bytes(slice.as_mut_ptr(), 0, slice.len()) };
    unsafe { slice_assume_init_mut(slice) }
}

#[inline(always)]
pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
    let ptr = ptr::from_ref(slice) as *const [MaybeUninit<T>];
    // SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
    unsafe { &*ptr }
}

/// View an mutable initialized array as potentially-uninitialized.
///
/// This is unsafe because it allows assigning uninitialized values into
/// `slice`, which would be undefined behavior.
#[inline(always)]
pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
    let ptr = ptr::from_mut(slice)
Download .txt
gitextract_26_m99a6/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── build.yml
│       ├── nopanic.yaml
│       ├── release.yml
│       ├── tests.yml
│       └── workspace.yml
├── .gitignore
├── .typos.toml
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── SECURITY.md
├── benches/
│   └── buffer.rs
├── build.rs
├── custom_impl_test/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── nopanic_check/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── src/
│   ├── backends/
│   │   ├── apple_other.rs
│   │   ├── custom.rs
│   │   ├── efi_rng.rs
│   │   ├── esp_idf.rs
│   │   ├── extern_impl.rs
│   │   ├── fuchsia.rs
│   │   ├── getentropy.rs
│   │   ├── getrandom.rs
│   │   ├── hermit.rs
│   │   ├── linux_android_with_fallback.rs
│   │   ├── linux_raw.rs
│   │   ├── netbsd.rs
│   │   ├── rdrand.rs
│   │   ├── rndr.rs
│   │   ├── solaris.rs
│   │   ├── solid.rs
│   │   ├── unsupported.rs
│   │   ├── use_file.rs
│   │   ├── vxworks.rs
│   │   ├── wasi_p1.rs
│   │   ├── wasi_p2_3.rs
│   │   ├── wasm_js.rs
│   │   ├── windows.rs
│   │   └── windows_legacy.rs
│   ├── backends.rs
│   ├── error.rs
│   ├── error_std_impls.rs
│   ├── lib.rs
│   ├── sys_rng.rs
│   ├── util.rs
│   └── utils/
│       ├── get_errno.rs
│       ├── lazy_bool.rs
│       ├── lazy_ptr.rs
│       ├── sanitizer.rs
│       └── sys_fill_exact.rs
└── tests/
    ├── mod.rs
    └── sys_rng.rs
Download .txt
SYMBOL INDEX (180 symbols across 40 files)

FILE: benches/buffer.rs
  function bench_fill (line 12) | fn bench_fill<const N: usize>() {
  function bench_fill_uninit (line 20) | fn bench_fill_uninit<const N: usize>() {
  function bench_u32 (line 27) | fn bench_u32(b: &mut test::Bencher) {
  function bench_u32_via_fill (line 37) | fn bench_u32_via_fill(b: &mut test::Bencher) {
  function bench_u64 (line 51) | fn bench_u64(b: &mut test::Bencher) {
  function bench_u64_via_fill (line 61) | fn bench_u64_via_fill(b: &mut test::Bencher) {

FILE: build.rs
  function main (line 3) | fn main() {

FILE: custom_impl_test/src/lib.rs
  constant SEED (line 5) | const SEED: u64 = 0x9095_810F_1B2B_E175;
  type Xoshiro128PlusPlus (line 7) | struct Xoshiro128PlusPlus {
    method new (line 12) | fn new(mut seed: u64) -> Self {
    method next_u32 (line 26) | fn next_u32(&mut self) -> u32 {
  function custom_impl (line 47) | pub fn custom_impl(dst: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  function __getrandom_v03_custom (line 68) | unsafe extern "Rust" fn __getrandom_v03_custom(dst_ptr: *mut u8, len: us...
  function my_fill_uninit_implementation (line 75) | fn my_fill_uninit_implementation(dst: &mut [MaybeUninit<u8>]) -> Result<...
  function test_custom_fill (line 80) | fn test_custom_fill() {
  function test_custom_u32 (line 92) | fn test_custom_u32() {
  function test_custom_u64 (line 98) | fn test_custom_u64() {

FILE: nopanic_check/src/lib.rs
  function panic (line 6) | fn panic(_info: &core::panic::PanicInfo) -> ! {
  function getrandom_wrapper (line 14) | pub unsafe extern "C" fn getrandom_wrapper(buf_ptr: *mut u8, buf_len: us...
  function __getrandom_v03_custom (line 22) | unsafe extern "Rust" fn __getrandom_v03_custom(

FILE: src/backends/apple_other.rs
  function fill_inner (line 8) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant IOS_RANDOM_GEN (line 20) | pub(crate) const IOS_RANDOM_GEN: Error = Self::new_internal(10);

FILE: src/backends/custom.rs
  function fill_inner (line 8) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/efi_rng.rs
  function init (line 21) | fn init() -> Result<NonNull<rng::Protocol>, Error> {
  function fill_inner (line 94) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant BOOT_SERVICES_UNAVAILABLE (line 120) | pub(crate) const BOOT_SERVICES_UNAVAILABLE: Error = Self::new_internal(10);
  constant NO_RNG_HANDLE (line 121) | pub(crate) const NO_RNG_HANDLE: Error = Self::new_internal(11);

FILE: src/backends/esp_idf.rs
  function esp_fill_random (line 8) | fn esp_fill_random(buf: *mut c_void, len: usize) -> u32;
  function fill_inner (line 12) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/extern_impl.rs
  function fill_inner (line 7) | pub(crate) fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Err...
  function inner_u32 (line 11) | pub(crate) fn inner_u32() -> Result<u32, crate::Error> {
  function inner_u64 (line 17) | pub(crate) fn inner_u64() -> Result<u64, crate::Error> {

FILE: src/backends/fuchsia.rs
  function zx_cprng_draw (line 9) | fn zx_cprng_draw(buffer: *mut u8, length: usize);
  function fill_inner (line 13) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/getentropy.rs
  function fill_inner (line 23) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/getrandom.rs
  function fill_inner (line 27) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/hermit.rs
  function sys_read_entropy (line 6) | fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
  function sys_secure_rand32 (line 11) | fn sys_secure_rand32(value: *mut u32) -> i32;
  function sys_secure_rand64 (line 12) | fn sys_secure_rand64(value: *mut u64) -> i32;
  function inner_u32 (line 16) | pub fn inner_u32() -> Result<u32, Error> {
  function inner_u64 (line 27) | pub fn inner_u64() -> Result<u64, Error> {
  function fill_inner (line 38) | pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/linux_android_with_fallback.rs
  type GetRandomFn (line 13) | type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc:...
  constant NOT_AVAILABLE (line 17) | const NOT_AVAILABLE: NonNull<c_void> = unsafe { NonNull::new_unchecked(u...
  function init (line 21) | fn init() -> NonNull<c_void> {
  function use_file_fallback (line 65) | fn use_file_fallback(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  function fill_inner (line 70) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/linux_raw.rs
  function getrandom_syscall (line 12) | unsafe fn getrandom_syscall(buf: *mut u8, buflen: usize, flags: u32) -> ...
  function fill_inner (line 146) | pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/netbsd.rs
  function polyfill_using_kern_arand (line 19) | unsafe extern "C" fn polyfill_using_kern_arand(
  type GetRandomFn (line 42) | type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc:...
  function init (line 46) | fn init() -> NonNull<c_void> {
  function fill_inner (line 59) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/rdrand.rs
  constant RETRY_LIMIT (line 23) | const RETRY_LIMIT: usize = 10;
  function rdrand (line 26) | fn rdrand() -> Option<Word> {
  function self_test (line 56) | fn self_test() -> bool {
  function init (line 72) | fn init() -> bool {
  function is_rdrand_good (line 115) | fn is_rdrand_good() -> bool {
  function rdrand_exact (line 125) | fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
  function rdrand_u32 (line 145) | fn rdrand_u32() -> Option<u32> {
  function rdrand_u64 (line 151) | fn rdrand_u64() -> Option<u64> {
  function rdrand_u32 (line 157) | fn rdrand_u32() -> Option<u32> {
  function rdrand_u64 (line 163) | fn rdrand_u64() -> Option<u64> {
  function inner_u32 (line 170) | pub fn inner_u32() -> Result<u32, Error> {
  function inner_u64 (line 179) | pub fn inner_u64() -> Result<u64, Error> {
  function fill_inner (line 188) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant FAILED_RDRAND (line 198) | pub(crate) const FAILED_RDRAND: Error = Self::new_internal(10);
  constant NO_RDRAND (line 200) | pub(crate) const NO_RDRAND: Error = Self::new_internal(11);

FILE: src/backends/rndr.rs
  constant RETRY_LIMIT (line 15) | const RETRY_LIMIT: usize = 5;
  function rndr (line 24) | unsafe fn rndr() -> Option<u64> {
  function rndr_fill (line 49) | unsafe fn rndr_fill(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
  function is_rndr_available (line 66) | fn is_rndr_available() -> bool {
  function is_rndr_available (line 71) | fn is_rndr_available() -> bool {
  function inner_u32 (line 115) | pub fn inner_u32() -> Result<u32, Error> {
  function inner_u64 (line 125) | pub fn inner_u64() -> Result<u64, Error> {
  function fill_inner (line 135) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant RNDR_FAILURE (line 145) | pub(crate) const RNDR_FAILURE: Error = Self::new_internal(10);
  constant RNDR_NOT_AVAILABLE (line 147) | pub(crate) const RNDR_NOT_AVAILABLE: Error = Self::new_internal(11);

FILE: src/backends/solaris.rs
  constant MAX_BYTES (line 21) | const MAX_BYTES: usize = 1024;
  function fill_inner (line 24) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/solid.rs
  function SOLID_RNG_SampleRandomBytes (line 8) | pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> i32;
  function fill_inner (line 12) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/unsupported.rs
  function fill_inner (line 7) | pub fn fill_inner(_dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/use_file.rs
  constant FILE_PATH (line 21) | const FILE_PATH: &CStr = c"/dev/urandom";
  constant FD_UNINIT (line 24) | const FD_UNINIT: libc::c_int = -1;
  constant FD_ONGOING_INIT (line 25) | const FD_ONGOING_INIT: libc::c_int = -2;
  function fill_inner (line 44) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  function open_readonly (line 55) | fn open_readonly(path: &CStr) -> Result<libc::c_int, Error> {
  function open_or_wait (line 71) | fn open_or_wait() -> Result<libc::c_int, Error> {
  function open_fd (line 106) | fn open_fd() -> Result<libc::c_int, Error> {
  function wait (line 121) | pub(super) fn wait() {
  function wait (line 147) | pub(super) fn wait() {
  function wake (line 162) | pub(super) fn wake() {
  function wait_until_rng_ready (line 196) | pub(super) fn wait_until_rng_ready() -> Result<(), Error> {

FILE: src/backends/vxworks.rs
  function init (line 14) | fn init() -> Result<(), Error> {
  function fill_inner (line 27) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant VXWORKS_RAND_SECURE (line 55) | pub(crate) const VXWORKS_RAND_SECURE: Error = Self::new_internal(10);

FILE: src/backends/wasi_p1.rs
  function random_get (line 11) | fn random_get(arg0: i32, arg1: i32) -> i32;
  constant MAX_ERROR_CODE (line 16) | const MAX_ERROR_CODE: i32 = u16::MAX as i32;
  function fill_inner (line 19) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/wasi_p2_3.rs
  function inner_u32 (line 21) | pub fn inner_u32() -> Result<u32, Error> {
  function inner_u64 (line 27) | pub fn inner_u64() -> Result<u64, Error> {
  function fill_inner (line 32) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/wasm_js.rs
  constant MAX_BUFFER_SIZE (line 14) | const MAX_BUFFER_SIZE: usize = 65536;
  function fill_inner (line 18) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  function fill_inner (line 28) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  function get_random_values (line 63) | fn get_random_values(buf: &mut [MaybeUninit<u8>]) -> Result<(), JsValue>;
  function get_random_values (line 66) | fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
  constant WEB_CRYPTO (line 71) | pub(crate) const WEB_CRYPTO: Error = Self::new_internal(10);

FILE: src/backends/windows.rs
  function ProcessPrng (line 43) | fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL;
  type BOOL (line 46) | type BOOL = core::ffi::c_int;
  constant TRUE (line 47) | const TRUE: BOOL = 1;
  function fill_inner (line 50) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {

FILE: src/backends/windows_legacy.rs
  function RtlGenRandom (line 25) | fn RtlGenRandom(randombuffer: *mut c_void, randombufferlength: u32) -> B...
  type BOOLEAN (line 28) | type BOOLEAN = u8;
  constant TRUE (line 29) | const TRUE: BOOLEAN = 1u8;
  function fill_inner (line 32) | pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
  constant WINDOWS_RTL_GEN_RANDOM (line 47) | pub(crate) const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(10);

FILE: src/error.rs
  type Error (line 45) | pub struct Error(NonZeroRawOsError);
    constant UNSUPPORTED (line 49) | pub const UNSUPPORTED: Error = Self::new_internal(0);
    constant ERRNO_NOT_POSITIVE (line 51) | pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1);
    constant UNEXPECTED (line 53) | pub const UNEXPECTED: Error = Self::new_internal(2);
    constant INTERNAL_START (line 56) | const INTERNAL_START: RawOsError = 1 << 16;
    constant CUSTOM_START (line 58) | const CUSTOM_START: RawOsError = 1 << 17;
    method from_errno (line 65) | pub(super) fn from_errno(errno: i32) -> Self {
    method from_neg_error_code (line 81) | pub(super) fn from_neg_error_code(code: RawOsError) -> Self {
    method from_uefi_code (line 93) | pub(super) fn from_uefi_code(code: RawOsError) -> Self {
    method raw_os_error (line 115) | pub fn raw_os_error(self) -> Option<RawOsError> {
    method new_custom (line 153) | pub const fn new_custom(n: u16) -> Error {
    method new_internal (line 160) | pub(crate) const fn new_internal(n: u16) -> Error {
    method internal_desc (line 166) | fn internal_desc(&self) -> Option<&'static str> {
    method fmt (line 213) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method fmt (line 230) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

FILE: src/error_std_impls.rs
  function from (line 7) | fn from(err: Error) -> Self {

FILE: src/lib.rs
  function fill (line 87) | pub fn fill(dest: &mut [u8]) -> Result<(), Error> {
  function fill_uninit (line 118) | pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Er...
  function u32 (line 143) | pub fn u32() -> Result<u32, Error> {
  function u64 (line 157) | pub fn u64() -> Result<u64, Error> {

FILE: src/sys_rng.rs
  type SysRng (line 34) | pub struct SysRng;
  type Error (line 37) | type Error = Error;
  method try_next_u32 (line 40) | fn try_next_u32(&mut self) -> Result<u32, Error> {
  method try_next_u64 (line 45) | fn try_next_u64(&mut self) -> Result<u64, Error> {
  method try_fill_bytes (line 50) | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {

FILE: src/util.rs
  function slice_assume_init_mut (line 9) | pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> ...
  function uninit_slice_fill_zero (line 16) | pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
  function slice_as_uninit (line 22) | pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
  function slice_as_uninit_mut (line 33) | pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUnin...
  function inner_u32 (line 41) | pub fn inner_u32() -> Result<u32, Error> {
  function inner_u64 (line 56) | pub fn inner_u64() -> Result<u64, Error> {
  function truncate (line 70) | pub(crate) fn truncate(val: u64) -> u32 {

FILE: src/utils/get_errno.rs
  function get_errno (line 27) | pub(crate) fn get_errno() -> libc::c_int {

FILE: src/utils/lazy_bool.rs
  type LazyBool (line 11) | pub(crate) struct LazyBool(AtomicU8);
    constant UNINIT (line 14) | const UNINIT: u8 = u8::MAX;
    method new (line 17) | pub const fn new() -> Self {
    method cold_init (line 23) | fn cold_init(&self, init: impl FnOnce() -> bool) -> bool {
    method unsync_init (line 32) | pub fn unsync_init(&self, init: impl FnOnce() -> bool) -> bool {

FILE: src/utils/lazy_ptr.rs
  type LazyPtr (line 19) | pub(crate) struct LazyPtr<T>(AtomicPtr<T>);
  function new (line 23) | pub const fn new() -> Self {
  function cold_init (line 29) | fn cold_init<E>(&self, init: impl FnOnce() -> Result<NonNull<T>, E>) -> ...
  function try_unsync_init (line 38) | pub fn try_unsync_init<E>(
  function unsync_init (line 53) | pub fn unsync_init(&self, init: impl FnOnce() -> NonNull<T>) -> NonNull<...

FILE: src/utils/sanitizer.rs
  function unpoison (line 15) | pub unsafe fn unpoison(buf: &mut [MaybeUninit<u8>]) {

FILE: src/utils/sys_fill_exact.rs
  function sys_fill_exact (line 14) | pub(crate) fn sys_fill_exact(

FILE: tests/mod.rs
  function test_zero (line 9) | fn test_zero() {
  type DiffBits (line 16) | trait DiffBits: Sized {
    method diff_bits (line 17) | fn diff_bits(ab: (&Self, &Self)) -> usize;
    method diff_bits (line 21) | fn diff_bits((a, b): (&Self, &Self)) -> usize {
    method diff_bits (line 27) | fn diff_bits((a, b): (&Self, &Self)) -> usize {
    method diff_bits (line 33) | fn diff_bits((a, b): (&Self, &Self)) -> usize {
  function num_diff_bits (line 39) | fn num_diff_bits<T: DiffBits>(s1: &[T], s2: &[T]) -> usize {
  function test_diff (line 46) | fn test_diff() {
  function test_diff_u32 (line 71) | fn test_diff_u32() {
  function test_diff_u64 (line 90) | fn test_diff_u64() {
  function test_small (line 109) | fn test_small() {
  function test_small_uninit (line 137) | fn test_small_uninit() {
  function test_huge (line 166) | fn test_huge() {
  function test_huge_uninit (line 172) | fn test_huge_uninit() {
  function test_multithreading (line 184) | fn test_multithreading() {

FILE: tests/sys_rng.rs
  function test_sys_rng (line 8) | fn test_sys_rng() {
  function test_construction (line 16) | fn test_construction() {
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (218K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 448,
    "preview": "# Allow normal use of \"cargo run\" and \"cargo test\" on these wasm32 platforms.\n[target.wasm32-unknown-unknown]\nrunner = '"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 314,
    "preview": "version: 2\nupdates:\n- package-ecosystem: cargo\n  directory: \"/\"\n  versioning-strategy: lockfile-only\n  allow:\n    - depe"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 9272,
    "preview": "name: Build\n\non:\n  push:\n    branches: master\n  pull_request:\n    branches: master\n  schedule:\n    - cron: \"0 12 * * 1\"\n"
  },
  {
    "path": ".github/workflows/nopanic.yaml",
    "chars": 5067,
    "preview": "# This CI config checks that  getrandom's backend implementation\n# do not contain potential panics.\n#\n# It is unclear ho"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 489,
    "preview": "name: Publish to crates.io\non:\n  push:\n    tags: ['v*']  # Triggers when pushing tags starting with 'v'\njobs:\n  publish:"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 15130,
    "preview": "name: Test\n\non:\n  push:\n    branches: master\n  pull_request:\n    branches: master\n  schedule:\n    - cron: \"0 12 * * 1\"\n\n"
  },
  {
    "path": ".github/workflows/workspace.yml",
    "chars": 4775,
    "preview": "name: Workspace\n\non:\n  push:\n    branches: master\n  pull_request:\n    branches: master\n\npermissions:\n  contents: read\n\nj"
  },
  {
    "path": ".gitignore",
    "chars": 119,
    "preview": "/target\n**/*.rs.bk\nnopanic_check/Cargo.lock\nnopanic_check/target/\ncustom_impl_test/Cargo.lock\ncustom_impl_test/target/\n"
  },
  {
    "path": ".typos.toml",
    "chars": 79,
    "preview": "[files]\nextend-exclude = [\n    \".git/\"\n]\n\n[default.extend-words]\n\"nto\" = \"nto\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 29315,
    "preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changel"
  },
  {
    "path": "Cargo.toml",
    "chars": 5404,
    "preview": "[package]\nname = \"getrandom\"\nversion = \"0.4.2\"\nedition = \"2024\"\nrust-version = \"1.85\" # Sync tests.yml and README.md.\nau"
  },
  {
    "path": "LICENSE-APACHE",
    "chars": 10849,
    "preview": "                              Apache License\n                        Version 2.0, January 2004\n                     http"
  },
  {
    "path": "LICENSE-MIT",
    "chars": 1130,
    "preview": "Copyright (c) 2018-2026 The rust-random Project Developers\nCopyright (c) 2014 The Rust Project Developers\n\nPermission is"
  },
  {
    "path": "README.md",
    "chars": 20219,
    "preview": "# getrandom: system's random number generator\n\n[![Build Status]][GitHub Actions]\n[![Crate]][crates.io]\n[![Documentation]"
  },
  {
    "path": "SECURITY.md",
    "chars": 694,
    "preview": "# Security Policy\n\n## Supported Versions\n\nSecurity updates are applied only to the latest release.\n\n## Reporting a Vulne"
  },
  {
    "path": "benches/buffer.rs",
    "chars": 3551,
    "preview": "//! Basic benchmarks\n#![feature(test)]\nextern crate test;\n\nuse std::{\n    mem::{MaybeUninit, size_of},\n    slice,\n};\n\n//"
  },
  {
    "path": "build.rs",
    "chars": 446,
    "preview": "//! Build script for memory sanitization support\n\nfn main() {\n    // Automatically detect cfg(sanitize = \"memory\") even "
  },
  {
    "path": "custom_impl_test/Cargo.toml",
    "chars": 330,
    "preview": "[package]\nname = \"custom_impl_test\"\ndescription = \"Helper crate for testing custom implementations\"\nversion = \"0.1.0\"\ned"
  },
  {
    "path": "custom_impl_test/src/lib.rs",
    "chars": 2682,
    "preview": "use core::mem::MaybeUninit;\nuse getrandom::Error;\n\n/// Chosen by fair dice roll.\nconst SEED: u64 = 0x9095_810F_1B2B_E175"
  },
  {
    "path": "nopanic_check/Cargo.toml",
    "chars": 472,
    "preview": "[package]\nname = \"nopanic_check\"\ndescription = \"Helper crate for checking that getrandom implementation does not contain"
  },
  {
    "path": "nopanic_check/src/lib.rs",
    "chars": 921,
    "preview": "// WASI preview 2 requires enabled std\n#![cfg_attr(not(all(target_arch = \"wasm32\", target_env = \"p2\")), no_std)]\n\n#[cfg("
  },
  {
    "path": "src/backends/apple_other.rs",
    "chars": 636,
    "preview": "//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable.\nuse crate::Error;\nuse core::{ffi::c_voi"
  },
  {
    "path": "src/backends/custom.rs",
    "chars": 441,
    "preview": "//! An implementation which calls out to an externally defined function.\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\n"
  },
  {
    "path": "src/backends/efi_rng.rs",
    "chars": 3355,
    "preview": "//! Implementation for UEFI using EFI_RNG_PROTOCOL\nuse crate::Error;\nuse core::{\n    mem::MaybeUninit,\n    ptr::{self, N"
  },
  {
    "path": "src/backends/esp_idf.rs",
    "chars": 836,
    "preview": "//! Implementation for ESP-IDF\nuse crate::Error;\nuse core::{ffi::c_void, mem::MaybeUninit};\n\npub use crate::util::{inner"
  },
  {
    "path": "src/backends/extern_impl.rs",
    "chars": 678,
    "preview": "//! An implementation which calls out to an externally defined function.\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\n"
  },
  {
    "path": "src/backends/fuchsia.rs",
    "chars": 400,
    "preview": "//! Implementation for Fuchsia Zircon\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\npub use crate::util::{inner_u32, in"
  },
  {
    "path": "src/backends/getentropy.rs",
    "chars": 1179,
    "preview": "//! Implementation using getentropy(2)\n//!\n//! When porting to a new target, ensure that its implementation follows the\n"
  },
  {
    "path": "src/backends/getrandom.rs",
    "chars": 1004,
    "preview": "//! Implementation using getrandom(2).\n//!\n//! Available since:\n//!   - Linux Kernel 3.17, Glibc 2.25, Musl 1.1.20\n//!  "
  },
  {
    "path": "src/backends/hermit.rs",
    "chars": 1814,
    "preview": "//! Implementation for Hermit\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\nunsafe extern \"C\" {\n    fn sys_read_entropy"
  },
  {
    "path": "src/backends/linux_android_with_fallback.rs",
    "chars": 3174,
    "preview": "//! Implementation for Linux / Android with `/dev/urandom` fallback\nuse super::use_file;\nuse crate::Error;\nuse core::{\n "
  },
  {
    "path": "src/backends/linux_raw.rs",
    "chars": 6370,
    "preview": "//! Implementation for Linux / Android using `asm!`-based syscalls.\npub use crate::util::{inner_u32, inner_u64};\nuse cra"
  },
  {
    "path": "src/backends/netbsd.rs",
    "chars": 2246,
    "preview": "//! Implementation for NetBSD\n//!\n//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we\n//! imple"
  },
  {
    "path": "src/backends/rdrand.rs",
    "chars": 6444,
    "preview": "//! RDRAND backend for x86(-64) targets\nuse crate::{Error, util::slice_as_uninit};\nuse core::mem::{MaybeUninit, size_of}"
  },
  {
    "path": "src/backends/rndr.rs",
    "chars": 4830,
    "preview": "//! RNDR register backend for aarch64 targets\n//!\n//! Arm Architecture Reference Manual for A-profile architecture:\n//! "
  },
  {
    "path": "src/backends/solaris.rs",
    "chars": 1959,
    "preview": "//! Solaris implementation using getrandom(2).\n//!\n//! While getrandom(2) has been available since Solaris 11.3, it has "
  },
  {
    "path": "src/backends/solid.rs",
    "chars": 502,
    "preview": "//! Implementation for SOLID\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\npub use crate::util::{inner_u32, inner_u64};"
  },
  {
    "path": "src/backends/unsupported.rs",
    "chars": 238,
    "preview": "//! Implementation that errors at runtime.\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\npub use crate::util::{inner_u3"
  },
  {
    "path": "src/backends/use_file.rs",
    "chars": 8334,
    "preview": "//! Implementations that just need to read from a file\nuse crate::Error;\nuse core::{\n    ffi::{CStr, c_void},\n    mem::M"
  },
  {
    "path": "src/backends/vxworks.rs",
    "chars": 1627,
    "preview": "//! Implementation for VxWorks\nuse crate::Error;\nuse core::{\n    cmp::Ordering::{Equal, Greater, Less},\n    mem::MaybeUn"
  },
  {
    "path": "src/backends/wasi_p1.rs",
    "chars": 1407,
    "preview": "//! Implementation for WASI Preview 1\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\npub use crate::util::{inner_u32, in"
  },
  {
    "path": "src/backends/wasi_p2_3.rs",
    "chars": 1719,
    "preview": "//! Implementation for WASIp2 and WASIp3.\nuse crate::Error;\nuse core::{mem::MaybeUninit, ptr::copy_nonoverlapping};\n\n#[c"
  },
  {
    "path": "src/backends/wasm_js.rs",
    "chars": 2598,
    "preview": "//! Implementation for WASM based on Web and Node.js\nuse crate::Error;\nuse core::mem::MaybeUninit;\n\npub use crate::util:"
  },
  {
    "path": "src/backends/windows.rs",
    "chars": 3276,
    "preview": "//! Implementation for Windows 10 and later\n//!\n//! On Windows 10 and later, ProcessPrng \"is the primary interface to th"
  },
  {
    "path": "src/backends/windows_legacy.rs",
    "chars": 2087,
    "preview": "//! Legacy implementation for Windows XP and later\n//!\n//! For targets where we cannot use ProcessPrng (added in Windows"
  },
  {
    "path": "src/backends.rs",
    "chars": 6986,
    "preview": "//! System-specific implementations.\n//!\n//! This module should provide `fill_inner` with the signature\n//! `fn fill_inn"
  },
  {
    "path": "src/error.rs",
    "chars": 9900,
    "preview": "#[cfg(feature = \"std\")]\nextern crate std;\n\nuse core::fmt;\n\ncfg_if::cfg_if!(\n    if #[cfg(target_os = \"uefi\")] {\n        "
  },
  {
    "path": "src/error_std_impls.rs",
    "chars": 278,
    "preview": "extern crate std;\n\nuse crate::Error;\nuse std::io;\n\nimpl From<Error> for io::Error {\n    fn from(err: Error) -> Self {\n  "
  },
  {
    "path": "src/lib.rs",
    "chars": 4786,
    "preview": "// Overwrite links to crate items with intra-crate links\n//! [`Error::UNEXPECTED`]: Error::UNEXPECTED\n//! [`fill_uninit`"
  },
  {
    "path": "src/sys_rng.rs",
    "chars": 1399,
    "preview": "use crate::Error;\nuse rand_core::{TryCryptoRng, TryRng};\n\n/// A [`TryRng`] interface over the system's preferred random "
  },
  {
    "path": "src/util.rs",
    "chars": 2696,
    "preview": "#![allow(dead_code)]\nuse crate::Error;\nuse core::{mem::MaybeUninit, ptr, slice};\n\n/// Polyfill for `maybe_uninit_slice` "
  },
  {
    "path": "src/utils/get_errno.rs",
    "chars": 1332,
    "preview": "cfg_if! {\n    if #[cfg(any(target_os = \"netbsd\", target_os = \"openbsd\", target_os = \"android\", target_os = \"cygwin\"))] {"
  },
  {
    "path": "src/utils/lazy_bool.rs",
    "chars": 1206,
    "preview": "use core::sync::atomic::{AtomicU8, Ordering::Relaxed};\n\n/// Lazily caches a `bool` in an `AtomicU8`.\n///\n/// Initializat"
  },
  {
    "path": "src/utils/lazy_ptr.rs",
    "chars": 2110,
    "preview": "use core::{\n    convert::Infallible,\n    ptr::{self, NonNull},\n    sync::atomic::{AtomicPtr, Ordering::Relaxed},\n};\n\n///"
  },
  {
    "path": "src/utils/sanitizer.rs",
    "chars": 1134,
    "preview": "use core::mem::MaybeUninit;\n\n/// Unpoisons `buf` if MSAN support is enabled.\n///\n/// Most backends do not need to unpois"
  },
  {
    "path": "src/utils/sys_fill_exact.rs",
    "chars": 1390,
    "preview": "use crate::Error;\nuse core::mem::MaybeUninit;\n\nmod get_errno;\nmod sanitizer;\n\npub(crate) use get_errno::get_errno;\n\n/// "
  },
  {
    "path": "tests/mod.rs",
    "chars": 5628,
    "preview": "//! Main `getrandom` tests\nuse core::mem::MaybeUninit;\nuse getrandom::{fill, fill_uninit};\n\n#[cfg(all(feature = \"wasm_js"
  },
  {
    "path": "tests/sys_rng.rs",
    "chars": 357,
    "preview": "//! Tests for `SysRng`\n#![cfg(feature = \"sys_rng\")]\n\nuse getrandom::SysRng;\nuse getrandom::rand_core::TryRng;\n\n#[test]\nf"
  }
]

About this extraction

This page contains the full source code of the rust-random/getrandom GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (203.2 KB), approximately 58.5k tokens, and a symbol index with 180 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!