Skip to content

v0.5.0 - Proven panic-free, and a twentieth the size

Choose a tag to compare

@buvinghausen buvinghausen released this 02 Oct 18:46
· 36 commits to master since this release
63f0c72

0.5.0 proves the Rust core cannot panic, fixes the panics that proof turned up, and cuts the native library every binding loads to a twentieth of its size. The full list is in CHANGELOG.md.

Highlights

  • The public API is proven panic-free at link time. Every generation, parsing and conversion function and every C export carries #[no_panic] under the new no-panic feature, and CI links a release binary that calls each one on Linux and Windows, so a panic path the optimizer cannot remove fails the build. The feature is off by default and changes no code a consumer runs.

  • The native libraries are a twentieth the size. The shared library is now built #![no_std], and link-time optimization finally reaches it. Same 13 exports over the same code.

    0.4.0 0.5.0
    linux-x64 426,856 bytes 19,048 bytes
    win-x64 124,928 bytes 17,920 bytes

    The Linux libraries now depend on libc alone, so the musl builds no longer need libgcc_s. The Python, Ruby and PHP extensions keep std, so a panic in one still surfaces as a host exception.

  • Python wheels are tested before they ship. All eight are built, installed on their own platform and called into on every CI run, and the release publishes those exact files after checking their count, version and provenance. Through 0.4.0 they were built at the tag, and 0.4.0's osx-x64 wheel failed there.

  • The Composer package is smaller. It no longer carries the other bindings: 2.6 MB downloaded (was 3.5), 6.1 MB unpacked (was 8.5).

Upgrade notes

Rust is the one breaking change. NewV6Error and NewV7Error gained a BufferTooSmall variant and are now #[non_exhaustive], so a match on either one outside the crate needs a wildcard arm. That is why this is 0.5.0.

Every other package is a drop-in. The C ABI only gained return code 3 from uuid_new_v6_batch/uuid_new_v7_batch (a count * 16 that overflows usize). Only a 32-bit target can reach it, and no binding can, because each allocates its buffer before the call.

Building from source: [lib] now declares only the rlib. Build the shared library with cargo cdylib and the wasm32-wasip1 module with cargo wasm-module; a plain cargo build no longer produces a shared library.

Fixes

All in the Rust crate unless noted.

  • default-features = false builds on every target. It failed with "#[panic_handler] function required" on any target that can produce a cdylib, including the developer's own machine and wasm32-unknown-unknown. CI now builds a real consumer for both.
  • Uuid::from_str no longer panics on a stray hyphen. A 36-character string with an extra hyphen in the last group read one byte past the end (00000000-0000-0000-0000--00000000000). It is now ParseUuidError.
  • A short buffer passed to new_v6_batch/new_v7_batch returns BufferTooSmall instead of panicking, and leaves the buffer untouched.
  • v7::now_v7 no longer panics on a clock set before 1970. It returns TimestampOutOfRange, as it now also does for a clock so far ahead that its milliseconds overflow a u64, which used to be silently truncated.
  • Timestamp::to_unix_millis saturates instead of overflowing. In a release build it used to wrap into a valid-looking timestamp, so new_v6_at/new_v7_at minted a UUID for the wrong time.
  • Ruby: the native extension falls back to RuntimeError instead of panicking on an uninitialized exception cache (unreachable in practice).

Verifying

Every native library and static archive in this release is built by CI and carries a build-provenance attestation:

gh attestation verify go/native/linux-x64/libhyperuuid.so \
  --repo SkunkWerkx/HyperUuid --signer-repo SkunkWerkx/.github

The Python wheels are now signed by the forge, so they verify the same way (or with --owner SkunkWerkx). Wheels up to 0.4.0 verify with --repo alone.