Repository navigation
0.8.0 adds UUID inspection from the core: version, variant and an RFC check, also on values read straight back from SQL Server. It also guarantees that a v7 batch is in strictly increasing order, and brings Android to C#, Go and Swift. Most of it was asked for by Norse Architecture, the first consumer. The full list is in CHANGELOG.md.
Highlights
-
Version and variant inspection (#29). Every binding now has
Version,VariantandIsRfc, in its own spelling. They come from new C exportsuuid_version,uuid_variantanduuid_is_rfc; in Rust they areUuid::variant()andUuid::is_rfc(version), beside the existingUuid::version(). UseIsRfc(id, 7)before trusting a value's v7 fields, for example in a wrap constructor or a deserializer. It checks the RFC variant as well as the version nibble, which a platform's own nibble-onlyVersionproperty doesn't. Swift had no version or variant accessor before. -
Reads straight from SQL Server byte order (#30). A new
Layout(Rfc9562,SqlServer) is accepted byVersion,IsRfc,V6UnixMillis,V7UnixMillis,V6Timestamp,V7TimestampandGetTimestamp. A value read back from auniqueidentifiercolumn is checked and dated in one native call, without converting it back first. In SQL Server order only v6 and v7 exist, and the core checks the variant bits as well as the version nibble, so it never confuses the two. -
A v7 batch is always strictly increasing (#32). The counter wraps every 2^26 values. Before this release, a batch that straddled the wrap had its second half sort before its first.
- Crossing the wrap: the UUIDs from the wrap on now carry the supplied timestamp plus one millisecond, which RFC 9562 §6.2 allows on counter overflow.
- Size limit: a batch takes at most
MaxV7BatchUUIDs (67,108,864). A larger one is refused before anything is allocated. - One batch, not the whole stream: the next batch or call in the same millisecond can sort before the end of the previous batch, at most once per 2^26 UUIDs.
v7 ordering, precisely has all the details.
-
Android for C#, Go and Swift. Each binding gets the core for arm64 and x86_64, built with the NDK and aligned for the 16 KB memory pages that Android 15 and Google Play require.
Language How C# A .NET MAUI app now gets the core on every platform MAUI targets with nothing but the PackageReference. On CoreCLR, the app loadsruntimes/android-{rid}/native/libhyperuuid.sofrom its APK. A Native AOT publish links the core in fromstaticlibs/android-{rid}/libhyperuuid.a.Go Under GOOS=android, cgo linksgo/staticlib/android_{arm64,amd64}, with the NDK's clang asCC.Swift The Swift SDK for Android (Swift 6.3+, API 28+) links the artifact bundle's *-unknown-linux-androidvariants.On every PR, CI runs the C# app (CoreCLR and Native AOT) and the full Go and Swift suites in a 16 KB-page Android emulator. The arm64 APKs are built and checked, but not run.
-
A shared conformance corpus (#31).
corpus/*.jsonpins v5 derivation, the v6 and v7 field layouts, both SQL Server conversions, timestamp reads and inspection. Every binding's suite replays it. The vectors are generated bycorpus/oracle.py, which shares no code with the core, and CI regenerates every vector on each run to catch a hand-edited one.
Fixes
- A batch too large to address is no longer reported as a random-source failure. C#, Go, Java, PHP, Ruby's Fiddle backend and Swift treated that error code as an RNG error. It is now an argument error, as Python and Ruby's Magnus backend already reported it. It can only happen on a 32-bit target.
- Ruby: the Magnus extension survives a compacting garbage collection. Raising
RandomSourceErrororTimestampOutOfRangeErrorafter a compaction could segfault. Both are now pinned when the extension loads.
Upgrade notes
Most of this release is new API. These changes can affect existing code:
- PHP:
Uuid::variant()returns aUuidVariantenum instead of an int.$id->variant()->value === 0b10replaces the old comparison, which is now always false. - Ruby:
Uuid#variantreturns a Symbol (:ncs,:rfc9562,:microsoft,:future) instead of an Integer.variant == :rfc9562replacesvariant == 0b10, which is now always false. - Swift:
UuidGenerator.ErrorgainsbatchTooLarge(count:)andbatchNotAddressable(count:). Aswitchover it with nodefaultneeds both cases. The second replaces a crash on a v6 count pastUInt32.max. - All bindings: a v7 batch larger than
MaxV7Batchnow fails with an argument error. - All bindings except Python:
GetTimestampnow requires an RFC 9562 v6 or v7. A value with a 6 or 7 version nibble but another variant returnsNone/nullinstead of a meaningless timestamp. Python already behaved this way.
Verifying
Every native library, static archive and wasm32-wasip1 archive in this release was built and attested by CI run 37873606161, at commit a623c0c. That includes the new Android archives:
gh attestation verify go/staticlib/android_arm64/libhyperuuid.a \
--repo SkunkWerkx/HyperUuid --signer-repo SkunkWerkx/.githubThe binaries were built before the tag existed. The tagged commit is the one that commits them, and its parent is the commit they were built from. So to pin the source, check against that commit rather than the tag: add --source-digest a623c0cce76569b0cca31a26b09b232319d396d8.
The gems, hyperuuid-wasm included, are attested by this repo's own release.yml, so --repo SkunkWerkx/HyperUuid alone verifies them. The Python wheels verify the same way as the native libraries, or with --owner SkunkWerkx.