oxicode 0.2.5

A modern binary serialization library - successor to bincode
Documentation
name: CI

on:
  push:
    branches: [master, "*.*.x"]
  pull_request:
    branches: [master]

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: -Dwarnings

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  fmt:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all -- --check

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      - run: cargo clippy --workspace --all-targets --all-features -- -D warnings

  check:
    name: Check (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.os }}
      - run: cargo check --workspace --all-targets --all-features

  # MSRV is 1.81.0 for the *library* (oxicode + oxicode_derive). This
  # intentionally does not use `--all-targets`/`--all-features`:
  #
  # - `compression-lz4`/`compression-zstd` transitively depend on
  #   `oxiarc-core`, which requires Cargo's `edition2024` support
  #   (stabilized in Rust 1.85) — building those features needs a newer
  #   toolchain than the crate's own MSRV. Tracked as a follow-up; the
  #   README/MSRV docs should note this caveat until oxiarc-core no
  #   longer requires edition2024 at our MSRV.
  # - dev-dependencies (criterion -> clap 4.6.2) also require
  #   `edition2024`, so `--all-targets` (which pulls in benches/tests)
  #   cannot build at 1.81.0 either. MSRV therefore covers the public
  #   library surface, matching how `rust-version` is documented by
  #   Cargo itself (it governs the package, not its dev-dependencies).
  msrv:
    name: MSRV (1.81.0)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.81.0"
      - uses: Swatinem/rust-cache@v2
      - run: cargo check -p oxicode_derive
      - run: cargo check -p oxicode --no-default-features
      - run: cargo check -p oxicode --no-default-features --features alloc
      - run: cargo check -p oxicode --no-default-features --features std
      - run: cargo check -p oxicode --no-default-features --features derive
      - run: cargo check -p oxicode --no-default-features --features serde
      - run: cargo check -p oxicode --no-default-features --features checksum
      - run: cargo check -p oxicode --no-default-features --features simd
      - run: cargo check -p oxicode --features async-tokio

  test:
    name: Test (all features, partition ${{ matrix.partition }}/2)
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        partition: [1, 2]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@nextest
      - uses: Swatinem/rust-cache@v2
        with:
          key: test-${{ matrix.partition }}
      - run: cargo nextest run --workspace --all-features --partition count:${{ matrix.partition }}/2

  test-macos:
    name: Test (default features, macOS)
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@nextest
      - uses: Swatinem/rust-cache@v2
      - run: cargo nextest run --workspace

  # The entire tests/ integration-test tree is now crate-level `#![cfg(...)]`
  # gated on the exact features each file needs (derive/std/alloc/serde/
  # checksum/compression/simd/async-tokio/validation/versioning, determined
  # per-file from its imports), so `--tests` builds cleanly for every reduced
  # feature set below (verified locally via `cargo check -p oxicode
  # --no-default-features --all-targets` and `--no-default-features
  # --features alloc --all-targets`). `--all-targets` (which also pulls in
  # benches/ and examples/) is intentionally NOT used yet: those targets
  # still call `alloc`-gated APIs (e.g. `encode_to_vec`) unconditionally and
  # have no `required-features` in Cargo.toml, which is a separate,
  # not-yet-fixed gap tracked outside this test-tree hardening pass.
  feature-matrix-reduced:
    name: Check (--no-default-features, feature=${{ matrix.feature }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        feature: ["", alloc]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@nextest
      - uses: Swatinem/rust-cache@v2
        with:
          key: reduced-${{ matrix.feature }}
      - name: cargo check --no-default-features (lib + tests)
        if: matrix.feature == ''
        run: cargo check -p oxicode --no-default-features --lib --tests
      - name: cargo nextest run --lib --tests --no-default-features
        if: matrix.feature == ''
        run: cargo nextest run -p oxicode --lib --tests --no-default-features
      - name: cargo check --no-default-features --features ${{ matrix.feature }} (lib + tests)
        if: matrix.feature != ''
        run: cargo check -p oxicode --no-default-features --features ${{ matrix.feature }} --lib --tests
      - name: cargo nextest run --lib --tests --no-default-features --features ${{ matrix.feature }}
        if: matrix.feature != ''
        run: cargo nextest run -p oxicode --lib --tests --no-default-features --features ${{ matrix.feature }}

  feature-matrix:
    name: Test (feature=${{ matrix.feature }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        feature:
          - simd
          - compression-lz4
          - compression-zstd
          - serde
          - checksum
          - async-tokio
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@nextest
      - uses: Swatinem/rust-cache@v2
        with:
          key: feature-${{ matrix.feature }}
      - run: cargo nextest run -p oxicode --lib --tests --features ${{ matrix.feature }}

  doc:
    name: Documentation
    runs-on: ubuntu-latest
    env:
      RUSTDOCFLAGS: -Dwarnings
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo doc --workspace --all-features --no-deps
      - run: cargo test --doc --all-features

  # Big-endian (s390x) and 32-bit (i686) checks for a serialization crate
  # with explicit endianness handling (to_le_bytes/to_be_bytes/from_*_bytes
  # in config.rs, varint/*, de/impls.rs) and unsafe pointer-width-sensitive
  # code (de/impls.rs, de/borrow_slice.rs, features/impl_alloc.rs,
  # simd/aligned.rs). `cargo check --target` catches byte-order/pointer-
  # width regressions in type layout and const-eval without requiring a
  # full cross-linked test run.
  cross-target:
    name: Cross-check (${{ matrix.target }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - s390x-unknown-linux-gnu # big-endian, 64-bit
          - i686-unknown-linux-gnu # little-endian, 32-bit
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
        with:
          key: cross-${{ matrix.target }}
      - run: cargo check -p oxicode --all-features --target ${{ matrix.target }}

  # Miri coverage of the crate's `unsafe` usage (src/de/impls.rs — fixed
  # array MaybeUninit decode; src/de/borrow_slice.rs — zero-copy slice
  # borrow; src/features/impl_alloc.rs — Rc/Arc/Box alloc paths;
  # src/simd/{aligned,array,copy}.rs — aligned-buffer SIMD paths). Targets
  # are hand-picked integration tests that exercise these modules; unlike
  # the previous job, this is NOT `continue-on-error` — a Miri failure
  # fails the build.
  miri:
    name: Miri (unsafe code)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@nightly
        with:
          components: miri
      - uses: Swatinem/rust-cache@v2
      - name: Miri - fixed-size array decode (de::impls MaybeUninit path)
        run: cargo +nightly miri test -p oxicode --test array_fixed_size_advanced2_test --test fixed_array_advanced_test --features derive
        env:
          MIRIFLAGS: "-Zmiri-strict-provenance"
      - name: Miri - alloc types (Rc/Arc/Box/BTreeMap unsafe paths)
        run: cargo +nightly miri test -p oxicode --test alloc_types_test --features derive
        env:
          MIRIFLAGS: "-Zmiri-strict-provenance"
      - name: Miri - borrow-decode (zero-copy str/bytes paths)
        run: cargo +nightly miri test -p oxicode --test borrow_decode_test --features derive
        env:
          MIRIFLAGS: "-Zmiri-strict-provenance"
      - name: Miri - SIMD aligned buffers
        run: cargo +nightly miri test -p oxicode --test simd_correctness_test --features simd,derive
        env:
          MIRIFLAGS: "-Zmiri-strict-provenance"

  deny:
    name: cargo-deny
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: EmbarkStudios/cargo-deny-action@v2
        with:
          command: check bans licenses advisories sources

  # `AsyncEncoder`/`AsyncDecoder` were renamed to `AsyncStreamingEncoder`/
  # `AsyncStreamingDecoder`, but backward-compatible `pub type` aliases were
  # kept (source-compat proven by tests/async_backcompat_names_test.rs).
  # cargo-semver-checks does not recognize a type alias as an equivalent
  # re-export of the old struct path, so it still flags a `struct_missing`
  # false positive for oxicode::streaming::{AsyncEncoder,AsyncDecoder}. That
  # single lint is downgraded to `warn` in the root Cargo.toml under
  # `[package.metadata.cargo-semver-checks.lints]` (read automatically by
  # the action below); every other semver lint stays at `deny` and this job
  # still hard-fails on any real breakage.
  semver-checks:
    name: cargo-semver-checks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: obi1kenobi/cargo-semver-checks-action@v2
        with:
          package: oxicode, oxicode_derive