[Pitch] Generating UUIDs using RandomNumberGenerators

Hey everyone,

I have a small proposal for a new API on UUID which I wrote a couple of times already and thought it might be worth pitching to include in Foundation.

Below is the proposal. Looking forward to hear what everyone thinks about it!

Generating UUIDs using RandomNumberGenerators

Introduction

UUIDs (Universally Unique IDentifiers) are 128 bits long and are intended to guarantee uniqueness across space and time. This proposal adds APIs to generate UUIDs from Swift's random number generators.

Motivation

UUIDs often need to be randomly generated. This is currently possible by calling the UUID initializer. However, this initializer doesn't allow providing a custom source from which the UUID is generated. Swift's standard library provides a common abstraction for random number generators through the RandomNumberGenerator protocol. Providing methods to generate UUIDs using a RandomNumberGenerator allows developers to customize their source of randomness. An example where this is useful is where a system needs to generate UUIDs using a deterministically seeded random number generator.

Proposed solution

This proposal adds a new static method to the UUID type to generate new random UUIDs using a RandomNumberGenerator.


/// Generates a new random UUID.
///
/// - Parameter generator: The random number generator to use when creating the new random value.
/// - Returns: A random UUID.
@available(FoundationPreview 6.2, *)
public static func random(
    using generator: inout some RandomNumberGenerator
) -> UUID

Source compatibility

The new API is purely additive and ha no impact on the existing API.

Implications on adoption

This feature can be freely adopted and un-adopted in source code with no deployment constraints and without affecting source compatibility.

Alternatives considered

Initializer based random UUID generation

The existing UUID.init() is already generating new random UUIDs and a new UUID(using: &rng) method would be a good alternative to the proposed static method. However, the static random method has precedence on various types such as Int.random.

14 Likes

Would these still be formatted as v4 UUIDs, with the correct bytes set for that?

Yes similar to the UUID.init() this will generate a valid v4 UUID.

2 Likes

From quickly looking at the example attached implementation diff… it looks like we are calling public APIs in the new random(using:) function. If this does not need to access symbols that are not already public… could this instead ship as an extension in a package outside of Foundation?

This pitch intentionally adds this method to Foundation so that it is accessible without adding another dependency. I think it is possible to back deploy this method so it is as available as UUID itself but I leave that up to the folks working on Foundation to decide.

1 Like

This looks good to me.

We don't really have a policy around when to back deploy vs not. I think we generally prefer not to do it, because it simplifies the support matrix. We can think of just what OS it was introduced in, instead of which OS and SDK combination.

1 Like

Great addition! I have refactored some benchmarking code before to use Int's instead of UUIDs to make the runtime more deterministic because Int's support custom RNGs which in turn allowed me to use a deterministic RNG.

Nit: Not sure if this actually compiles as RandomNumberGenerator has newer availability annotations (+2 years).

Did you consider making this an initializer on UUID like UUID(using: &rng) since UUID() is already random?

5 Likes

I updated the proposal to remove the back deployment from it.

I did consider this but there is precedence on many other standard library types to use a random static method such as Int.random. I added an alternative considered section to cover this.

3 Likes

Is it possible to show determinism via a test in the PR using a seedable generator like an LCRNG?

The determinism is really up to the random number generator that is being used. I think adding such seedable generator is a bit out of scope of this proposal but I do agree that it would be great to get one added to the standard library or Foundation. I have previously implemented a PCG based seedable random number generator that I also used for UUID generation.

I just meant in the test suite, not as a part of the proposal. It'd be nice to confirm that it is possible to generate a consistent UUID from a seed.

1 Like

I added a test case showing seeded random number generation here Proposal to generate `UUID`s using `RandomNumberGenerator`s by FranzBusch · Pull Request #1271 · swiftlang/swift-foundation · GitHub

2 Likes