@@ -102,19 +102,44 @@ we may introduce dedicated comparators to accommodate such use cases.
102102
103103We have examined which UUID versions can be correctly generated within the stdlib and which versions are popular.
104104
105- Correctly generating time-based UUIDs is not straightforward. Each new UUID must have a timestamp that is not earlier
106- than the timestamp of the previously generated one. Handling clock rollbacks and system restarts would require storing
107- the last generated UUID in stable storage, as described in the [ RFC] ( https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-generator-states ) .
108- We believe the Standard Library is not an appropriate place to implement such logic.
109- Hence, it was decided not to implement the generation of time-based UUIDs.
105+ Some versions require functionality not available in the Standard library, or not available across all supported platforms.
110106
111- The popularity of each UUID version was also explored. Our findings indicate that in approximately 90 percent of cases
112- users generate a UUID version 4 (random). Excluding time-based UUIDs, this figure rises to over 97 percent.
107+ For example, UUID versions 2, 3, and 5 require support of ` MD5 ` and ` SHA-1 ` hash functions, which are currently unsupported.
108+ Correctly generating time-based UUIDs (versions 1, 6, 7) comes with its own set of challenges as proper generation have to
109+ guarantee monotonicity. Such a guarantee is hard to support without making different trade-offs.
113110
114- Considering this, it was decided to initially provide an API only for generating version 4 (random) UUIDs.
115- These UUIDs are produced using a cryptographically secure pseudorandom number generator (CSPRNG) available
116- on the platform. For more details about the underlying APIs used to produce the random ` Uuid ` in each of the
117- supported targets, refer to the official documentation of the ` Uuid.random() ` function.
111+ In terms of popularity, our findings indicate that in approximately 90 percent of cases users generate a UUID version 4 (random).
112+ Yet another UUID version gaining popularity, especially in domains relative to databases, is version 7.
113+
114+ Hence, it was decided to implement only UUID versions 4 and 7 generation for now, and consider providing generators
115+ for other versions based on demand and technical limitations we have.
116+
117+ Corresponding generator functions were named ` Uuid.generateV4() ` and ` Uuid.generateV7() ` .
118+ For convenience, a ` Uuid.random() ` function is also provided. ` Uuid.random() ` generates V4 UUID and is fully replaceable
119+ with ` Uuid.generateV4() ` , yet its name is more friendly to users who unfamiliar with UUID and only need to generate any
120+ random UUID.
121+
122+ Both UUID version 4 and 7 include a random part that [ should be] ( https://www.rfc-editor.org/rfc/rfc9562.html#name-unguessability )
123+ generated using a cryptographically secure pseudorandom number generator (CSPRNG).
124+ Implementations provided in the Standard library utilize CSPRNGs available on a platform.
125+ For more details about the underlying APIs used to produce the random ` Uuid ` in each of the supported targets,
126+ refer to the official documentation of UUID generation functions.
127+
128+ UUID V7 is a time-based UUID, and as it was mentioned, correctly generating time-based UUIDs is not straightforward.
129+ Each new UUID must have a timestamp that is not earlier than the timestamp of the previously generated one.
130+ [ RFC] ( https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-best-practices ) describes multiple possible trade-offs in its
131+ "UUID Best Practices" section, and for UUID V7 generation we decided to guarantee a monotonicity of generated UUIDs
132+ within an application lifetime. Providing no monotonicity guarantees would compromise the whole point of UUID V7 existence,
133+ and providing monotonicity for a different scope would be hard or impossible.
134+ Please refer to ` Uuid.generateV7() ` documentation for additional details on monotonicity guarantee and how it is implemented.
135+
136+ With all that being said about version 7's monotonicity, there are scenarios requiring creation of such UUIDs corresponding
137+ for some fixed moment in time. For example, inserting events corresponding to past moments of time into a database.
138+
139+ To accommodate generation of such UUIDs we provided additional function - ` Uuid.generateV7NonMonotonicAt(timestamp: Instant) ` .
140+ As the name suggests, this function generates ` Uuid ` for a given ` Instant ` ,
141+ and it does not provide any monotonicity guarantees (meaning that two ` Uuid ` s generated
142+ for the same ` timestamp ` value are not guaranteed to be ordered in any particular way).
118143
119144#### UUID string formats the Kotlin Standard Library should parse and format to
120145
@@ -502,11 +527,26 @@ ByteArray.toHexString(format: HexFormat = HexFormat.Default): String
502527
503528It was discovered that some UUID use-cases may require accepting any of the supported string representations.
504529The ` parse ` function is aimed to fulfill these scenarios,
505- and it will throw ` IllegalStateException ` only if a supplied string's format could not be recognized.
530+ and it will throw ` IllegalArgumentException ` only if a supplied string's format could not be recognized.
506531If any new formats are supported in the future, ` parse ` will start accepting them as well.
507532For scenarios where UUID string representations in an exact format are expected, specialized functions, such as
508533` parseHexDash ` and ` parseHex ` , should be used instead.
509534
535+ #### Invalid inputs handling
536+
537+ In some scenarios strings not matching a UUID format are expected (to some extent), and require specific handling.
538+ To aim with invalid inputs processing, all three ` parse ` -functions have counterparts returning either an
539+ ` Uuid ` , if the input string conformed a format, or ` null ` otherwise.
540+
541+ For consistency with other functions in the Standard library, these functions use ` OrNull ` suffix in their name:
542+
543+ | Function throwing ` IllegalArgumentException ` on invalid input | Function returning ` null ` on invalid input |
544+ | ---------------------------------------------------------------| ------------------------------------------------------|
545+ | ` Uuid.parse(uuidString: String): Uuid ` | ` Uuid.parseOrNull(uuidString: String): Uuid? ` |
546+ | ` Uuid.parseHex(uuidString: String): Uuid ` | ` Uuid.parseHexOrNull(uuidString: String): Uuid? ` |
547+ | ` Uuid.parseHexDash(uuidString: String): Uuid ` | ` Uuid.parseHexDashOrNull(uuidString: String): Uuid? ` |
548+
549+
510550## Dependencies
511551
512552The dependencies of the proposed API:
0 commit comments