summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uuid
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uuid')
-rw-r--r--third_party/rust/uuid/.cargo-checksum.json1
-rw-r--r--third_party/rust/uuid/CODE_OF_CONDUCT.md78
-rw-r--r--third_party/rust/uuid/CONTRIBUTING.md140
-rw-r--r--third_party/rust/uuid/COPYRIGHT8
-rw-r--r--third_party/rust/uuid/Cargo.lock607
-rw-r--r--third_party/rust/uuid/Cargo.toml194
-rw-r--r--third_party/rust/uuid/LICENSE-APACHE201
-rw-r--r--third_party/rust/uuid/LICENSE-MIT26
-rw-r--r--third_party/rust/uuid/README.md99
-rw-r--r--third_party/rust/uuid/benches/format_str.rs66
-rw-r--r--third_party/rust/uuid/benches/parse_str.rs50
-rw-r--r--third_party/rust/uuid/benches/v4.rs11
-rw-r--r--third_party/rust/uuid/examples/random_uuid.rs15
-rw-r--r--third_party/rust/uuid/examples/sortable_uuid.rs15
-rw-r--r--third_party/rust/uuid/examples/uuid_macro.rs19
-rw-r--r--third_party/rust/uuid/examples/windows_guid.rs112
-rw-r--r--third_party/rust/uuid/src/builder.rs905
-rw-r--r--third_party/rust/uuid/src/error.rs172
-rw-r--r--third_party/rust/uuid/src/external.rs6
-rw-r--r--third_party/rust/uuid/src/external/arbitrary_support.rs45
-rw-r--r--third_party/rust/uuid/src/external/serde_support.rs313
-rw-r--r--third_party/rust/uuid/src/external/slog_support.rs37
-rw-r--r--third_party/rust/uuid/src/fmt.rs1030
-rw-r--r--third_party/rust/uuid/src/lib.rs1548
-rw-r--r--third_party/rust/uuid/src/macros.rs99
-rw-r--r--third_party/rust/uuid/src/md5.rs14
-rw-r--r--third_party/rust/uuid/src/parser.rs521
-rw-r--r--third_party/rust/uuid/src/rng.rs39
-rw-r--r--third_party/rust/uuid/src/sha1.rs14
-rw-r--r--third_party/rust/uuid/src/timestamp.rs409
-rw-r--r--third_party/rust/uuid/src/v1.rs175
-rw-r--r--third_party/rust/uuid/src/v3.rs151
-rw-r--r--third_party/rust/uuid/src/v4.rs63
-rw-r--r--third_party/rust/uuid/src/v5.rs162
-rw-r--r--third_party/rust/uuid/src/v6.rs177
-rw-r--r--third_party/rust/uuid/src/v7.rs124
-rw-r--r--third_party/rust/uuid/src/v8.rs57
-rw-r--r--third_party/rust/uuid/tests/macros.rs11
-rw-r--r--third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.rs45
-rw-r--r--third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.stderr197
-rw-r--r--third_party/rust/uuid/tests/ui/compile_pass/renamed.rs11
-rw-r--r--third_party/rust/uuid/tests/ui/compile_pass/valid.rs20
42 files changed, 7987 insertions, 0 deletions
diff --git a/third_party/rust/uuid/.cargo-checksum.json b/third_party/rust/uuid/.cargo-checksum.json
new file mode 100644
index 0000000000..844f3c9ec8
--- /dev/null
+++ b/third_party/rust/uuid/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CODE_OF_CONDUCT.md":"b360d72c37ca9eee599c13d4f7f4b95707c6414634e67befc6a63c1d430d299c","CONTRIBUTING.md":"be72ea4c22c397964f6f44b10562c4ad485dc1cc24b3dcca951e49907439d9ac","COPYRIGHT":"b4b2c0de2a05de3372d5c828128413ce82bb7dba2272487b7729f09cc3d3519d","Cargo.lock":"19bcf0624f45e4aecf6133123fd9b021c7c13576ca59e93e8c9afe9818157bc2","Cargo.toml":"9e9e54f6c8469b7b121a91fcd589c63f1faefea78c90f21e35b667ffe1b019ed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"436bc5a105d8e57dcd8778730f3754f7bf39c14d2f530e4cde4bd2d17a83ec3d","README.md":"923e1deffbdae6ef5c6faca922ac4fb4f0aaadac800a7e28b4a5ab6ecce19d1d","benches/format_str.rs":"f1320973392ce1cd0f0988747c6b4253d3b4ce34cf742dd558efad86f88a81e5","benches/parse_str.rs":"4e9e2f881c609ccdce502a6490e6b5f06cd8954e44f8a1b98d6c0e22f53a15d5","benches/v4.rs":"f59d7180882e12cb09761d941d7bece9690a97f7f29181e2692b38012b6363d7","examples/random_uuid.rs":"9f2282adaa253c803ca58b1ce1c50eb61aaf904a47aec10b777963a6f5ecf9ff","examples/sortable_uuid.rs":"bff06efa3bf3ced72dd4b27d470417bba4887f5110d79cda52688329aa922cea","examples/uuid_macro.rs":"75178c9756da545f94e31f9d322e9a97d8f76a08326f26f2d014088cb42e4ebf","examples/windows_guid.rs":"2e2a21779aec9772a7f0c9ec475b5dc44835640cb104352134986e809f0f7f59","src/builder.rs":"3b3626a94686e8d9a6ffaf2ecfcc3a8710ca93af93f73fba892286744364e919","src/error.rs":"621799694111aab9d6e570290f4d1b341fe6be58d2b3425fa7891ada7575cab7","src/external.rs":"9843b6893a7f07591abbbf8588da36f241563fe71e5e445fa500fdd7b65791e3","src/external/arbitrary_support.rs":"98cf90603e1b1c288847097b9da41d604fd1ddfa8b9e7a235d74c7b36f204777","src/external/serde_support.rs":"1263176b9916bf61fe3ab32140c22e2e757ea29ffff6f5459b1b720acbe2ed9d","src/external/slog_support.rs":"53c6251e424bdc9b6ba35defb4c723d4d34d44053badbf98e1c7c3e7c83fbb5e","src/fmt.rs":"d66a735d72a4c94629dbd18327e7b9c31aa26c0f0017ed67787b3291413f4f8f","src/lib.rs":"055bfe67fcd3a994309becc9d4803a02498f678567045a81c346f73d352f7579","src/macros.rs":"faa4e32837d38107a62402f2119726e007d4acde9abc2177686b25dec2b68039","src/md5.rs":"227a753edc428499108e6f25074bbeb6a80d55f52e18c717a1d88831ae77066a","src/parser.rs":"06c4bfdd6b74db9469a516f7015d328b1f1bd2750f609423c47e308bf98e8706","src/rng.rs":"b9f69610560aa5b5d9b2eaa16fb2239515bd163da126cf5c392e5fb9b0296c3e","src/sha1.rs":"e1a9657e11f1ed1ede33c0655f9c2641059b7c24f17be4ac425c930cc216e019","src/timestamp.rs":"31e4338f6695e2f1e736ba6d958a7ef6200d15e6a58c4229d8b0ca99691900a6","src/v1.rs":"784f8bee32039de761444ef0ed9e70035f8ff7d16beea3ab39bd7b30e0104fea","src/v3.rs":"d797bac7ba71c489a67cb6d0dbd23931fc151fd51994272215edf768ae9b54d2","src/v4.rs":"76d2e5cdc4935f06c6f3b9a34076a6795129698f6887556c4dbe4753dbef56ce","src/v5.rs":"76e4cbb4695ae7904334e089cb549e7c4382ea74045d437d0b4231ce4a64b17d","src/v6.rs":"38717015364f85aad712b27d1ce91ed9f4c9968957424233dad8ceef7ea221f3","src/v7.rs":"86a2db956f6e2d38d20bcc2b64b2f5dc512471717dfedbd21f9c7b07d065a9c0","src/v8.rs":"21a6e05bcfc1fd835df416d40e6403eef951f79abc36c170e4e767fbd197c43f","tests/macros.rs":"5dc3b4a3f0fdcedb47f680f0534d4074bab3a4b26257d8a4f89e9eaad3e6bca7","tests/ui/compile_fail/invalid_parse.rs":"eb81a6a1be99bcce58afa15e2cacab3e7d64f628d3eb31897d2a13feffb2032f","tests/ui/compile_fail/invalid_parse.stderr":"a0d2f080cf64a965028b2044f775d4f75fc541f560ec75baf783231590cd429e","tests/ui/compile_pass/renamed.rs":"f2bd73151e605035051d3aaf572133861457e6d199d0ff7ede748fc6c0f44c7b","tests/ui/compile_pass/valid.rs":"a0cfeeae38dc78151ecc21ad801e56d61993a7e393e0943a6b06f2811e004135"},"package":"1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"} \ No newline at end of file
diff --git a/third_party/rust/uuid/CODE_OF_CONDUCT.md b/third_party/rust/uuid/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..43ff03c15f
--- /dev/null
+++ b/third_party/rust/uuid/CODE_OF_CONDUCT.md
@@ -0,0 +1,78 @@
+# Contributor Covenant Code of Conduct
+
+The latest version of the CODE OF CONDUCT can be found [here].
+
+[here]: https://github.com/uuid-rs/conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+education, socio-economic status, nationality, personal appearance, race,
+religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting one of the project maintainers through details available
+on their GitHub profile. All complaints will be reviewed and investigated and will
+result in a response that is deemed necessary and appropriate to the circumstances.
+The project team is obligated to maintain confidentiality with regard to the
+reporter of an incident. Further details of specific enforcement policies may
+be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
diff --git a/third_party/rust/uuid/CONTRIBUTING.md b/third_party/rust/uuid/CONTRIBUTING.md
new file mode 100644
index 0000000000..1025171af8
--- /dev/null
+++ b/third_party/rust/uuid/CONTRIBUTING.md
@@ -0,0 +1,140 @@
+Contributing to Uuid
+---
+[Contributing to Uuid]: #contributing-to-uuid
+
+Thank you for your interest in contributing to the Uuid Project!
+
+* [Feature Requests](#feature-requests)
+* [Bug Reports](#bug-reports)
+* [Pull Requests](#pull-requests)
+* [Writing Documentation](#writing-documentation)
+* [Issue Triage](#issue-triage)
+* [Out-of-tree Contributions](#out-of-tree-contributions)
+* [Helpful Links](#helpful-links)
+
+For any questions, please make a post on [Discussions] or [users.rust-lang.org][u-r-l-o].
+
+> All contributors need to follow our [Code of Conduct].
+
+[Code of Conduct]: CODE_OF_CONDUCT.md
+
+# Feature Requests
+[Feature Requests]: #feature-requests
+
+The `uuid` crate is stable so features that require breaking changes can't be
+accepted. There are bound to be usability gaps that can be filled with non-breaking
+features though!
+
+If you have the chance, please [search existing issues], as there is a chance
+that someone has already requested your feature.
+
+File your feature request with a descriptive title, as this helps others find
+your request.
+
+You can request your feature by following [this link][Feature Request Link] and
+filling it in.
+
+> We welcome pull requests for your own feature requests. Discussion should stay
+on the relevant issue to make it easier to find.
+
+## Adding new unstable dependencies
+
+If a feature introduces a new unstable dependency then it needs to be private.
+That means traits and types from the unstable library can't be visible in `uuid`'s
+own public API.
+
+To implement unstable traits, see the precedent set by the `zerocopy-unstable` feature.
+It implements a public unstable trait on `Uuid`, but uses the `uuid_unstable` cfg flag.
+
+[Feature Request Link]: https://github.com/uuid-rs/uuid/issues/new?template=Feature_request.md
+
+# Bug Reports
+[Bug Reports]: #bug-reports
+
+While no one likes bugs, they are an unfortunate reality in software. Remember
+we can't fix bugs we don't know about, so don't be shy about reporting.
+
+If you have the chance, please [search existing issues], as there is a chance
+that someone has already reported your error. This isn't strictly needed, as
+sometimes you might not what exactly you are looking for.
+
+File your issue with a descriptive title, as this helps others find your issue.
+
+Reporting a bug is as easy as following [this link][Bug Report Link] and
+filling it in.
+
+Sometimes a backtrace may be needed. In that case, set `RUST_BACKTRACE`
+environment variable to `1`. For example:
+
+```bash
+$ RUST_BACKTRACE=1 cargo build
+```
+
+> We welcome pull requests for your own bug reports, provided they have been
+discussed.
+
+[Bug Report Link]: https://github.com/uuid-rs/uuid/issues/new?template=Bug_report.md
+
+# Pull Requests
+[Pull Requests]: #pull-requests
+
+Pull requests(PRs) are the primary mechanism we use to change Uuid. GitHub itself
+has some [great documentation] on using the Pull Request feature. We use the
+"fork and pull" model described [here][fnp], where contributors push changes to
+their personal fork and create pull requests to bring those changes into the
+source repository.
+
+Unless the changes are fairly minor (like documentation changes or tiny
+patches), we require PRs to relevant issues.
+
+Please open PRs against the `main` branch.
+
+When you feel that the PR is ready, please ping one of the maintainers so
+they can review your changes.
+
+[great documentation]: https://help.github.com/articles/about-pull-requests/
+[fnp]: https://help.github.com/articles/about-collaborative-development-models/
+
+# Writing Documentation
+[Writing Documentation]: #writing-documentation
+
+Documentation is an important part of Uuid. Lackluster or incorrect
+documentation can cause headaches for the users of `uuid`. Therefore,
+improvements to documentation are always welcome.
+
+We follow the documentation style guidelines as given by [RFC 1574].
+
+[RFC 1574]: https://github.com/rust-lang/rfcs/blob/main/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text
+
+# Issue Triage
+[Issue Triage]: #issue-triage
+
+Sometimes, an issue might stay open even after the relevant bug has been fixed.
+Other times, the bug report may become invalid. Or we may just forget about the
+bug.
+
+You can help to go through old bug reports and check if they are still valid.
+You can follow [this link][lrus] to look for issues like this.
+
+[lrus]: https://github.com/uuid-rs/uuid/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
+
+# Fuzzing
+We use [`cargo fuzz`] to fuzz test various parts of `uuid`. See their guide
+for more details on what fuzzing is and how to run the tests yourself.
+
+# Helpful Links
+[Helpful Links]: #helpful-links
+
+For people new to Uuid, and just starting to contribute, or even for more
+seasoned developers, some useful places to look for information are:
+
+* The Wikipedia entry on [Universally Unique Identifier][wiki-uuid].
+* [RFC 4122] which gives the specification of Uuids.
+
+[wiki-uuid]: https://en.wikipedia.org/wiki/Universally_unique_identifier
+[RFC 4122]: https://www.ietf.org/rfc/rfc4122.txt
+
+[u-r-l-o]: https://users.rust-lang.org
+[Discussions]: https://github.com/uuid-rs/uuid/discussions
+[search existing issues]: https://github.com/uuid-rs/uuid/search?q=&type=Issues&utf8=%E2%9C%93
+[`cargo fuzz`]: https://rust-fuzz.github.io/book/cargo-fuzz.html
diff --git a/third_party/rust/uuid/COPYRIGHT b/third_party/rust/uuid/COPYRIGHT
new file mode 100644
index 0000000000..925929c167
--- /dev/null
+++ b/third_party/rust/uuid/COPYRIGHT
@@ -0,0 +1,8 @@
+The Uuid Project is copyright 2013-2014, The Rust Project Developers and
+copyright 2018, The Uuid Developers.
+
+Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+http://www.apache.org/licenses/LICENSE-2.0> or the MIT License <LICENSE-MIT or
+http://opensource.org/licenses/MIT>, at your option. All files in the project
+carrying such notice may not be copied, modified, or distributed except
+according to those terms.
diff --git a/third_party/rust/uuid/Cargo.lock b/third_party/rust/uuid/Cargo.lock
new file mode 100644
index 0000000000..de9b45f293
--- /dev/null
+++ b/third_party/rust/uuid/Cargo.lock
@@ -0,0 +1,607 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "arbitrary"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad"
+
+[[package]]
+name = "atomic"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "basic-toml"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "itoa"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+
+[[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.139"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "md-5"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
+
+[[package]]
+name = "ryu"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
+[[package]]
+name = "serde"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_test"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3611210d2d67e3513204742004d6ac6f589e521861dabb0f649b070eea8bed9e"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
+[[package]]
+name = "slog"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
+
+[[package]]
+name = "syn"
+version = "1.0.107"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "trybuild"
+version = "1.0.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a44da5a6f2164c8e14d3bbc0657d69c5966af9f5f6930d4f600b1f5c4a673413"
+dependencies = [
+ "basic-toml",
+ "glob",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "termcolor",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+
+[[package]]
+name = "uuid"
+version = "1.3.0"
+dependencies = [
+ "arbitrary",
+ "atomic",
+ "bincode",
+ "getrandom",
+ "md-5",
+ "rand",
+ "rustversion",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "serde_test",
+ "sha1_smol",
+ "slog",
+ "trybuild",
+ "uuid-macro-internal",
+ "wasm-bindgen",
+ "wasm-bindgen-test",
+ "windows-sys",
+ "zerocopy",
+]
+
+[[package]]
+name = "uuid-macro-internal"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b300a878652a387d2a0de915bdae8f1a548f0c6d45e072fe2688794b656cc9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
+name = "wasm-bindgen-test"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
+dependencies = [
+ "console_error_panic_hook",
+ "js-sys",
+ "scoped-tls",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-bindgen-test-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-test-macro"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+
+[[package]]
+name = "zerocopy"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/third_party/rust/uuid/Cargo.toml b/third_party/rust/uuid/Cargo.toml
new file mode 100644
index 0000000000..e07072ca46
--- /dev/null
+++ b/third_party/rust/uuid/Cargo.toml
@@ -0,0 +1,194 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "uuid"
+version = "1.3.0"
+authors = [
+ "Ashley Mannix<ashleymannix@live.com.au>",
+ "Christopher Armstrong",
+ "Dylan DPC<dylan.dpc@gmail.com>",
+ "Hunar Roop Kahlon<hunar.roop@gmail.com>",
+]
+exclude = [".github/**"]
+description = "A library to generate and parse UUIDs."
+homepage = "https://github.com/uuid-rs/uuid"
+documentation = "https://docs.rs/uuid"
+readme = "README.md"
+keywords = [
+ "guid",
+ "unique",
+ "uuid",
+]
+categories = [
+ "data-structures",
+ "no-std",
+ "parser-implementations",
+ "wasm",
+]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/uuid-rs/uuid"
+
+[package.metadata.docs.rs]
+rustc-args = [
+ "--cfg",
+ "uuid_unstable",
+]
+rustdoc-args = [
+ "--cfg",
+ "uuid_unstable",
+]
+targets = ["x86_64-unknown-linux-gnu"]
+features = [
+ "serde",
+ "arbitrary",
+ "slog",
+ "v1",
+ "v3",
+ "v4",
+ "v5",
+ "v6",
+ "v7",
+ "v8",
+]
+
+[package.metadata.playground]
+features = [
+ "serde",
+ "v1",
+ "v3",
+ "v4",
+ "v5",
+ "v6",
+ "v7",
+ "v8",
+]
+
+[dependencies.arbitrary]
+version = "1.1.3"
+optional = true
+
+[dependencies.atomic]
+version = "0.5"
+optional = true
+default-features = false
+package = "atomic"
+
+[dependencies.getrandom]
+version = "0.2"
+optional = true
+package = "getrandom"
+
+[dependencies.md-5]
+version = "0.10"
+optional = true
+default-features = false
+package = "md-5"
+
+[dependencies.rand]
+version = "0.8"
+optional = true
+package = "rand"
+
+[dependencies.serde]
+version = "1.0.56"
+optional = true
+default-features = false
+
+[dependencies.sha1_smol]
+version = "1"
+optional = true
+default-features = false
+package = "sha1_smol"
+
+[dependencies.slog]
+version = "2"
+optional = true
+
+[dependencies.uuid-macro-internal]
+version = "1.3.0"
+optional = true
+package = "uuid-macro-internal"
+
+[dependencies.wasm-bindgen]
+version = "0.2"
+optional = true
+package = "wasm-bindgen"
+
+[dependencies.zerocopy]
+version = "0.6"
+optional = true
+
+[dev-dependencies.bincode]
+version = "1.0"
+
+[dev-dependencies.rustversion]
+version = "1"
+
+[dev-dependencies.serde_derive]
+version = "1.0.79"
+
+[dev-dependencies.serde_json]
+version = "1.0"
+
+[dev-dependencies.serde_test]
+version = "1.0.56"
+
+[dev-dependencies.trybuild]
+version = "1.0.52"
+
+[features]
+default = ["std"]
+fast-rng = [
+ "rng",
+ "rand",
+]
+js = [
+ "wasm-bindgen",
+ "getrandom",
+ "getrandom/js",
+]
+macro-diagnostics = ["uuid-macro-internal"]
+md5 = ["md-5"]
+rng = ["getrandom"]
+sha1 = ["sha1_smol"]
+std = []
+v1 = ["atomic"]
+v3 = ["md5"]
+v4 = ["rng"]
+v5 = ["sha1"]
+v6 = ["atomic"]
+v7 = [
+ "atomic",
+ "rng",
+]
+v8 = []
+
+[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen]
+version = "0.2"
+package = "wasm-bindgen"
+
+[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test]
+version = "0.3"
+
+[target."cfg(windows)".dev-dependencies.windows-sys]
+version = "0.45.0"
+features = ["Win32_System_Com"]
+
+[badges.is-it-maintained-issue-resolution]
+repository = "uuid-rs/uuid"
+
+[badges.is-it-maintained-open-issues]
+repository = "uuid-rs/uuid"
+
+[badges.maintenance]
+status = "actively-developed"
diff --git a/third_party/rust/uuid/LICENSE-APACHE b/third_party/rust/uuid/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/uuid/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/uuid/LICENSE-MIT b/third_party/rust/uuid/LICENSE-MIT
new file mode 100644
index 0000000000..99a3078e62
--- /dev/null
+++ b/third_party/rust/uuid/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright (c) 2014 The Rust Project Developers
+Copyright (c) 2018 Ashley Mannix, Christopher Armstrong, Dylan DPC, Hunar Roop Kahlon
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/uuid/README.md b/third_party/rust/uuid/README.md
new file mode 100644
index 0000000000..70a0799191
--- /dev/null
+++ b/third_party/rust/uuid/README.md
@@ -0,0 +1,99 @@
+# `uuid`
+
+[![Latest Version](https://img.shields.io/crates/v/uuid.svg)](https://crates.io/crates/uuid)
+![Minimum rustc version](https://img.shields.io/badge/rustc-1.46.0+-yellow.svg)
+[![Continuous integration](https://github.com/uuid-rs/uuid/actions/workflows/ci.yml/badge.svg)](https://github.com/uuid-rs/uuid/actions/workflows/ci.yml)
+
+Here's an example of a UUID:
+
+```text
+67e55044-10b1-426f-9247-bb680e5fe0c8
+```
+
+A UUID is a unique 128-bit value, stored as 16 octets, and regularly
+formatted as a hex string in five groups. UUIDs are used to assign unique
+identifiers to entities without requiring a central allocating authority.
+
+They are particularly useful in distributed systems, though can be used in
+disparate areas, such as databases and network protocols. Typically a UUID
+is displayed in a readable string form as a sequence of hexadecimal digits,
+separated into groups by hyphens.
+
+The uniqueness property is not strictly guaranteed, however for all
+practical purposes, it can be assumed that an unintentional collision would
+be extremely unlikely.
+
+## Getting started
+
+Add the following to your `Cargo.toml`:
+
+```toml
+[dependencies.uuid]
+version = "1.3.0"
+features = [
+ "v4", # Lets you generate random UUIDs
+ "fast-rng", # Use a faster (but still sufficiently random) RNG
+ "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
+]
+```
+
+When you want a UUID, you can generate one:
+
+```rust
+use uuid::Uuid;
+
+let id = Uuid::new_v4();
+```
+
+If you have a UUID value, you can use its string literal form inline:
+
+```rust
+use uuid::{uuid, Uuid};
+
+const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+```
+
+You can also parse UUIDs without needing any crate features:
+
+```rust
+use uuid::{Uuid, Version};
+
+let my_uuid = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8")?;
+
+assert_eq!(Some(Version::Random), my_uuid.get_version());
+```
+
+If you'd like to parse UUIDs _really_ fast, check out the [`uuid-simd`](https://github.com/nugine/uuid-simd)
+library.
+
+For more details on using `uuid`, [see the library documentation](https://docs.rs/uuid/1.3.0/uuid).
+
+## Minimum Supported Rust Version (MSRV)
+
+The minimum supported Rust version for `uuid` is documented in
+CI. It may be bumped in minor releases as necessary.
+
+## References
+
+* [`uuid` library docs](https://docs.rs/uuid/1.3.0/uuid).
+* [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier).
+* [RFC4122: A Universally Unique IDentifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122).
+
+---
+# License
+
+Licensed under either of
+
+* Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
+* MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
+
+at your option.
+
+
+[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fuuid-rs%2Fuuid.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fuuid-rs%2Fuuid?ref=badge_large)
+
+## Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions. \ No newline at end of file
diff --git a/third_party/rust/uuid/benches/format_str.rs b/third_party/rust/uuid/benches/format_str.rs
new file mode 100644
index 0000000000..fab89297bf
--- /dev/null
+++ b/third_party/rust/uuid/benches/format_str.rs
@@ -0,0 +1,66 @@
+#![feature(test)]
+extern crate test;
+
+use std::io::Write;
+use test::Bencher;
+use uuid::Uuid;
+
+#[bench]
+fn hyphenated(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 36];
+ write!(&mut buffer as &mut [_], "{:x}", uuid.hyphenated()).unwrap();
+ buffer
+ });
+}
+
+#[bench]
+fn simple(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 32];
+ write!(&mut buffer as &mut [_], "{:x}", uuid.simple()).unwrap();
+ buffer
+ })
+}
+
+#[bench]
+fn urn(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 36 + 9];
+ write!(&mut buffer as &mut [_], "{:x}", uuid.urn()).unwrap();
+ buffer
+ })
+}
+
+#[bench]
+fn encode_hyphen(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 36];
+ uuid.hyphenated().encode_lower(&mut buffer);
+ buffer
+ });
+}
+
+#[bench]
+fn encode_simple(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 32];
+ uuid.simple().encode_lower(&mut buffer);
+ buffer
+ })
+}
+
+#[bench]
+fn encode_urn(b: &mut Bencher) {
+ let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();
+ b.iter(|| {
+ let mut buffer = [0_u8; 36 + 9];
+ uuid.urn().encode_lower(&mut buffer);
+ buffer
+ })
+}
diff --git a/third_party/rust/uuid/benches/parse_str.rs b/third_party/rust/uuid/benches/parse_str.rs
new file mode 100644
index 0000000000..e53ba242d3
--- /dev/null
+++ b/third_party/rust/uuid/benches/parse_str.rs
@@ -0,0 +1,50 @@
+#![feature(test)]
+extern crate test;
+
+use test::Bencher;
+use uuid::Uuid;
+
+#[bench]
+fn parse_nil(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("00000000000000000000000000000000"));
+}
+
+#[bench]
+fn parse_nil_hyphenated(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("00000000-0000-0000-0000-000000000000"));
+}
+
+#[bench]
+fn parse_random(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8"));
+}
+
+#[bench]
+fn parse_random_hyphenated(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8"));
+}
+
+#[bench]
+fn parse_urn(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8"));
+}
+
+#[bench]
+fn parse_invalid_len(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4"))
+}
+
+#[bench]
+fn parse_invalid_character(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4"))
+}
+
+#[bench]
+fn parse_invalid_group_len(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("01020304-1112-2122-3132-41424344"));
+}
+
+#[bench]
+fn parse_invalid_groups(b: &mut Bencher) {
+ b.iter(|| Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4"));
+}
diff --git a/third_party/rust/uuid/benches/v4.rs b/third_party/rust/uuid/benches/v4.rs
new file mode 100644
index 0000000000..61c3246b95
--- /dev/null
+++ b/third_party/rust/uuid/benches/v4.rs
@@ -0,0 +1,11 @@
+#![cfg(feature = "v4")]
+#![feature(test)]
+extern crate test;
+
+use test::Bencher;
+use uuid::Uuid;
+
+#[bench]
+fn new_v4(b: &mut Bencher) {
+ b.iter(|| Uuid::new_v4());
+}
diff --git a/third_party/rust/uuid/examples/random_uuid.rs b/third_party/rust/uuid/examples/random_uuid.rs
new file mode 100644
index 0000000000..897071c468
--- /dev/null
+++ b/third_party/rust/uuid/examples/random_uuid.rs
@@ -0,0 +1,15 @@
+//! Generating a random UUID.
+//!
+//! If you enable the `v4` feature you can generate random UUIDs.
+
+#[test]
+#[cfg(feature = "v4")]
+fn generate_random_uuid() {
+ use uuid::Uuid;
+
+ let uuid = Uuid::new_v4();
+
+ assert_eq!(Some(uuid::Version::Random), uuid.get_version());
+}
+
+fn main() {}
diff --git a/third_party/rust/uuid/examples/sortable_uuid.rs b/third_party/rust/uuid/examples/sortable_uuid.rs
new file mode 100644
index 0000000000..dc12812533
--- /dev/null
+++ b/third_party/rust/uuid/examples/sortable_uuid.rs
@@ -0,0 +1,15 @@
+//! Generating a sortable UUID.
+//!
+//! If you enable the `v7` feature you can generate sortable UUIDs.
+
+#[test]
+#[cfg(feature = "v7")]
+fn generate_sortable_uuid() {
+ use uuid::Uuid;
+
+ let uuid = Uuid::now_v7();
+
+ assert_eq!(Some(uuid::Version::SortRand), uuid.get_version());
+}
+
+fn main() {}
diff --git a/third_party/rust/uuid/examples/uuid_macro.rs b/third_party/rust/uuid/examples/uuid_macro.rs
new file mode 100644
index 0000000000..c4ff0484b5
--- /dev/null
+++ b/third_party/rust/uuid/examples/uuid_macro.rs
@@ -0,0 +1,19 @@
+//! Using the `uuid!` macro.
+//!
+//! `uuid!` will parse encoded UUIDs at compile time instead of at runtime.
+//! If you've got a fixed UUID string handy then consider using `uuid!` instead
+//! of `Uuid::parse_str` or `str::parse`.
+//!
+//! If you enable the `macro-diagnostics` feature, you can see much better
+//! error messages.
+
+#[test]
+fn parse_uuid_at_compile_time() {
+ use uuid::uuid;
+
+ let uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+
+ assert_eq!(Some(uuid::Version::Random), uuid.get_version());
+}
+
+fn main() {}
diff --git a/third_party/rust/uuid/examples/windows_guid.rs b/third_party/rust/uuid/examples/windows_guid.rs
new file mode 100644
index 0000000000..6cbc10ed68
--- /dev/null
+++ b/third_party/rust/uuid/examples/windows_guid.rs
@@ -0,0 +1,112 @@
+//! Converting between Windows GUIDs and UUIDs.
+//!
+//! Windows GUIDs are specified as using mixed endianness.
+//! What you get will depend on the source of the GUID.
+//! Functions like `CoCreateGuid` will generate a valid UUID so
+//! the fields will be naturally ordered for `Uuid::from_fields`.
+//! Other GUIDs might need to be passed to `Uuid::from_fields_le`
+//! to have their ordering swapped.
+
+#[test]
+#[cfg(windows)]
+fn guid_to_uuid() {
+ use uuid::Uuid;
+ use windows_sys::core;
+
+ let guid_in = core::GUID {
+ data1: 0x4a35229d,
+ data2: 0x5527,
+ data3: 0x4f30,
+ data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
+ };
+
+ let uuid = Uuid::from_fields(guid_in.data1, guid_in.data2, guid_in.data3, &guid_in.data4);
+
+ let guid_out = {
+ let fields = uuid.as_fields();
+
+ core::GUID {
+ data1: fields.0,
+ data2: fields.1,
+ data3: fields.2,
+ data4: *fields.3,
+ }
+ };
+
+ assert_eq!(
+ (guid_in.data1, guid_in.data2, guid_in.data3, guid_in.data4),
+ (
+ guid_out.data1,
+ guid_out.data2,
+ guid_out.data3,
+ guid_out.data4
+ )
+ );
+}
+
+#[test]
+#[cfg(windows)]
+fn guid_to_uuid_le_encoded() {
+ use uuid::Uuid;
+ use windows_sys::core;
+
+ // A GUID might not be encoded directly as a UUID
+ // If its fields are stored in little-endian order they might
+ // need to be flipped. Whether or not this is necessary depends
+ // on the source of the GUID
+ let guid_in = core::GUID {
+ data1: 0x9d22354a,
+ data2: 0x2755,
+ data3: 0x304f,
+ data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
+ };
+
+ let uuid = Uuid::from_fields_le(guid_in.data1, guid_in.data2, guid_in.data3, &guid_in.data4);
+
+ let guid_out = {
+ let fields = uuid.to_fields_le();
+
+ core::GUID {
+ data1: fields.0,
+ data2: fields.1,
+ data3: fields.2,
+ data4: *fields.3,
+ }
+ };
+
+ assert_eq!(
+ (guid_in.data1, guid_in.data2, guid_in.data3, guid_in.data4),
+ (
+ guid_out.data1,
+ guid_out.data2,
+ guid_out.data3,
+ guid_out.data4
+ )
+ );
+}
+
+#[test]
+#[cfg(windows)]
+fn uuid_from_cocreateguid() {
+ use uuid::{Uuid, Variant, Version};
+ use windows_sys::core;
+ use windows_sys::Win32::System::Com::CoCreateGuid;
+
+ let mut guid = core::GUID {
+ data1: 0,
+ data2: 0,
+ data3: 0,
+ data4: [0u8; 8],
+ };
+
+ unsafe {
+ CoCreateGuid(&mut guid);
+ }
+
+ let uuid = Uuid::from_fields(guid.data1, guid.data2, guid.data3, &guid.data4);
+
+ assert_eq!(Variant::RFC4122, uuid.get_variant());
+ assert_eq!(Some(Version::Random), uuid.get_version());
+}
+
+fn main() {}
diff --git a/third_party/rust/uuid/src/builder.rs b/third_party/rust/uuid/src/builder.rs
new file mode 100644
index 0000000000..60aeb435ea
--- /dev/null
+++ b/third_party/rust/uuid/src/builder.rs
@@ -0,0 +1,905 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A Builder type for [`Uuid`]s.
+//!
+//! [`Uuid`]: ../struct.Uuid.html
+
+use crate::{error::*, timestamp, Bytes, Uuid, Variant, Version};
+
+/// A builder for creating a UUID.
+///
+/// This type is useful if you need to mutate individual fields of a [`Uuid`]
+/// while constructing it. Since the [`Uuid`] type is `Copy`, it doesn't offer
+/// any methods to mutate in place. They live on the `Builder` instead.
+///
+/// The `Builder` type also always exposes APIs to construct [`Uuid`]s for any
+/// version without needing crate features or additional dependencies. It's a
+/// lower-level API than the methods on [`Uuid`].
+///
+/// # Examples
+///
+/// Creating a version 4 UUID from externally generated random bytes:
+///
+/// ```
+/// # use uuid::{Builder, Version, Variant};
+/// # let rng = || [
+/// # 70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90,
+/// # 145, 63, 62,
+/// # ];
+/// let random_bytes = rng();
+///
+/// let uuid = Builder::from_random_bytes(random_bytes).into_uuid();
+///
+/// assert_eq!(Some(Version::Random), uuid.get_version());
+/// assert_eq!(Variant::RFC4122, uuid.get_variant());
+/// ```
+#[allow(missing_copy_implementations)]
+#[derive(Debug)]
+pub struct Builder(Uuid);
+
+impl Uuid {
+ /// The 'nil UUID' (all zeros).
+ ///
+ /// The nil UUID is a special form of UUID that is specified to have all
+ /// 128 bits set to zero.
+ ///
+ /// # References
+ ///
+ /// * [Nil UUID in RFC4122](https://tools.ietf.org/html/rfc4122.html#section-4.1.7)
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let uuid = Uuid::nil();
+ ///
+ /// assert_eq!(
+ /// "00000000-0000-0000-0000-000000000000",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn nil() -> Self {
+ Uuid::from_bytes([0; 16])
+ }
+
+ /// The 'max UUID' (all ones).
+ ///
+ /// The max UUID is a special form of UUID that is specified to have all
+ /// 128 bits set to one.
+ ///
+ /// # References
+ ///
+ /// * [Max UUID in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.4)
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let uuid = Uuid::max();
+ ///
+ /// assert_eq!(
+ /// "ffffffff-ffff-ffff-ffff-ffffffffffff",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ #[cfg(uuid_unstable)]
+ pub const fn max() -> Self {
+ Uuid::from_bytes([0xFF; 16])
+ }
+
+ /// Creates a UUID from four field values.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let d1 = 0xa1a2a3a4;
+ /// let d2 = 0xb1b2;
+ /// let d3 = 0xc1c2;
+ /// let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+ ///
+ /// let uuid = Uuid::from_fields(d1, d2, d3, &d4);
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Uuid {
+ Uuid::from_bytes([
+ (d1 >> 24) as u8,
+ (d1 >> 16) as u8,
+ (d1 >> 8) as u8,
+ d1 as u8,
+ (d2 >> 8) as u8,
+ d2 as u8,
+ (d3 >> 8) as u8,
+ d3 as u8,
+ d4[0],
+ d4[1],
+ d4[2],
+ d4[3],
+ d4[4],
+ d4[5],
+ d4[6],
+ d4[7],
+ ])
+ }
+
+ /// Creates a UUID from four field values in little-endian order.
+ ///
+ /// The bytes in the `d1`, `d2` and `d3` fields will be flipped to convert
+ /// into big-endian order. This is based on the endianness of the UUID,
+ /// rather than the target environment so bytes will be flipped on both
+ /// big and little endian machines.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let d1 = 0xa1a2a3a4;
+ /// let d2 = 0xb1b2;
+ /// let d3 = 0xc1c2;
+ /// let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+ ///
+ /// let uuid = Uuid::from_fields_le(d1, d2, d3, &d4);
+ ///
+ /// assert_eq!(
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_fields_le(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Uuid {
+ Uuid::from_bytes([
+ d1 as u8,
+ (d1 >> 8) as u8,
+ (d1 >> 16) as u8,
+ (d1 >> 24) as u8,
+ (d2) as u8,
+ (d2 >> 8) as u8,
+ d3 as u8,
+ (d3 >> 8) as u8,
+ d4[0],
+ d4[1],
+ d4[2],
+ d4[3],
+ d4[4],
+ d4[5],
+ d4[6],
+ d4[7],
+ ])
+ }
+
+ /// Creates a UUID from a 128bit value.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let v = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8u128;
+ ///
+ /// let uuid = Uuid::from_u128(v);
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_u128(v: u128) -> Self {
+ Uuid::from_bytes([
+ (v >> 120) as u8,
+ (v >> 112) as u8,
+ (v >> 104) as u8,
+ (v >> 96) as u8,
+ (v >> 88) as u8,
+ (v >> 80) as u8,
+ (v >> 72) as u8,
+ (v >> 64) as u8,
+ (v >> 56) as u8,
+ (v >> 48) as u8,
+ (v >> 40) as u8,
+ (v >> 32) as u8,
+ (v >> 24) as u8,
+ (v >> 16) as u8,
+ (v >> 8) as u8,
+ v as u8,
+ ])
+ }
+
+ /// Creates a UUID from a 128bit value in little-endian order.
+ ///
+ /// The entire value will be flipped to convert into big-endian order.
+ /// This is based on the endianness of the UUID, rather than the target
+ /// environment so bytes will be flipped on both big and little endian
+ /// machines.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let v = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8u128;
+ ///
+ /// let uuid = Uuid::from_u128_le(v);
+ ///
+ /// assert_eq!(
+ /// "d8d7d6d5-d4d3-d2d1-c2c1-b2b1a4a3a2a1",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_u128_le(v: u128) -> Self {
+ Uuid::from_bytes([
+ v as u8,
+ (v >> 8) as u8,
+ (v >> 16) as u8,
+ (v >> 24) as u8,
+ (v >> 32) as u8,
+ (v >> 40) as u8,
+ (v >> 48) as u8,
+ (v >> 56) as u8,
+ (v >> 64) as u8,
+ (v >> 72) as u8,
+ (v >> 80) as u8,
+ (v >> 88) as u8,
+ (v >> 96) as u8,
+ (v >> 104) as u8,
+ (v >> 112) as u8,
+ (v >> 120) as u8,
+ ])
+ }
+
+ /// Creates a UUID from two 64bit values.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let hi = 0xa1a2a3a4b1b2c1c2u64;
+ /// let lo = 0xd1d2d3d4d5d6d7d8u64;
+ ///
+ /// let uuid = Uuid::from_u64_pair(hi, lo);
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_u64_pair(high_bits: u64, low_bits: u64) -> Self {
+ Uuid::from_bytes([
+ (high_bits >> 56) as u8,
+ (high_bits >> 48) as u8,
+ (high_bits >> 40) as u8,
+ (high_bits >> 32) as u8,
+ (high_bits >> 24) as u8,
+ (high_bits >> 16) as u8,
+ (high_bits >> 8) as u8,
+ high_bits as u8,
+ (low_bits >> 56) as u8,
+ (low_bits >> 48) as u8,
+ (low_bits >> 40) as u8,
+ (low_bits >> 32) as u8,
+ (low_bits >> 24) as u8,
+ (low_bits >> 16) as u8,
+ (low_bits >> 8) as u8,
+ low_bits as u8,
+ ])
+ }
+
+ /// Creates a UUID using the supplied bytes.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if `b` has any length other than 16.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Uuid::from_slice(&bytes)?;
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn from_slice(b: &[u8]) -> Result<Uuid, Error> {
+ if b.len() != 16 {
+ return Err(Error(ErrorKind::ByteLength { len: b.len() }));
+ }
+
+ let mut bytes: Bytes = [0; 16];
+ bytes.copy_from_slice(b);
+ Ok(Uuid::from_bytes(bytes))
+ }
+
+ /// Creates a UUID using the supplied bytes in little endian order.
+ ///
+ /// The individual fields encoded in the buffer will be flipped.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if `b` has any length other than 16.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Uuid::from_slice_le(&bytes)?;
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8"
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn from_slice_le(b: &[u8]) -> Result<Uuid, Error> {
+ if b.len() != 16 {
+ return Err(Error(ErrorKind::ByteLength { len: b.len() }));
+ }
+
+ let mut bytes: Bytes = [0; 16];
+ bytes.copy_from_slice(b);
+ Ok(Uuid::from_bytes_le(bytes))
+ }
+
+ /// Creates a UUID using the supplied bytes.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Uuid::from_bytes(bytes);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8"
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn from_bytes(bytes: Bytes) -> Uuid {
+ Uuid(bytes)
+ }
+
+ /// Creates a UUID using the supplied bytes in little endian order.
+ ///
+ /// The individual fields encoded in the buffer will be flipped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Uuid::from_bytes_le(bytes);
+ ///
+ /// assert_eq!(
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn from_bytes_le(b: Bytes) -> Uuid {
+ Uuid([
+ b[3], b[2], b[1], b[0], b[5], b[4], b[7], b[6], b[8], b[9], b[10], b[11], b[12], b[13],
+ b[14], b[15],
+ ])
+ }
+
+ /// Creates a reference to a UUID from a reference to the supplied bytes.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Uuid::from_bytes_ref(&bytes);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8"
+ /// );
+ ///
+ /// assert!(std::ptr::eq(
+ /// uuid as *const Uuid as *const u8,
+ /// &bytes as *const [u8; 16] as *const u8,
+ /// ));
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn from_bytes_ref(bytes: &Bytes) -> &Uuid {
+ // SAFETY: `Bytes` and `Uuid` have the same ABI
+ unsafe { &*(bytes as *const Bytes as *const Uuid) }
+ }
+
+ // NOTE: There is no `from_u128_ref` because in little-endian
+ // environments the value isn't properly encoded. Callers would
+ // need to use `.to_be()` themselves.
+}
+
+impl Builder {
+ /// Creates a `Builder` using the supplied bytes.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Builder::from_bytes(bytes).into_uuid();
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_bytes(b: Bytes) -> Self {
+ Builder(Uuid::from_bytes(b))
+ }
+
+ /// Creates a `Builder` using the supplied bytes in little endian order.
+ ///
+ /// The individual fields encoded in the buffer will be flipped.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// # use uuid::{Builder, Uuid};
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Builder::from_bytes_le(bytes).into_uuid();
+ ///
+ /// assert_eq!(
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn from_bytes_le(b: Bytes) -> Self {
+ Builder(Uuid::from_bytes_le(b))
+ }
+
+ /// Creates a `Builder` for a version 1 UUID using the supplied timestamp and node ID.
+ pub const fn from_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Self {
+ Builder(timestamp::encode_rfc4122_timestamp(ticks, counter, node_id))
+ }
+
+ /// Creates a `Builder` for a version 3 UUID using the supplied MD5 hashed bytes.
+ pub const fn from_md5_bytes(md5_bytes: Bytes) -> Self {
+ Builder(Uuid::from_bytes(md5_bytes))
+ .with_variant(Variant::RFC4122)
+ .with_version(Version::Md5)
+ }
+
+ /// Creates a `Builder` for a version 4 UUID using the supplied random bytes.
+ ///
+ /// This method assumes the bytes are already sufficiently random, it will only
+ /// set the appropriate bits for the UUID version and variant.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::{Builder, Variant, Version};
+ /// # let rng = || [
+ /// # 70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90,
+ /// # 145, 63, 62,
+ /// # ];
+ /// let random_bytes = rng();
+ /// let uuid = Builder::from_random_bytes(random_bytes).into_uuid();
+ ///
+ /// assert_eq!(Some(Version::Random), uuid.get_version());
+ /// assert_eq!(Variant::RFC4122, uuid.get_variant());
+ /// ```
+ pub const fn from_random_bytes(random_bytes: Bytes) -> Self {
+ Builder(Uuid::from_bytes(random_bytes))
+ .with_variant(Variant::RFC4122)
+ .with_version(Version::Random)
+ }
+
+ /// Creates a `Builder` for a version 5 UUID using the supplied SHA-1 hashed bytes.
+ ///
+ /// This method assumes the bytes are already a SHA-1 hash, it will only set the appropriate
+ /// bits for the UUID version and variant.
+ pub const fn from_sha1_bytes(sha1_bytes: Bytes) -> Self {
+ Builder(Uuid::from_bytes(sha1_bytes))
+ .with_variant(Variant::RFC4122)
+ .with_version(Version::Sha1)
+ }
+
+ /// Creates a `Builder` for a version 6 UUID using the supplied timestamp and node ID.
+ ///
+ /// This method will encode the ticks, counter, and node ID in a sortable UUID.
+ #[cfg(uuid_unstable)]
+ pub const fn from_sorted_rfc4122_timestamp(
+ ticks: u64,
+ counter: u16,
+ node_id: &[u8; 6],
+ ) -> Self {
+ Builder(timestamp::encode_sorted_rfc4122_timestamp(
+ ticks, counter, node_id,
+ ))
+ }
+
+ /// Creates a `Builder` for a version 7 UUID using the supplied Unix timestamp and random bytes.
+ ///
+ /// This method assumes the bytes are already sufficiently random.
+ ///
+ /// # Examples
+ ///
+ /// Creating a UUID using the current system timestamp:
+ ///
+ /// ```
+ /// # use std::convert::TryInto;
+ /// use std::time::{Duration, SystemTime};
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// # use uuid::{Builder, Uuid, Variant, Version, Timestamp, NoContext};
+ /// # let rng = || [
+ /// # 70, 235, 208, 238, 14, 109, 67, 201, 185, 13
+ /// # ];
+ /// let ts = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
+ ///
+ /// let random_bytes = rng();
+ ///
+ /// let uuid = Builder::from_unix_timestamp_millis(ts.as_millis().try_into()?, &random_bytes).into_uuid();
+ ///
+ /// assert_eq!(Some(Version::SortRand), uuid.get_version());
+ /// assert_eq!(Variant::RFC4122, uuid.get_variant());
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[cfg(uuid_unstable)]
+ pub const fn from_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Self {
+ Builder(timestamp::encode_unix_timestamp_millis(
+ millis,
+ random_bytes,
+ ))
+ }
+
+ /// Creates a `Builder` for a version 8 UUID using the supplied user-defined bytes.
+ ///
+ /// This method won't interpret the given bytes in any way, except to set the appropriate
+ /// bits for the UUID version and variant.
+ #[cfg(uuid_unstable)]
+ pub const fn from_custom_bytes(custom_bytes: Bytes) -> Self {
+ Builder::from_bytes(custom_bytes)
+ .with_variant(Variant::RFC4122)
+ .with_version(Version::Custom)
+ }
+
+ /// Creates a `Builder` using the supplied bytes.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if `b` has any length other than 16.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Builder::from_slice(&bytes)?.into_uuid();
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn from_slice(b: &[u8]) -> Result<Self, Error> {
+ Ok(Builder(Uuid::from_slice(b)?))
+ }
+
+ /// Creates a `Builder` using the supplied bytes in little endian order.
+ ///
+ /// The individual fields encoded in the buffer will be flipped.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if `b` has any length other than 16.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ ///
+ /// let uuid = Builder::from_slice_le(&bytes)?.into_uuid();
+ ///
+ /// assert_eq!(
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn from_slice_le(b: &[u8]) -> Result<Self, Error> {
+ Ok(Builder(Uuid::from_slice_le(b)?))
+ }
+
+ /// Creates a `Builder` from four field values.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let d1 = 0xa1a2a3a4;
+ /// let d2 = 0xb1b2;
+ /// let d3 = 0xc1c2;
+ /// let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+ ///
+ /// let uuid = Builder::from_fields(d1, d2, d3, &d4).into_uuid();
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8"
+ /// );
+ /// ```
+ pub const fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
+ Builder(Uuid::from_fields(d1, d2, d3, d4))
+ }
+
+ /// Creates a `Builder` from four field values.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let d1 = 0xa1a2a3a4;
+ /// let d2 = 0xb1b2;
+ /// let d3 = 0xc1c2;
+ /// let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+ ///
+ /// let uuid = Builder::from_fields_le(d1, d2, d3, &d4).into_uuid();
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "a4a3a2a1-b2b1-c2c1-d1d2-d3d4d5d6d7d8"
+ /// );
+ /// ```
+ pub const fn from_fields_le(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
+ Builder(Uuid::from_fields_le(d1, d2, d3, d4))
+ }
+
+ /// Creates a `Builder` from a 128bit value.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let v = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8u128;
+ ///
+ /// let uuid = Builder::from_u128(v).into_uuid();
+ ///
+ /// assert_eq!(
+ /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_u128(v: u128) -> Self {
+ Builder(Uuid::from_u128(v))
+ }
+
+ /// Creates a UUID from a 128bit value in little-endian order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let v = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8u128;
+ ///
+ /// let uuid = Builder::from_u128_le(v).into_uuid();
+ ///
+ /// assert_eq!(
+ /// "d8d7d6d5-d4d3-d2d1-c2c1-b2b1a4a3a2a1",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn from_u128_le(v: u128) -> Self {
+ Builder(Uuid::from_u128_le(v))
+ }
+
+ /// Creates a `Builder` with an initial [`Uuid::nil`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let uuid = Builder::nil().into_uuid();
+ ///
+ /// assert_eq!(
+ /// "00000000-0000-0000-0000-000000000000",
+ /// uuid.hyphenated().to_string(),
+ /// );
+ /// ```
+ pub const fn nil() -> Self {
+ Builder(Uuid::nil())
+ }
+
+ /// Specifies the variant of the UUID.
+ pub fn set_variant(&mut self, v: Variant) -> &mut Self {
+ *self = Builder(self.0).with_variant(v);
+ self
+ }
+
+ /// Specifies the variant of the UUID.
+ pub const fn with_variant(mut self, v: Variant) -> Self {
+ let byte = (self.0).0[8];
+
+ (self.0).0[8] = match v {
+ Variant::NCS => byte & 0x7f,
+ Variant::RFC4122 => (byte & 0x3f) | 0x80,
+ Variant::Microsoft => (byte & 0x1f) | 0xc0,
+ Variant::Future => byte | 0xe0,
+ };
+
+ self
+ }
+
+ /// Specifies the version number of the UUID.
+ pub fn set_version(&mut self, v: Version) -> &mut Self {
+ *self = Builder(self.0).with_version(v);
+ self
+ }
+
+ /// Specifies the version number of the UUID.
+ pub const fn with_version(mut self, v: Version) -> Self {
+ (self.0).0[6] = ((self.0).0[6] & 0x0f) | ((v as u8) << 4);
+
+ self
+ }
+
+ /// Get a reference to the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let builder = Builder::nil();
+ ///
+ /// let uuid1 = builder.as_uuid();
+ /// let uuid2 = builder.as_uuid();
+ ///
+ /// assert_eq!(uuid1, uuid2);
+ /// ```
+ pub const fn as_uuid(&self) -> &Uuid {
+ &self.0
+ }
+
+ /// Convert the builder into a [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Builder;
+ /// let uuid = Builder::nil().into_uuid();
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "00000000-0000-0000-0000-000000000000"
+ /// );
+ /// ```
+ pub const fn into_uuid(self) -> Uuid {
+ self.0
+ }
+}
diff --git a/third_party/rust/uuid/src/error.rs b/third_party/rust/uuid/src/error.rs
new file mode 100644
index 0000000000..e9aecbf82c
--- /dev/null
+++ b/third_party/rust/uuid/src/error.rs
@@ -0,0 +1,172 @@
+use crate::std::fmt;
+
+/// A general error that can occur when working with UUIDs.
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Error(pub(crate) ErrorKind);
+
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub(crate) enum ErrorKind {
+ /// Invalid character in the [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ Char { character: char, index: usize },
+ /// A simple [`Uuid`] didn't contain 32 characters.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ SimpleLength { len: usize },
+ /// A byte array didn't contain 16 bytes
+ ByteLength { len: usize },
+ /// A hyphenated [`Uuid`] didn't contain 5 groups
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ GroupCount { count: usize },
+ /// A hyphenated [`Uuid`] had a group that wasn't the right length
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ GroupLength {
+ group: usize,
+ len: usize,
+ index: usize,
+ },
+ /// The input was not a valid UTF8 string
+ InvalidUTF8,
+ /// Some other error occurred.
+ Other,
+}
+
+/// A string that is guaranteed to fail to parse to a [`Uuid`].
+///
+/// This type acts as a lightweight error indicator, suggesting
+/// that the string cannot be parsed but offering no error
+/// details. To get details, use `InvalidUuid::into_err`.
+///
+/// [`Uuid`]: ../struct.Uuid.html
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct InvalidUuid<'a>(pub(crate) &'a [u8]);
+
+impl<'a> InvalidUuid<'a> {
+ /// Converts the lightweight error type into detailed diagnostics.
+ pub fn into_err(self) -> Error {
+ // Check whether or not the input was ever actually a valid UTF8 string
+ let input_str = match std::str::from_utf8(self.0) {
+ Ok(s) => s,
+ Err(_) => return Error(ErrorKind::InvalidUTF8),
+ };
+
+ let (uuid_str, offset, simple) = match input_str.as_bytes() {
+ [b'{', s @ .., b'}'] => (s, 1, false),
+ [b'u', b'r', b'n', b':', b'u', b'u', b'i', b'd', b':', s @ ..] => {
+ (s, "urn:uuid:".len(), false)
+ }
+ s => (s, 0, true),
+ };
+
+ let mut hyphen_count = 0;
+ let mut group_bounds = [0; 4];
+
+ // SAFETY: the byte array came from a valid utf8 string,
+ // and is aligned along char boundaries.
+ let uuid_str = unsafe { std::str::from_utf8_unchecked(uuid_str) };
+
+ for (index, character) in uuid_str.char_indices() {
+ let byte = character as u8;
+ if character as u32 - byte as u32 > 0 {
+ // Multibyte char
+ return Error(ErrorKind::Char {
+ character,
+ index: index + offset + 1,
+ });
+ } else if byte == b'-' {
+ // While we search, also count group breaks
+ if hyphen_count < 4 {
+ group_bounds[hyphen_count] = index;
+ }
+ hyphen_count += 1;
+ } else if !matches!(byte, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F') {
+ // Non-hex char
+ return Error(ErrorKind::Char {
+ character: byte as char,
+ index: index + offset + 1,
+ });
+ }
+ }
+
+ if hyphen_count == 0 && simple {
+ // This means that we tried and failed to parse a simple uuid.
+ // Since we verified that all the characters are valid, this means
+ // that it MUST have an invalid length.
+ Error(ErrorKind::SimpleLength {
+ len: input_str.len(),
+ })
+ } else if hyphen_count != 4 {
+ // We tried to parse a hyphenated variant, but there weren't
+ // 5 groups (4 hyphen splits).
+ Error(ErrorKind::GroupCount {
+ count: hyphen_count + 1,
+ })
+ } else {
+ // There are 5 groups, one of them has an incorrect length
+ const BLOCK_STARTS: [usize; 5] = [0, 9, 14, 19, 24];
+ for i in 0..4 {
+ if group_bounds[i] != BLOCK_STARTS[i + 1] - 1 {
+ return Error(ErrorKind::GroupLength {
+ group: i,
+ len: group_bounds[i] - BLOCK_STARTS[i],
+ index: offset + BLOCK_STARTS[i] + 1,
+ });
+ }
+ }
+
+ // The last group must be too long
+ Error(ErrorKind::GroupLength {
+ group: 4,
+ len: input_str.len() - BLOCK_STARTS[4],
+ index: offset + BLOCK_STARTS[4] + 1,
+ })
+ }
+ }
+}
+
+// NOTE: This impl is part of the public API. Breaking changes to it should be carefully considered
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {
+ ErrorKind::Char {
+ character, index, ..
+ } => {
+ write!(f, "invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `{}` at {}", character, index)
+ }
+ ErrorKind::SimpleLength { len } => {
+ write!(
+ f,
+ "invalid length: expected length 32 for simple format, found {}",
+ len
+ )
+ }
+ ErrorKind::ByteLength { len } => {
+ write!(f, "invalid length: expected 16 bytes, found {}", len)
+ }
+ ErrorKind::GroupCount { count } => {
+ write!(f, "invalid group count: expected 5, found {}", count)
+ }
+ ErrorKind::GroupLength { group, len, .. } => {
+ let expected = [8, 4, 4, 4, 12][group];
+ write!(
+ f,
+ "invalid group length in group {}: expected {}, found {}",
+ group, expected, len
+ )
+ }
+ ErrorKind::InvalidUTF8 => write!(f, "non-UTF8 input"),
+ ErrorKind::Other => write!(f, "failed to parse a UUID"),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+mod std_support {
+ use super::*;
+ use crate::std::error;
+
+ impl error::Error for Error {}
+}
diff --git a/third_party/rust/uuid/src/external.rs b/third_party/rust/uuid/src/external.rs
new file mode 100644
index 0000000000..219a9236e5
--- /dev/null
+++ b/third_party/rust/uuid/src/external.rs
@@ -0,0 +1,6 @@
+#[cfg(feature = "arbitrary")]
+pub(crate) mod arbitrary_support;
+#[cfg(feature = "serde")]
+pub(crate) mod serde_support;
+#[cfg(feature = "slog")]
+pub(crate) mod slog_support;
diff --git a/third_party/rust/uuid/src/external/arbitrary_support.rs b/third_party/rust/uuid/src/external/arbitrary_support.rs
new file mode 100644
index 0000000000..38cce7c73e
--- /dev/null
+++ b/third_party/rust/uuid/src/external/arbitrary_support.rs
@@ -0,0 +1,45 @@
+use crate::{std::convert::TryInto, Builder, Uuid};
+
+use arbitrary::{Arbitrary, Unstructured};
+
+impl Arbitrary<'_> for Uuid {
+ fn arbitrary(u: &mut Unstructured<'_>) -> arbitrary::Result<Self> {
+ let b = u
+ .bytes(16)?
+ .try_into()
+ .map_err(|_| arbitrary::Error::NotEnoughData)?;
+
+ Ok(Builder::from_random_bytes(b).into_uuid())
+ }
+
+ fn size_hint(depth: usize) -> (usize, Option<usize>) {
+ (16, Some(16))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use crate::{Variant, Version};
+
+ #[test]
+ fn test_arbitrary() {
+ let mut bytes = Unstructured::new(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+ let uuid = Uuid::arbitrary(&mut bytes).unwrap();
+
+ assert_eq!(Some(Version::Random), uuid.get_version());
+ assert_eq!(Variant::RFC4122, uuid.get_variant());
+ }
+
+ #[test]
+ fn test_arbitrary_empty() {
+ let mut bytes = Unstructured::new(&[]);
+
+ // Ensure we don't panic when building an arbitrary `Uuid`
+ let uuid = Uuid::arbitrary(&mut bytes);
+
+ assert!(uuid.is_err());
+ }
+}
diff --git a/third_party/rust/uuid/src/external/serde_support.rs b/third_party/rust/uuid/src/external/serde_support.rs
new file mode 100644
index 0000000000..5228daf15f
--- /dev/null
+++ b/third_party/rust/uuid/src/external/serde_support.rs
@@ -0,0 +1,313 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+ error::*,
+ fmt::{Braced, Hyphenated, Simple, Urn},
+ std::fmt,
+ Uuid,
+};
+use serde::{
+ de::{self, Error as _},
+ Deserialize, Deserializer, Serialize, Serializer,
+};
+
+impl Serialize for Uuid {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ if serializer.is_human_readable() {
+ serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer()))
+ } else {
+ serializer.serialize_bytes(self.as_bytes())
+ }
+ }
+}
+
+impl Serialize for Hyphenated {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
+ }
+}
+
+impl Serialize for Simple {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
+ }
+}
+
+impl Serialize for Urn {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
+ }
+}
+
+impl Serialize for Braced {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
+ }
+}
+
+impl<'de> Deserialize<'de> for Uuid {
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ fn de_error<E: de::Error>(e: Error) -> E {
+ E::custom(format_args!("UUID parsing failed: {}", e))
+ }
+
+ if deserializer.is_human_readable() {
+ struct UuidVisitor;
+
+ impl<'vi> de::Visitor<'vi> for UuidVisitor {
+ type Value = Uuid;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(formatter, "a UUID string")
+ }
+
+ fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
+ value.parse::<Uuid>().map_err(de_error)
+ }
+
+ fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
+ Uuid::from_slice(value).map_err(de_error)
+ }
+
+ fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
+ where
+ A: de::SeqAccess<'vi>,
+ {
+ #[rustfmt::skip]
+ let bytes = [
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(16, &self)) },
+ ];
+
+ Ok(Uuid::from_bytes(bytes))
+ }
+ }
+
+ deserializer.deserialize_str(UuidVisitor)
+ } else {
+ struct UuidBytesVisitor;
+
+ impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
+ type Value = Uuid;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(formatter, "bytes")
+ }
+
+ fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
+ Uuid::from_slice(value).map_err(de_error)
+ }
+ }
+
+ deserializer.deserialize_bytes(UuidBytesVisitor)
+ }
+ }
+}
+
+pub mod compact {
+ //! Serialize a [`Uuid`] as a `[u8; 16]`.
+ //!
+ //! [`Uuid`]: ../../struct.Uuid.html
+
+ /// Serialize from a [`Uuid`] as a `[u8; 16]`
+ ///
+ /// [`Uuid`]: ../../struct.Uuid.html
+ pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serde::Serialize::serialize(u.as_bytes(), serializer)
+ }
+
+ /// Deserialize a `[u8; 16]` as a [`Uuid`]
+ ///
+ /// [`Uuid`]: ../../struct.Uuid.html
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?;
+
+ Ok(crate::Uuid::from_bytes(bytes))
+ }
+
+ #[cfg(test)]
+ mod tests {
+ use serde_derive::*;
+ use serde_test::{self, Configure};
+
+ #[test]
+ fn test_serialize_compact() {
+ #[derive(Serialize, Debug, Deserialize, PartialEq)]
+ struct UuidContainer {
+ #[serde(with = "crate::serde::compact")]
+ u: crate::Uuid,
+ }
+
+ let uuid_bytes = b"F9168C5E-CEB2-4F";
+ let container = UuidContainer {
+ u: crate::Uuid::from_slice(uuid_bytes).unwrap(),
+ };
+
+ // more complex because of the struct wrapping the actual UUID
+ // serialization
+ serde_test::assert_tokens(
+ &container.compact(),
+ &[
+ serde_test::Token::Struct {
+ name: "UuidContainer",
+ len: 1,
+ },
+ serde_test::Token::Str("u"),
+ serde_test::Token::Tuple { len: 16 },
+ serde_test::Token::U8(uuid_bytes[0]),
+ serde_test::Token::U8(uuid_bytes[1]),
+ serde_test::Token::U8(uuid_bytes[2]),
+ serde_test::Token::U8(uuid_bytes[3]),
+ serde_test::Token::U8(uuid_bytes[4]),
+ serde_test::Token::U8(uuid_bytes[5]),
+ serde_test::Token::U8(uuid_bytes[6]),
+ serde_test::Token::U8(uuid_bytes[7]),
+ serde_test::Token::U8(uuid_bytes[8]),
+ serde_test::Token::U8(uuid_bytes[9]),
+ serde_test::Token::U8(uuid_bytes[10]),
+ serde_test::Token::U8(uuid_bytes[11]),
+ serde_test::Token::U8(uuid_bytes[12]),
+ serde_test::Token::U8(uuid_bytes[13]),
+ serde_test::Token::U8(uuid_bytes[14]),
+ serde_test::Token::U8(uuid_bytes[15]),
+ serde_test::Token::TupleEnd,
+ serde_test::Token::StructEnd,
+ ],
+ )
+ }
+ }
+}
+
+#[cfg(test)]
+mod serde_tests {
+ use super::*;
+
+ use serde_test::{Compact, Configure, Readable, Token};
+
+ #[test]
+ fn test_serialize_readable_string() {
+ let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
+ let u = Uuid::parse_str(uuid_str).unwrap();
+ serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
+ }
+
+ #[test]
+ fn test_deserialize_readable_compact() {
+ let uuid_bytes = b"F9168C5E-CEB2-4F";
+ let u = Uuid::from_slice(uuid_bytes).unwrap();
+
+ serde_test::assert_de_tokens(
+ &u.readable(),
+ &[
+ serde_test::Token::Tuple { len: 16 },
+ serde_test::Token::U8(uuid_bytes[0]),
+ serde_test::Token::U8(uuid_bytes[1]),
+ serde_test::Token::U8(uuid_bytes[2]),
+ serde_test::Token::U8(uuid_bytes[3]),
+ serde_test::Token::U8(uuid_bytes[4]),
+ serde_test::Token::U8(uuid_bytes[5]),
+ serde_test::Token::U8(uuid_bytes[6]),
+ serde_test::Token::U8(uuid_bytes[7]),
+ serde_test::Token::U8(uuid_bytes[8]),
+ serde_test::Token::U8(uuid_bytes[9]),
+ serde_test::Token::U8(uuid_bytes[10]),
+ serde_test::Token::U8(uuid_bytes[11]),
+ serde_test::Token::U8(uuid_bytes[12]),
+ serde_test::Token::U8(uuid_bytes[13]),
+ serde_test::Token::U8(uuid_bytes[14]),
+ serde_test::Token::U8(uuid_bytes[15]),
+ serde_test::Token::TupleEnd,
+ ],
+ );
+ }
+
+ #[test]
+ fn test_deserialize_readable_bytes() {
+ let uuid_bytes = b"F9168C5E-CEB2-4F";
+ let u = Uuid::from_slice(uuid_bytes).unwrap();
+
+ serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
+ }
+
+ #[test]
+ fn test_serialize_hyphenated() {
+ let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
+ let u = Uuid::parse_str(uuid_str).unwrap();
+ serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
+ }
+
+ #[test]
+ fn test_serialize_simple() {
+ let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
+ let u = Uuid::parse_str(uuid_str).unwrap();
+ serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
+ }
+
+ #[test]
+ fn test_serialize_urn() {
+ let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
+ let u = Uuid::parse_str(uuid_str).unwrap();
+ serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
+ }
+
+ #[test]
+ fn test_serialize_braced() {
+ let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
+ let u = Uuid::parse_str(uuid_str).unwrap();
+ serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
+ }
+
+ #[test]
+ fn test_serialize_non_human_readable() {
+ let uuid_bytes = b"F9168C5E-CEB2-4F";
+ let u = Uuid::from_slice(uuid_bytes).unwrap();
+ serde_test::assert_tokens(
+ &u.compact(),
+ &[serde_test::Token::Bytes(&[
+ 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
+ ])],
+ );
+ }
+
+ #[test]
+ fn test_de_failure() {
+ serde_test::assert_de_tokens_error::<Readable<Uuid>>(
+ &[Token::Str("hello_world")],
+ "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
+ );
+
+ serde_test::assert_de_tokens_error::<Compact<Uuid>>(
+ &[Token::Bytes(b"hello_world")],
+ "UUID parsing failed: invalid length: expected 16 bytes, found 11",
+ );
+ }
+}
diff --git a/third_party/rust/uuid/src/external/slog_support.rs b/third_party/rust/uuid/src/external/slog_support.rs
new file mode 100644
index 0000000000..2d6e817ba2
--- /dev/null
+++ b/third_party/rust/uuid/src/external/slog_support.rs
@@ -0,0 +1,37 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::Uuid;
+
+impl slog::Value for Uuid {
+ fn serialize(
+ &self,
+ _: &slog::Record<'_>,
+ key: slog::Key,
+ serializer: &mut dyn slog::Serializer,
+ ) -> Result<(), slog::Error> {
+ serializer.emit_arguments(key, &format_args!("{}", self))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::new;
+
+ use slog::{self, crit, Drain};
+
+ #[test]
+ fn test_slog_kv() {
+ let root = slog::Logger::root(slog::Discard.fuse(), slog::o!());
+ let u1 = new();
+ crit!(root, "test"; "u1" => u1);
+ }
+}
diff --git a/third_party/rust/uuid/src/fmt.rs b/third_party/rust/uuid/src/fmt.rs
new file mode 100644
index 0000000000..92b40422a3
--- /dev/null
+++ b/third_party/rust/uuid/src/fmt.rs
@@ -0,0 +1,1030 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Adapters for alternative string formats.
+
+use crate::{
+ std::{borrow::Borrow, fmt, ptr, str},
+ Uuid, Variant,
+};
+
+impl std::fmt::Debug for Uuid {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(self, f)
+ }
+}
+
+impl fmt::Display for Uuid {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(self, f)
+ }
+}
+
+impl fmt::Display for Variant {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ Variant::NCS => write!(f, "NCS"),
+ Variant::RFC4122 => write!(f, "RFC4122"),
+ Variant::Microsoft => write!(f, "Microsoft"),
+ Variant::Future => write!(f, "Future"),
+ }
+ }
+}
+
+impl fmt::LowerHex for Uuid {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(self.as_hyphenated(), f)
+ }
+}
+
+impl fmt::UpperHex for Uuid {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::UpperHex::fmt(self.as_hyphenated(), f)
+ }
+}
+
+/// Format a [`Uuid`] as a hyphenated string, like
+/// `67e55044-10b1-426f-9247-bb680e5fe0c8`.
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+pub struct Hyphenated(Uuid);
+
+/// Format a [`Uuid`] as a simple string, like
+/// `67e5504410b1426f9247bb680e5fe0c8`.
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+pub struct Simple(Uuid);
+
+/// Format a [`Uuid`] as a URN string, like
+/// `urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8`.
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+pub struct Urn(Uuid);
+
+/// Format a [`Uuid`] as a braced hyphenated string, like
+/// `{67e55044-10b1-426f-9247-bb680e5fe0c8}`.
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+pub struct Braced(Uuid);
+
+impl Uuid {
+ /// Get a [`Hyphenated`] formatter.
+ #[inline]
+ pub const fn hyphenated(self) -> Hyphenated {
+ Hyphenated(self)
+ }
+
+ /// Get a borrowed [`Hyphenated`] formatter.
+ #[inline]
+ pub fn as_hyphenated(&self) -> &Hyphenated {
+ // SAFETY: `Uuid` and `Hyphenated` have the same ABI
+ unsafe { &*(self as *const Uuid as *const Hyphenated) }
+ }
+
+ /// Get a [`Simple`] formatter.
+ #[inline]
+ pub const fn simple(self) -> Simple {
+ Simple(self)
+ }
+
+ /// Get a borrowed [`Simple`] formatter.
+ #[inline]
+ pub fn as_simple(&self) -> &Simple {
+ // SAFETY: `Uuid` and `Simple` have the same ABI
+ unsafe { &*(self as *const Uuid as *const Simple) }
+ }
+
+ /// Get a [`Urn`] formatter.
+ #[inline]
+ pub const fn urn(self) -> Urn {
+ Urn(self)
+ }
+
+ /// Get a borrowed [`Urn`] formatter.
+ #[inline]
+ pub fn as_urn(&self) -> &Urn {
+ // SAFETY: `Uuid` and `Urn` have the same ABI
+ unsafe { &*(self as *const Uuid as *const Urn) }
+ }
+
+ /// Get a [`Braced`] formatter.
+ #[inline]
+ pub const fn braced(self) -> Braced {
+ Braced(self)
+ }
+
+ /// Get a borrowed [`Braced`] formatter.
+ #[inline]
+ pub fn as_braced(&self) -> &Braced {
+ // SAFETY: `Uuid` and `Braced` have the same ABI
+ unsafe { &*(self as *const Uuid as *const Braced) }
+ }
+}
+
+const UPPER: [u8; 16] = [
+ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
+];
+const LOWER: [u8; 16] = [
+ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
+];
+
+#[inline]
+const fn format_simple(src: &[u8; 16], upper: bool) -> [u8; 32] {
+ let lut = if upper { &UPPER } else { &LOWER };
+ let mut dst = [0; 32];
+ let mut i = 0;
+ while i < 16 {
+ let x = src[i];
+ dst[i * 2] = lut[(x >> 4) as usize];
+ dst[i * 2 + 1] = lut[(x & 0x0f) as usize];
+ i += 1;
+ }
+ dst
+}
+
+#[inline]
+const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
+ let lut = if upper { &UPPER } else { &LOWER };
+ let groups = [(0, 8), (9, 13), (14, 18), (19, 23), (24, 36)];
+ let mut dst = [0; 36];
+
+ let mut group_idx = 0;
+ let mut i = 0;
+ while group_idx < 5 {
+ let (start, end) = groups[group_idx];
+ let mut j = start;
+ while j < end {
+ let x = src[i];
+ i += 1;
+
+ dst[j] = lut[(x >> 4) as usize];
+ dst[j + 1] = lut[(x & 0x0f) as usize];
+ j += 2;
+ }
+ if group_idx < 4 {
+ dst[end] = b'-';
+ }
+ group_idx += 1;
+ }
+ dst
+}
+
+#[inline]
+fn encode_simple<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
+ let buf = &mut buffer[..Simple::LENGTH];
+ let dst = buf.as_mut_ptr();
+
+ // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
+ // SAFETY: The encoded buffer is ASCII encoded
+ unsafe {
+ ptr::write(dst.cast(), format_simple(src, upper));
+ str::from_utf8_unchecked_mut(buf)
+ }
+}
+
+#[inline]
+fn encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
+ let buf = &mut buffer[..Hyphenated::LENGTH];
+ let dst = buf.as_mut_ptr();
+
+ // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
+ // SAFETY: The encoded buffer is ASCII encoded
+ unsafe {
+ ptr::write(dst.cast(), format_hyphenated(src, upper));
+ str::from_utf8_unchecked_mut(buf)
+ }
+}
+
+#[inline]
+fn encode_braced<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
+ let buf = &mut buffer[..Braced::LENGTH];
+ buf[0] = b'{';
+ buf[Braced::LENGTH - 1] = b'}';
+
+ // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
+ // SAFETY: The encoded buffer is ASCII encoded
+ unsafe {
+ let dst = buf.as_mut_ptr().add(1);
+
+ ptr::write(dst.cast(), format_hyphenated(src, upper));
+ str::from_utf8_unchecked_mut(buf)
+ }
+}
+
+#[inline]
+fn encode_urn<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
+ let buf = &mut buffer[..Urn::LENGTH];
+ buf[..9].copy_from_slice(b"urn:uuid:");
+
+ // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
+ // SAFETY: The encoded buffer is ASCII encoded
+ unsafe {
+ let dst = buf.as_mut_ptr().add(9);
+
+ ptr::write(dst.cast(), format_hyphenated(src, upper));
+ str::from_utf8_unchecked_mut(buf)
+ }
+}
+
+impl Hyphenated {
+ /// The length of a hyphenated [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ pub const LENGTH: usize = 36;
+
+ /// Creates a [`Hyphenated`] from a [`Uuid`].
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ /// [`Hyphenated`]: struct.Hyphenated.html
+ pub const fn from_uuid(uuid: Uuid) -> Self {
+ Hyphenated(uuid)
+ }
+
+ /// Writes the [`Uuid`] as a lower-case hyphenated string to
+ /// `buffer`, and returns the subslice of the buffer that contains the
+ /// encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.hyphenated()
+ /// .encode_lower(&mut Uuid::encode_buffer()),
+ /// "936da01f-9abd-4d9d-80c7-02af85c822a8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 40];
+ /// uuid.hyphenated().encode_lower(&mut buf);
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_hyphenated(self.0.as_bytes(), buffer, false)
+ }
+
+ /// Writes the [`Uuid`] as an upper-case hyphenated string to
+ /// `buffer`, and returns the subslice of the buffer that contains the
+ /// encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.hyphenated()
+ /// .encode_upper(&mut Uuid::encode_buffer()),
+ /// "936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 40];
+ /// uuid.hyphenated().encode_upper(&mut buf);
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_hyphenated(self.0.as_bytes(), buffer, true)
+ }
+
+ /// Get a reference to the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let hyphenated = Uuid::nil().hyphenated();
+ /// assert_eq!(*hyphenated.as_uuid(), Uuid::nil());
+ /// ```
+ pub const fn as_uuid(&self) -> &Uuid {
+ &self.0
+ }
+
+ /// Consumes the [`Hyphenated`], returning the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let hyphenated = Uuid::nil().hyphenated();
+ /// assert_eq!(hyphenated.into_uuid(), Uuid::nil());
+ /// ```
+ pub const fn into_uuid(self) -> Uuid {
+ self.0
+ }
+}
+
+impl Braced {
+ /// The length of a braced [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ pub const LENGTH: usize = 38;
+
+ /// Creates a [`Braced`] from a [`Uuid`].
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ /// [`Braced`]: struct.Braced.html
+ pub const fn from_uuid(uuid: Uuid) -> Self {
+ Braced(uuid)
+ }
+
+ /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
+ /// braces to `buffer`, and returns the subslice of the buffer that contains
+ /// the encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.braced()
+ /// .encode_lower(&mut Uuid::encode_buffer()),
+ /// "{936da01f-9abd-4d9d-80c7-02af85c822a8}"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 40];
+ /// uuid.braced().encode_lower(&mut buf);
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"{936da01f-9abd-4d9d-80c7-02af85c822a8}!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_braced(self.0.as_bytes(), buffer, false)
+ }
+
+ /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
+ /// braces to `buffer`, and returns the subslice of the buffer that contains
+ /// the encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.braced()
+ /// .encode_upper(&mut Uuid::encode_buffer()),
+ /// "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 40];
+ /// uuid.braced().encode_upper(&mut buf);
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_braced(self.0.as_bytes(), buffer, true)
+ }
+
+ /// Get a reference to the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let braced = Uuid::nil().braced();
+ /// assert_eq!(*braced.as_uuid(), Uuid::nil());
+ /// ```
+ pub const fn as_uuid(&self) -> &Uuid {
+ &self.0
+ }
+
+ /// Consumes the [`Braced`], returning the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let braced = Uuid::nil().braced();
+ /// assert_eq!(braced.into_uuid(), Uuid::nil());
+ /// ```
+ pub const fn into_uuid(self) -> Uuid {
+ self.0
+ }
+}
+
+impl Simple {
+ /// The length of a simple [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ pub const LENGTH: usize = 32;
+
+ /// Creates a [`Simple`] from a [`Uuid`].
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ /// [`Simple`]: struct.Simple.html
+ pub const fn from_uuid(uuid: Uuid) -> Self {
+ Simple(uuid)
+ }
+
+ /// Writes the [`Uuid`] as a lower-case simple string to `buffer`,
+ /// and returns the subslice of the buffer that contains the encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
+ /// "936da01f9abd4d9d80c702af85c822a8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 36];
+ /// assert_eq!(
+ /// uuid.simple().encode_lower(&mut buf),
+ /// "936da01f9abd4d9d80c702af85c822a8"
+ /// );
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_simple(self.0.as_bytes(), buffer, false)
+ }
+
+ /// Writes the [`Uuid`] as an upper-case simple string to `buffer`,
+ /// and returns the subslice of the buffer that contains the encoded UUID.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.simple().encode_upper(&mut Uuid::encode_buffer()),
+ /// "936DA01F9ABD4D9D80C702AF85C822A8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 36];
+ /// assert_eq!(
+ /// uuid.simple().encode_upper(&mut buf),
+ /// "936DA01F9ABD4D9D80C702AF85C822A8"
+ /// );
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_simple(self.0.as_bytes(), buffer, true)
+ }
+
+ /// Get a reference to the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let simple = Uuid::nil().simple();
+ /// assert_eq!(*simple.as_uuid(), Uuid::nil());
+ /// ```
+ pub const fn as_uuid(&self) -> &Uuid {
+ &self.0
+ }
+
+ /// Consumes the [`Simple`], returning the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let simple = Uuid::nil().simple();
+ /// assert_eq!(simple.into_uuid(), Uuid::nil());
+ /// ```
+ pub const fn into_uuid(self) -> Uuid {
+ self.0
+ }
+}
+
+impl Urn {
+ /// The length of a URN [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ pub const LENGTH: usize = 45;
+
+ /// Creates a [`Urn`] from a [`Uuid`].
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ /// [`Urn`]: struct.Urn.html
+ pub const fn from_uuid(uuid: Uuid) -> Self {
+ Urn(uuid)
+ }
+
+ /// Writes the [`Uuid`] as a lower-case URN string to
+ /// `buffer`, and returns the subslice of the buffer that contains the
+ /// encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
+ /// "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 49];
+ /// uuid.urn().encode_lower(&mut buf);
+ /// assert_eq!(
+ /// uuid.urn().encode_lower(&mut buf),
+ /// "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
+ /// );
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_urn(self.0.as_bytes(), buffer, false)
+ }
+
+ /// Writes the [`Uuid`] as an upper-case URN string to
+ /// `buffer`, and returns the subslice of the buffer that contains the
+ /// encoded UUID.
+ ///
+ /// This is slightly more efficient than using the formatting
+ /// infrastructure as it avoids virtual calls, and may avoid
+ /// double buffering.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ ///
+ /// # Panics
+ ///
+ /// Panics if the buffer is not large enough: it must have length at least
+ /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
+ /// sufficiently-large temporary buffer.
+ ///
+ /// [`LENGTH`]: #associatedconstant.LENGTH
+ /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
+ ///
+ /// // the encoded portion is returned
+ /// assert_eq!(
+ /// uuid.urn().encode_upper(&mut Uuid::encode_buffer()),
+ /// "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
+ /// );
+ ///
+ /// // the buffer is mutated directly, and trailing contents remains
+ /// let mut buf = [b'!'; 49];
+ /// assert_eq!(
+ /// uuid.urn().encode_upper(&mut buf),
+ /// "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
+ /// );
+ /// assert_eq!(
+ /// &buf as &[_],
+ /// b"urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
+ /// );
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ /// */
+ #[inline]
+ pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
+ encode_urn(self.0.as_bytes(), buffer, true)
+ }
+
+ /// Get a reference to the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let urn = Uuid::nil().urn();
+ /// assert_eq!(*urn.as_uuid(), Uuid::nil());
+ /// ```
+ pub const fn as_uuid(&self) -> &Uuid {
+ &self.0
+ }
+
+ /// Consumes the [`Urn`], returning the underlying [`Uuid`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use uuid::Uuid;
+ ///
+ /// let urn = Uuid::nil().urn();
+ /// assert_eq!(urn.into_uuid(), Uuid::nil());
+ /// ```
+ pub const fn into_uuid(self) -> Uuid {
+ self.0
+ }
+}
+
+macro_rules! impl_fmt_traits {
+ ($($T:ident<$($a:lifetime),*>),+) => {$(
+ impl<$($a),*> fmt::Display for $T<$($a),*> {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(self, f)
+ }
+ }
+
+ impl<$($a),*> fmt::LowerHex for $T<$($a),*> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.encode_lower(&mut [0; Self::LENGTH]))
+ }
+ }
+
+ impl<$($a),*> fmt::UpperHex for $T<$($a),*> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.encode_upper(&mut [0; Self::LENGTH]))
+ }
+ }
+
+ impl_fmt_from!($T<$($a),*>);
+ )+}
+}
+
+macro_rules! impl_fmt_from {
+ ($T:ident<>) => {
+ impl From<Uuid> for $T {
+ #[inline]
+ fn from(f: Uuid) -> Self {
+ $T(f)
+ }
+ }
+
+ impl From<$T> for Uuid {
+ #[inline]
+ fn from(f: $T) -> Self {
+ f.into_uuid()
+ }
+ }
+
+ impl AsRef<Uuid> for $T {
+ #[inline]
+ fn as_ref(&self) -> &Uuid {
+ &self.0
+ }
+ }
+
+ impl Borrow<Uuid> for $T {
+ #[inline]
+ fn borrow(&self) -> &Uuid {
+ &self.0
+ }
+ }
+ };
+ ($T:ident<$a:lifetime>) => {
+ impl<$a> From<&$a Uuid> for $T<$a> {
+ #[inline]
+ fn from(f: &$a Uuid) -> Self {
+ $T::from_uuid_ref(f)
+ }
+ }
+
+ impl<$a> From<$T<$a>> for &$a Uuid {
+ #[inline]
+ fn from(f: $T<$a>) -> &$a Uuid {
+ f.0
+ }
+ }
+
+ impl<$a> AsRef<Uuid> for $T<$a> {
+ #[inline]
+ fn as_ref(&self) -> &Uuid {
+ self.0
+ }
+ }
+
+ impl<$a> Borrow<Uuid> for $T<$a> {
+ #[inline]
+ fn borrow(&self) -> &Uuid {
+ self.0
+ }
+ }
+ };
+}
+
+impl_fmt_traits! {
+ Hyphenated<>,
+ Simple<>,
+ Urn<>,
+ Braced<>
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn hyphenated_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().hyphenated().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Hyphenated::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn hyphenated_ref_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().as_hyphenated().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Hyphenated::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn simple_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().simple().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Simple::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn simple_ref_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().as_simple().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Simple::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn urn_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().urn().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Urn::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn urn_ref_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().as_urn().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Urn::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn braced_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().braced().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Braced::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ fn braced_ref_trailing() {
+ let mut buf = [b'x'; 100];
+ let len = Uuid::nil().as_braced().encode_lower(&mut buf).len();
+ assert_eq!(len, super::Braced::LENGTH);
+ assert!(buf[len..].iter().all(|x| *x == b'x'));
+ }
+
+ #[test]
+ #[should_panic]
+ fn hyphenated_too_small() {
+ Uuid::nil().hyphenated().encode_lower(&mut [0; 35]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn simple_too_small() {
+ Uuid::nil().simple().encode_lower(&mut [0; 31]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn urn_too_small() {
+ Uuid::nil().urn().encode_lower(&mut [0; 44]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn braced_too_small() {
+ Uuid::nil().braced().encode_lower(&mut [0; 37]);
+ }
+
+ #[test]
+ fn hyphenated_to_inner() {
+ let hyphenated = Uuid::nil().hyphenated();
+ assert_eq!(Uuid::from(hyphenated), Uuid::nil());
+ }
+
+ #[test]
+ fn simple_to_inner() {
+ let simple = Uuid::nil().simple();
+ assert_eq!(Uuid::from(simple), Uuid::nil());
+ }
+
+ #[test]
+ fn urn_to_inner() {
+ let urn = Uuid::nil().urn();
+ assert_eq!(Uuid::from(urn), Uuid::nil());
+ }
+
+ #[test]
+ fn braced_to_inner() {
+ let braced = Uuid::nil().braced();
+ assert_eq!(Uuid::from(braced), Uuid::nil());
+ }
+}
diff --git a/third_party/rust/uuid/src/lib.rs b/third_party/rust/uuid/src/lib.rs
new file mode 100644
index 0000000000..05ebc2d02f
--- /dev/null
+++ b/third_party/rust/uuid/src/lib.rs
@@ -0,0 +1,1548 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Generate and parse universally unique identifiers (UUIDs).
+//!
+//! Here's an example of a UUID:
+//!
+//! ```text
+//! 67e55044-10b1-426f-9247-bb680e5fe0c8
+//! ```
+//!
+//! A UUID is a unique 128-bit value, stored as 16 octets, and regularly
+//! formatted as a hex string in five groups. UUIDs are used to assign unique
+//! identifiers to entities without requiring a central allocating authority.
+//!
+//! They are particularly useful in distributed systems, though can be used in
+//! disparate areas, such as databases and network protocols. Typically a UUID
+//! is displayed in a readable string form as a sequence of hexadecimal digits,
+//! separated into groups by hyphens.
+//!
+//! The uniqueness property is not strictly guaranteed, however for all
+//! practical purposes, it can be assumed that an unintentional collision would
+//! be extremely unlikely.
+//!
+//! UUIDs have a number of standardized encodings that are specified in [RFC4122](http://tools.ietf.org/html/rfc4122),
+//! with recent additions [in draft](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04).
+//!
+//! # Getting started
+//!
+//! Add the following to your `Cargo.toml`:
+//!
+//! ```toml
+//! [dependencies.uuid]
+//! version = "1.3.0"
+//! features = [
+//! "v4", # Lets you generate random UUIDs
+//! "fast-rng", # Use a faster (but still sufficiently random) RNG
+//! "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
+//! ]
+//! ```
+//!
+//! When you want a UUID, you can generate one:
+//!
+//! ```
+//! # fn main() {
+//! # #[cfg(feature = "v4")]
+//! # {
+//! use uuid::Uuid;
+//!
+//! let id = Uuid::new_v4();
+//! # }
+//! # }
+//! ```
+//!
+//! If you have a UUID value, you can use its string literal form inline:
+//!
+//! ```
+//! use uuid::{uuid, Uuid};
+//!
+//! const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+//! ```
+//!
+//! # Working with different UUID versions
+//!
+//! This library supports all standardized methods for generating UUIDs through individual Cargo features.
+//!
+//! By default, this crate depends on nothing but the Rust standard library and can parse and format
+//! UUIDs, but cannot generate them. Depending on the kind of UUID you'd like to work with, there
+//! are Cargo features that enable generating them:
+//!
+//! * `v1` - Version 1 UUIDs using a timestamp and monotonic counter.
+//! * `v3` - Version 3 UUIDs based on the MD5 hash of some data.
+//! * `v4` - Version 4 UUIDs with random data.
+//! * `v5` - Version 5 UUIDs based on the SHA1 hash of some data.
+//!
+//! Versions that are in draft are also supported. See the _unstable features_ section for details.
+//!
+//! This library also includes a [`Builder`] type that can be used to help construct UUIDs of any
+//! version without any additional dependencies or features. It's a lower-level API than [`Uuid`]
+//! that can be used when you need control over implicit requirements on things like a source
+//! of randomness.
+//!
+//! ## Which UUID version should I use?
+//!
+//! If you just want to generate unique identifiers then consider version 4 (`v4`) UUIDs. If you want
+//! to use UUIDs as database keys or need to sort them then consider version 7 (`v7`) UUIDs.
+//! Other versions should generally be avoided unless there's an existing need for them.
+//!
+//! Some UUID versions supersede others. Prefer version 6 over version 1 and version 5 over version 3.
+//!
+//! # Other features
+//!
+//! Other crate features can also be useful beyond the version support:
+//!
+//! * `macro-diagnostics` - enhances the diagnostics of `uuid!` macro.
+//! * `serde` - adds the ability to serialize and deserialize a UUID using
+//! `serde`.
+//! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for
+//! fuzzing.
+//! * `fast-rng` - uses a faster algorithm for generating random UUIDs.
+//! This feature requires more dependencies to compile, but is just as suitable for
+//! UUIDs as the default algorithm.
+//!
+//! # Unstable features
+//!
+//! Some features are unstable. They may be incomplete or depend on other
+//! unstable libraries. These include:
+//!
+//! * `v6` - Version 6 UUIDs using a timestamp and monotonic counter.
+//! * `v7` - Version 7 UUIDs using a Unix timestamp.
+//! * `v8` - Version 8 UUIDs using user-defined data.
+//! * `zerocopy` - adds support for zero-copy deserialization using the
+//! `zerocopy` library.
+//!
+//! Unstable features may break between minor releases.
+//!
+//! To allow unstable features, you'll need to enable the Cargo feature as
+//! normal, but also pass an additional flag through your environment to opt-in
+//! to unstable `uuid` features:
+//!
+//! ```text
+//! RUSTFLAGS="--cfg uuid_unstable"
+//! ```
+//!
+//! # Building for other targets
+//!
+//! ## WebAssembly
+//!
+//! For WebAssembly, enable the `js` feature:
+//!
+//! ```toml
+//! [dependencies.uuid]
+//! version = "1.3.0"
+//! features = [
+//! "v4",
+//! "v7",
+//! "js",
+//! ]
+//! ```
+//!
+//! ## Embedded
+//!
+//! For embedded targets without the standard library, you'll need to
+//! disable default features when building `uuid`:
+//!
+//! ```toml
+//! [dependencies.uuid]
+//! version = "1.3.0"
+//! default-features = false
+//! ```
+//!
+//! Some additional features are supported in no-std environments:
+//!
+//! * `v1`, `v3`, `v5`, `v6`, and `v8`.
+//! * `serde`.
+//!
+//! If you need to use `v4` or `v7` in a no-std environment, you'll need to
+//! follow [`getrandom`'s docs] on configuring a source of randomness
+//! on currently unsupported targets. Alternatively, you can produce
+//! random bytes yourself and then pass them to [`Builder::from_random_bytes`]
+//! without enabling the `v4` feature.
+//!
+//! # Examples
+//!
+//! Parse a UUID given in the simple format and print it as a URN:
+//!
+//! ```
+//! # use uuid::Uuid;
+//! # fn main() -> Result<(), uuid::Error> {
+//! let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
+//!
+//! println!("{}", my_uuid.urn());
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! Generate a random UUID and print it out in hexadecimal form:
+//!
+//! ```
+//! // Note that this requires the `v4` feature to be enabled.
+//! # use uuid::Uuid;
+//! # fn main() {
+//! # #[cfg(feature = "v4")] {
+//! let my_uuid = Uuid::new_v4();
+//!
+//! println!("{}", my_uuid);
+//! # }
+//! # }
+//! ```
+//!
+//! # References
+//!
+//! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
+//! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
+//! * [Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04)
+//!
+//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
+//! [`cargo-web`]: https://crates.io/crates/cargo-web
+//! [`getrandom`'s docs]: https://docs.rs/getrandom
+
+#![no_std]
+#![deny(missing_debug_implementations, missing_docs)]
+#![doc(
+ html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "https://www.rust-lang.org/favicon.ico",
+ html_root_url = "https://docs.rs/uuid/1.3.0"
+)]
+
+#[cfg(any(feature = "std", test))]
+#[macro_use]
+extern crate std;
+
+#[cfg(all(not(feature = "std"), not(test)))]
+#[macro_use]
+extern crate core as std;
+
+#[cfg(all(uuid_unstable, feature = "zerocopy"))]
+use zerocopy::{AsBytes, FromBytes, Unaligned};
+
+mod builder;
+mod error;
+mod parser;
+
+pub mod fmt;
+pub mod timestamp;
+
+pub use timestamp::{context::NoContext, ClockSequence, Timestamp};
+
+#[cfg(any(feature = "v1", feature = "v6"))]
+pub use timestamp::context::Context;
+
+#[cfg(feature = "v1")]
+#[doc(hidden)]
+// Soft-deprecated (Rust doesn't support deprecating re-exports)
+// Use `Context` from the crate root instead
+pub mod v1;
+#[cfg(feature = "v3")]
+mod v3;
+#[cfg(feature = "v4")]
+mod v4;
+#[cfg(feature = "v5")]
+mod v5;
+#[cfg(all(uuid_unstable, feature = "v6"))]
+mod v6;
+#[cfg(all(uuid_unstable, feature = "v7"))]
+mod v7;
+#[cfg(all(uuid_unstable, feature = "v8"))]
+mod v8;
+
+#[cfg(feature = "md5")]
+mod md5;
+#[cfg(feature = "rng")]
+mod rng;
+#[cfg(feature = "sha1")]
+mod sha1;
+
+mod external;
+
+#[macro_use]
+mod macros;
+
+#[doc(hidden)]
+#[cfg(feature = "macro-diagnostics")]
+pub extern crate uuid_macro_internal;
+
+use crate::std::convert;
+
+pub use crate::{builder::Builder, error::Error};
+
+/// A 128-bit (16 byte) buffer containing the UUID.
+///
+/// # ABI
+///
+/// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`].
+pub type Bytes = [u8; 16];
+
+/// The version of the UUID, denoting the generating algorithm.
+///
+/// # References
+///
+/// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[non_exhaustive]
+#[repr(u8)]
+pub enum Version {
+ /// The "nil" (all zeros) UUID.
+ Nil = 0u8,
+ /// Version 1: Timestamp and node ID.
+ Mac = 1,
+ /// Version 2: DCE Security.
+ Dce = 2,
+ /// Version 3: MD5 hash.
+ Md5 = 3,
+ /// Version 4: Random.
+ Random = 4,
+ /// Version 5: SHA-1 hash.
+ Sha1 = 5,
+ /// Version 6: Sortable Timestamp and node ID.
+ #[cfg(uuid_unstable)]
+ SortMac = 6,
+ /// Version 7: Timestamp and random.
+ #[cfg(uuid_unstable)]
+ SortRand = 7,
+ /// Version 8: Custom.
+ #[cfg(uuid_unstable)]
+ Custom = 8,
+ /// The "max" (all ones) UUID.
+ #[cfg(uuid_unstable)]
+ Max = 0xff,
+}
+
+/// The reserved variants of UUIDs.
+///
+/// # References
+///
+/// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[non_exhaustive]
+#[repr(u8)]
+pub enum Variant {
+ /// Reserved by the NCS for backward compatibility.
+ NCS = 0u8,
+ /// As described in the RFC4122 Specification (default).
+ RFC4122,
+ /// Reserved by Microsoft for backward compatibility.
+ Microsoft,
+ /// Reserved for future expansion.
+ Future,
+}
+
+/// A Universally Unique Identifier (UUID).
+///
+/// # Examples
+///
+/// Parse a UUID given in the simple format and print it as a urn:
+///
+/// ```
+/// # use uuid::Uuid;
+/// # fn main() -> Result<(), uuid::Error> {
+/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
+///
+/// println!("{}", my_uuid.urn());
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Create a new random (V4) UUID and print it out in hexadecimal form:
+///
+/// ```
+/// // Note that this requires the `v4` feature enabled in the uuid crate.
+/// # use uuid::Uuid;
+/// # fn main() {
+/// # #[cfg(feature = "v4")] {
+/// let my_uuid = Uuid::new_v4();
+///
+/// println!("{}", my_uuid);
+/// # }
+/// # }
+/// ```
+///
+/// # Formatting
+///
+/// A UUID can be formatted in one of a few ways:
+///
+/// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`.
+/// * [`hyphenated`](#method.hyphenated):
+/// `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`.
+/// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`.
+/// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`.
+///
+/// The default representation when formatting a UUID with `Display` is
+/// hyphenated:
+///
+/// ```
+/// # use uuid::Uuid;
+/// # fn main() -> Result<(), uuid::Error> {
+/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
+///
+/// assert_eq!(
+/// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+/// my_uuid.to_string(),
+/// );
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Other formats can be specified using adapter methods on the UUID:
+///
+/// ```
+/// # use uuid::Uuid;
+/// # fn main() -> Result<(), uuid::Error> {
+/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
+///
+/// assert_eq!(
+/// "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
+/// my_uuid.urn().to_string(),
+/// );
+/// # Ok(())
+/// # }
+/// ```
+///
+/// # Endianness
+///
+/// The specification for UUIDs encodes the integer fields that make up the
+/// value in big-endian order. This crate assumes integer inputs are already in
+/// the correct order by default, regardless of the endianness of the
+/// environment. Most methods that accept integers have a `_le` variant (such as
+/// `from_fields_le`) that assumes any integer values will need to have their
+/// bytes flipped, regardless of the endianness of the environment.
+///
+/// Most users won't need to worry about endianness unless they need to operate
+/// on individual fields (such as when converting between Microsoft GUIDs). The
+/// important things to remember are:
+///
+/// - The endianness is in terms of the fields of the UUID, not the environment.
+/// - The endianness is assumed to be big-endian when there's no `_le` suffix
+/// somewhere.
+/// - Byte-flipping in `_le` methods applies to each integer.
+/// - Endianness roundtrips, so if you create a UUID with `from_fields_le`
+/// you'll get the same values back out with `to_fields_le`.
+///
+/// # ABI
+///
+/// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
+#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[cfg_attr(all(uuid_unstable, feature = "zerocopy"), derive(AsBytes, FromBytes, Unaligned))]
+#[repr(transparent)]
+pub struct Uuid(Bytes);
+
+impl Uuid {
+ /// UUID namespace for Domain Name System (DNS).
+ pub const NAMESPACE_DNS: Self = Uuid([
+ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
+ 0xc8,
+ ]);
+
+ /// UUID namespace for ISO Object Identifiers (OIDs).
+ pub const NAMESPACE_OID: Self = Uuid([
+ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
+ 0xc8,
+ ]);
+
+ /// UUID namespace for Uniform Resource Locators (URLs).
+ pub const NAMESPACE_URL: Self = Uuid([
+ 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
+ 0xc8,
+ ]);
+
+ /// UUID namespace for X.500 Distinguished Names (DNs).
+ pub const NAMESPACE_X500: Self = Uuid([
+ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
+ 0xc8,
+ ]);
+
+ /// Returns the variant of the UUID structure.
+ ///
+ /// This determines the interpretation of the structure of the UUID.
+ /// This method simply reads the value of the variant byte. It doesn't
+ /// validate the rest of the UUID as conforming to that variant.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Variant};
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
+ ///
+ /// assert_eq!(Variant::RFC4122, my_uuid.get_variant());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
+ pub const fn get_variant(&self) -> Variant {
+ match self.as_bytes()[8] {
+ x if x & 0x80 == 0x00 => Variant::NCS,
+ x if x & 0xc0 == 0x80 => Variant::RFC4122,
+ x if x & 0xe0 == 0xc0 => Variant::Microsoft,
+ x if x & 0xe0 == 0xe0 => Variant::Future,
+ // The above match arms are actually exhaustive
+ // We just return `Future` here because we can't
+ // use `unreachable!()` in a `const fn`
+ _ => Variant::Future,
+ }
+ }
+
+ /// Returns the version number of the UUID.
+ ///
+ /// This represents the algorithm used to generate the value.
+ /// This method is the future-proof alternative to [`Uuid::get_version`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
+ ///
+ /// assert_eq!(3, my_uuid.get_version_num());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
+ pub const fn get_version_num(&self) -> usize {
+ (self.as_bytes()[6] >> 4) as usize
+ }
+
+ /// Returns the version of the UUID.
+ ///
+ /// This represents the algorithm used to generate the value.
+ /// If the version field doesn't contain a recognized version then `None`
+ /// is returned. If you're trying to read the version for a future extension
+ /// you can also use [`Uuid::get_version_num`] to unconditionally return a
+ /// number. Future extensions may start to return `Some` once they're
+ /// standardized and supported.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version};
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
+ ///
+ /// assert_eq!(Some(Version::Md5), my_uuid.get_version());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
+ pub const fn get_version(&self) -> Option<Version> {
+ match self.get_version_num() {
+ 0 if self.is_nil() => Some(Version::Nil),
+ 1 => Some(Version::Mac),
+ 2 => Some(Version::Dce),
+ 3 => Some(Version::Md5),
+ 4 => Some(Version::Random),
+ 5 => Some(Version::Sha1),
+ #[cfg(uuid_unstable)]
+ 6 => Some(Version::SortMac),
+ #[cfg(uuid_unstable)]
+ 7 => Some(Version::SortRand),
+ #[cfg(uuid_unstable)]
+ 8 => Some(Version::Custom),
+ #[cfg(uuid_unstable)]
+ 0xf => Some(Version::Max),
+ _ => None,
+ }
+ }
+
+ /// Returns the four field values of the UUID.
+ ///
+ /// These values can be passed to the [`Uuid::from_fields`] method to get
+ /// the original `Uuid` back.
+ ///
+ /// * The first field value represents the first group of (eight) hex
+ /// digits, taken as a big-endian `u32` value. For V1 UUIDs, this field
+ /// represents the low 32 bits of the timestamp.
+ /// * The second field value represents the second group of (four) hex
+ /// digits, taken as a big-endian `u16` value. For V1 UUIDs, this field
+ /// represents the middle 16 bits of the timestamp.
+ /// * The third field value represents the third group of (four) hex digits,
+ /// taken as a big-endian `u16` value. The 4 most significant bits give
+ /// the UUID version, and for V1 UUIDs, the last 12 bits represent the
+ /// high 12 bits of the timestamp.
+ /// * The last field value represents the last two groups of four and twelve
+ /// hex digits, taken in order. The first 1-3 bits of this indicate the
+ /// UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock
+ /// sequence and the last 48 bits indicate the node ID.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::nil();
+ ///
+ /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8]));
+ ///
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ ///
+ /// assert_eq!(
+ /// uuid.as_fields(),
+ /// (
+ /// 0xa1a2a3a4,
+ /// 0xb1b2,
+ /// 0xc1c2,
+ /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
+ /// )
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
+ let bytes = self.as_bytes();
+
+ let d1 = (bytes[0] as u32) << 24
+ | (bytes[1] as u32) << 16
+ | (bytes[2] as u32) << 8
+ | (bytes[3] as u32);
+
+ let d2 = (bytes[4] as u16) << 8 | (bytes[5] as u16);
+
+ let d3 = (bytes[6] as u16) << 8 | (bytes[7] as u16);
+
+ let d4: &[u8; 8] = convert::TryInto::try_into(&bytes[8..16]).unwrap();
+ (d1, d2, d3, d4)
+ }
+
+ /// Returns the four field values of the UUID in little-endian order.
+ ///
+ /// The bytes in the returned integer fields will be converted from
+ /// big-endian order. This is based on the endianness of the UUID,
+ /// rather than the target environment so bytes will be flipped on both
+ /// big and little endian machines.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use uuid::Uuid;
+ ///
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ ///
+ /// assert_eq!(
+ /// uuid.to_fields_le(),
+ /// (
+ /// 0xa4a3a2a1,
+ /// 0xb2b1,
+ /// 0xc2c1,
+ /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
+ /// )
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {
+ let d1 = (self.as_bytes()[0] as u32)
+ | (self.as_bytes()[1] as u32) << 8
+ | (self.as_bytes()[2] as u32) << 16
+ | (self.as_bytes()[3] as u32) << 24;
+
+ let d2 = (self.as_bytes()[4] as u16) | (self.as_bytes()[5] as u16) << 8;
+
+ let d3 = (self.as_bytes()[6] as u16) | (self.as_bytes()[7] as u16) << 8;
+
+ let d4: &[u8; 8] = convert::TryInto::try_into(&self.as_bytes()[8..16]).unwrap();
+ (d1, d2, d3, d4)
+ }
+
+ /// Returns a 128bit value containing the value.
+ ///
+ /// The bytes in the UUID will be packed directly into a `u128`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ ///
+ /// assert_eq!(
+ /// uuid.as_u128(),
+ /// 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8,
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn as_u128(&self) -> u128 {
+ (self.as_bytes()[0] as u128) << 120
+ | (self.as_bytes()[1] as u128) << 112
+ | (self.as_bytes()[2] as u128) << 104
+ | (self.as_bytes()[3] as u128) << 96
+ | (self.as_bytes()[4] as u128) << 88
+ | (self.as_bytes()[5] as u128) << 80
+ | (self.as_bytes()[6] as u128) << 72
+ | (self.as_bytes()[7] as u128) << 64
+ | (self.as_bytes()[8] as u128) << 56
+ | (self.as_bytes()[9] as u128) << 48
+ | (self.as_bytes()[10] as u128) << 40
+ | (self.as_bytes()[11] as u128) << 32
+ | (self.as_bytes()[12] as u128) << 24
+ | (self.as_bytes()[13] as u128) << 16
+ | (self.as_bytes()[14] as u128) << 8
+ | (self.as_bytes()[15] as u128)
+ }
+
+ /// Returns a 128bit little-endian value containing the value.
+ ///
+ /// The bytes in the `u128` will be flipped to convert into big-endian
+ /// order. This is based on the endianness of the UUID, rather than the
+ /// target environment so bytes will be flipped on both big and little
+ /// endian machines.
+ ///
+ /// Note that this will produce a different result than
+ /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather
+ /// than reversing the individual fields in-place.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ ///
+ /// assert_eq!(
+ /// uuid.to_u128_le(),
+ /// 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1,
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn to_u128_le(&self) -> u128 {
+ (self.as_bytes()[0] as u128)
+ | (self.as_bytes()[1] as u128) << 8
+ | (self.as_bytes()[2] as u128) << 16
+ | (self.as_bytes()[3] as u128) << 24
+ | (self.as_bytes()[4] as u128) << 32
+ | (self.as_bytes()[5] as u128) << 40
+ | (self.as_bytes()[6] as u128) << 48
+ | (self.as_bytes()[7] as u128) << 56
+ | (self.as_bytes()[8] as u128) << 64
+ | (self.as_bytes()[9] as u128) << 72
+ | (self.as_bytes()[10] as u128) << 80
+ | (self.as_bytes()[11] as u128) << 88
+ | (self.as_bytes()[12] as u128) << 96
+ | (self.as_bytes()[13] as u128) << 104
+ | (self.as_bytes()[14] as u128) << 112
+ | (self.as_bytes()[15] as u128) << 120
+ }
+
+ /// Returns two 64bit values containing the value.
+ ///
+ /// The bytes in the UUID will be split into two `u64`.
+ /// The first u64 represents the 64 most significant bits,
+ /// the second one represents the 64 least significant.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ /// assert_eq!(
+ /// uuid.as_u64_pair(),
+ /// (0xa1a2a3a4b1b2c1c2, 0xd1d2d3d4d5d6d7d8),
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn as_u64_pair(&self) -> (u64, u64) {
+ let value = self.as_u128();
+ ((value >> 64) as u64, value as u64)
+ }
+
+ /// Returns a slice of 16 octets containing the value.
+ ///
+ /// This method borrows the underlying byte value of the UUID.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let bytes1 = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ /// let uuid1 = Uuid::from_bytes_ref(&bytes1);
+ ///
+ /// let bytes2 = uuid1.as_bytes();
+ /// let uuid2 = Uuid::from_bytes_ref(bytes2);
+ ///
+ /// assert_eq!(uuid1, uuid2);
+ ///
+ /// assert!(std::ptr::eq(
+ /// uuid2 as *const Uuid as *const u8,
+ /// &bytes1 as *const [u8; 16] as *const u8,
+ /// ));
+ /// ```
+ pub const fn as_bytes(&self) -> &Bytes {
+ &self.0
+ }
+
+ /// Consumes self and returns the underlying byte value of the UUID.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let bytes = [
+ /// 0xa1, 0xa2, 0xa3, 0xa4,
+ /// 0xb1, 0xb2,
+ /// 0xc1, 0xc2,
+ /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+ /// ];
+ /// let uuid = Uuid::from_bytes(bytes);
+ /// assert_eq!(bytes, uuid.into_bytes());
+ /// ```
+ pub const fn into_bytes(self) -> Bytes {
+ self.0
+ }
+
+ /// Returns the bytes of the UUID in little-endian order.
+ ///
+ /// The bytes will be flipped to convert into little-endian order. This is
+ /// based on the endianness of the UUID, rather than the target environment
+ /// so bytes will be flipped on both big and little endian machines.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use uuid::Uuid;
+ ///
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
+ ///
+ /// assert_eq!(
+ /// uuid.to_bytes_le(),
+ /// ([
+ /// 0xa4, 0xa3, 0xa2, 0xa1, 0xb2, 0xb1, 0xc2, 0xc1, 0xd1, 0xd2,
+ /// 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8
+ /// ])
+ /// );
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub const fn to_bytes_le(&self) -> Bytes {
+ [
+ self.0[3], self.0[2], self.0[1], self.0[0], self.0[5], self.0[4], self.0[7], self.0[6],
+ self.0[8], self.0[9], self.0[10], self.0[11], self.0[12], self.0[13], self.0[14],
+ self.0[15],
+ ]
+ }
+
+ /// Tests if the UUID is nil (all zeros).
+ pub const fn is_nil(&self) -> bool {
+ self.as_u128() == u128::MIN
+ }
+
+ /// Tests if the UUID is max (all ones).
+ #[cfg(uuid_unstable)]
+ pub const fn is_max(&self) -> bool {
+ self.as_u128() == u128::MAX
+ }
+
+ /// A buffer that can be used for `encode_...` calls, that is
+ /// guaranteed to be long enough for any of the format adapters.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use uuid::Uuid;
+ /// let uuid = Uuid::nil();
+ ///
+ /// assert_eq!(
+ /// uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
+ /// "00000000000000000000000000000000"
+ /// );
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated()
+ /// .encode_lower(&mut Uuid::encode_buffer()),
+ /// "00000000-0000-0000-0000-000000000000"
+ /// );
+ ///
+ /// assert_eq!(
+ /// uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
+ /// "urn:uuid:00000000-0000-0000-0000-000000000000"
+ /// );
+ /// ```
+ pub const fn encode_buffer() -> [u8; fmt::Urn::LENGTH] {
+ [0; fmt::Urn::LENGTH]
+ }
+
+ /// If the UUID is the correct version (v1, v6, or v7) this will return
+ /// the timestamp and counter portion parsed from a V1 UUID.
+ ///
+ /// Returns `None` if the supplied UUID is not V1.
+ ///
+ /// The V1 timestamp format defined in RFC4122 specifies a 60-bit
+ /// integer representing the number of 100-nanosecond intervals
+ /// since 00:00:00.00, 15 Oct 1582.
+ ///
+ /// [`Timestamp`] offers several options for converting the raw RFC4122
+ /// value into more commonly-used formats, such as a unix timestamp.
+ ///
+ /// # Roundtripping
+ ///
+ /// This method is unlikely to roundtrip a timestamp in a UUID due to the way
+ /// UUIDs encode timestamps. The timestamp returned from this method will be truncated to
+ /// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs.
+ ///
+ /// [`Timestamp`]: v1/struct.Timestamp.html
+ pub const fn get_timestamp(&self) -> Option<Timestamp> {
+ match self.get_version() {
+ Some(Version::Mac) => {
+ let (ticks, counter) = timestamp::decode_rfc4122_timestamp(self);
+
+ Some(Timestamp::from_rfc4122(ticks, counter))
+ }
+ #[cfg(uuid_unstable)]
+ Some(Version::SortMac) => {
+ let (ticks, counter) = timestamp::decode_sorted_rfc4122_timestamp(self);
+
+ Some(Timestamp::from_rfc4122(ticks, counter))
+ }
+ #[cfg(uuid_unstable)]
+ Some(Version::SortRand) => {
+ let millis = timestamp::decode_unix_timestamp_millis(self);
+
+ let seconds = millis / 1000;
+ let nanos = ((millis % 1000) * 1_000_000) as u32;
+
+ Some(Timestamp {
+ seconds,
+ nanos,
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ counter: 0,
+ })
+ }
+ _ => None,
+ }
+ }
+}
+
+impl Default for Uuid {
+ #[inline]
+ fn default() -> Self {
+ Uuid::nil()
+ }
+}
+
+impl AsRef<[u8]> for Uuid {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+#[cfg(feature = "serde")]
+pub mod serde {
+ //! Adapters for alternative `serde` formats.
+ //!
+ //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with)
+ //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized
+ //! and deserialized.
+
+ pub use crate::external::serde_support::compact;
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use crate::std::string::{String, ToString};
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ macro_rules! check {
+ ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
+ $buf.clear();
+ write!($buf, $format, $target).unwrap();
+ assert!($buf.len() == $len);
+ assert!($buf.chars().all($cond), "{}", $buf);
+ };
+ }
+
+ pub const fn new() -> Uuid {
+ Uuid::from_bytes([
+ 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAA, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
+ 0xA1, 0xE4,
+ ])
+ }
+
+ pub const fn new2() -> Uuid {
+ Uuid::from_bytes([
+ 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAB, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
+ 0xA1, 0xE4,
+ ])
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_compare() {
+ let uuid1 = new();
+ let uuid2 = new2();
+
+ assert_eq!(uuid1, uuid1);
+ assert_eq!(uuid2, uuid2);
+
+ assert_ne!(uuid1, uuid2);
+ assert_ne!(uuid2, uuid1);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_default() {
+ let default_uuid = Uuid::default();
+ let nil_uuid = Uuid::nil();
+
+ assert_eq!(default_uuid, nil_uuid);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_display() {
+ use crate::std::fmt::Write;
+
+ let uuid = new();
+ let s = uuid.to_string();
+ let mut buffer = String::new();
+
+ assert_eq!(s, uuid.hyphenated().to_string());
+
+ check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_lowerhex() {
+ use crate::std::fmt::Write;
+
+ let mut buffer = String::new();
+ let uuid = new();
+
+ check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ }
+
+ // noinspection RsAssertEqual
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_operator_eq() {
+ let uuid1 = new();
+ let uuid1_dup = uuid1.clone();
+ let uuid2 = new2();
+
+ assert!(uuid1 == uuid1);
+ assert!(uuid1 == uuid1_dup);
+ assert!(uuid1_dup == uuid1);
+
+ assert!(uuid1 != uuid2);
+ assert!(uuid2 != uuid1);
+ assert!(uuid1_dup != uuid2);
+ assert!(uuid2 != uuid1_dup);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_uuid_to_string() {
+ use crate::std::fmt::Write;
+
+ let uuid = new();
+ let s = uuid.to_string();
+ let mut buffer = String::new();
+
+ assert_eq!(s.len(), 36);
+
+ check!(buffer, "{}", s, 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_non_conforming() {
+ let from_bytes =
+ Uuid::from_bytes([4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87]);
+
+ assert_eq!(from_bytes.get_version(), None);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_nil() {
+ let nil = Uuid::nil();
+ let not_nil = new();
+
+ assert!(nil.is_nil());
+ assert!(!not_nil.is_nil());
+
+ assert_eq!(nil.get_version(), Some(Version::Nil));
+ assert_eq!(not_nil.get_version(), Some(Version::Random));
+
+ assert_eq!(nil, Builder::from_bytes([0; 16]).with_version(Version::Nil).into_uuid());
+ }
+
+ #[test]
+ #[cfg(uuid_unstable)]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_max() {
+ let max = Uuid::max();
+ let not_max = new();
+
+ assert!(max.is_max());
+ assert!(!not_max.is_max());
+
+ assert_eq!(max.get_version(), Some(Version::Max));
+ assert_eq!(not_max.get_version(), Some(Version::Random));
+
+ assert_eq!(max, Builder::from_bytes([0xff; 16]).with_version(Version::Max).into_uuid());
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_predefined_namespaces() {
+ assert_eq!(
+ Uuid::NAMESPACE_DNS.hyphenated().to_string(),
+ "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
+ );
+ assert_eq!(
+ Uuid::NAMESPACE_URL.hyphenated().to_string(),
+ "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
+ );
+ assert_eq!(
+ Uuid::NAMESPACE_OID.hyphenated().to_string(),
+ "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
+ );
+ assert_eq!(
+ Uuid::NAMESPACE_X500.hyphenated().to_string(),
+ "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
+ );
+ }
+
+ #[cfg(feature = "v3")]
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_get_version_v3() {
+ let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
+
+ assert_eq!(uuid.get_version().unwrap(), Version::Md5);
+ assert_eq!(uuid.get_version_num(), 3);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_get_variant() {
+ let uuid1 = new();
+ let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
+ let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
+ let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
+ let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
+ let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
+
+ assert_eq!(uuid1.get_variant(), Variant::RFC4122);
+ assert_eq!(uuid2.get_variant(), Variant::RFC4122);
+ assert_eq!(uuid3.get_variant(), Variant::RFC4122);
+ assert_eq!(uuid4.get_variant(), Variant::Microsoft);
+ assert_eq!(uuid5.get_variant(), Variant::Microsoft);
+ assert_eq!(uuid6.get_variant(), Variant::NCS);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_to_simple_string() {
+ let uuid1 = new();
+ let s = uuid1.simple().to_string();
+
+ assert_eq!(s.len(), 32);
+ assert!(s.chars().all(|c| c.is_digit(16)));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_hyphenated_string() {
+ let uuid1 = new();
+ let s = uuid1.hyphenated().to_string();
+
+ assert_eq!(36, s.len());
+ assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_upper_lower_hex() {
+ use std::fmt::Write;
+
+ let mut buf = String::new();
+ let u = new();
+
+ macro_rules! check {
+ ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
+ $buf.clear();
+ write!($buf, $format, $target).unwrap();
+ assert_eq!($len, buf.len());
+ assert!($buf.chars().all($cond), "{}", $buf);
+ };
+ }
+
+ check!(buf, "{:x}", u, 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:#x}", u, 36, |c| c.is_lowercase() || c.is_digit(10) || c == '-');
+ check!(buf, "{:#X}", u, 36, |c| c.is_uppercase() || c.is_digit(10) || c == '-');
+
+ check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase()
+ || c.is_digit(10));
+ check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase()
+ || c.is_digit(10));
+
+ check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase()
+ || c.is_digit(10));
+ check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase()
+ || c.is_digit(10)
+ || c == '-');
+ check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase()
+ || c.is_digit(10));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_to_urn_string() {
+ let uuid1 = new();
+ let ss = uuid1.urn().to_string();
+ let s = &ss[9..];
+
+ assert!(ss.starts_with("urn:uuid:"));
+ assert_eq!(s.len(), 36);
+ assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_to_simple_string_matching() {
+ let uuid1 = new();
+
+ let hs = uuid1.hyphenated().to_string();
+ let ss = uuid1.simple().to_string();
+
+ let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
+
+ assert_eq!(hsn, ss);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_string_roundtrip() {
+ let uuid = new();
+
+ let hs = uuid.hyphenated().to_string();
+ let uuid_hs = Uuid::parse_str(&hs).unwrap();
+ assert_eq!(uuid_hs, uuid);
+
+ let ss = uuid.to_string();
+ let uuid_ss = Uuid::parse_str(&ss).unwrap();
+ assert_eq!(uuid_ss, uuid);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_fields() {
+ let d1: u32 = 0xa1a2a3a4;
+ let d2: u16 = 0xb1b2;
+ let d3: u16 = 0xc1c2;
+ let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+
+ let u = Uuid::from_fields(d1, d2, d3, &d4);
+
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+ let result = u.simple().to_string();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_fields_le() {
+ let d1: u32 = 0xa4a3a2a1;
+ let d2: u16 = 0xb2b1;
+ let d3: u16 = 0xc2c1;
+ let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+
+ let u = Uuid::from_fields_le(d1, d2, d3, &d4);
+
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+ let result = u.simple().to_string();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_as_fields() {
+ let u = new();
+ let (d1, d2, d3, d4) = u.as_fields();
+
+ assert_ne!(d1, 0);
+ assert_ne!(d2, 0);
+ assert_ne!(d3, 0);
+ assert_eq!(d4.len(), 8);
+ assert!(!d4.iter().all(|&b| b == 0));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_fields_roundtrip() {
+ let d1_in: u32 = 0xa1a2a3a4;
+ let d2_in: u16 = 0xb1b2;
+ let d3_in: u16 = 0xc1c2;
+ let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+
+ let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
+ let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
+
+ assert_eq!(d1_in, d1_out);
+ assert_eq!(d2_in, d2_out);
+ assert_eq!(d3_in, d3_out);
+ assert_eq!(d4_in, d4_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_fields_le_roundtrip() {
+ let d1_in: u32 = 0xa4a3a2a1;
+ let d2_in: u16 = 0xb2b1;
+ let d3_in: u16 = 0xc2c1;
+ let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+
+ let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in);
+ let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
+
+ assert_eq!(d1_in, d1_out);
+ assert_eq!(d2_in, d2_out);
+ assert_eq!(d3_in, d3_out);
+ assert_eq!(d4_in, d4_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_fields_le_are_actually_le() {
+ let d1_in: u32 = 0xa1a2a3a4;
+ let d2_in: u16 = 0xb1b2;
+ let d3_in: u16 = 0xc1c2;
+ let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
+
+ let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
+ let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
+
+ assert_eq!(d1_in, d1_out.swap_bytes());
+ assert_eq!(d2_in, d2_out.swap_bytes());
+ assert_eq!(d3_in, d3_out.swap_bytes());
+ assert_eq!(d4_in, d4_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_u128() {
+ let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
+
+ let u = Uuid::from_u128(v_in);
+
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+ let result = u.simple().to_string();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_u128_le() {
+ let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
+
+ let u = Uuid::from_u128_le(v_in);
+
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+ let result = u.simple().to_string();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_u64_pair() {
+ let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
+ let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
+
+ let u = Uuid::from_u64_pair(high_in, low_in);
+
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+ let result = u.simple().to_string();
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_u128_roundtrip() {
+ let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
+
+ let u = Uuid::from_u128(v_in);
+ let v_out = u.as_u128();
+
+ assert_eq!(v_in, v_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_u128_le_roundtrip() {
+ let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
+
+ let u = Uuid::from_u128_le(v_in);
+ let v_out = u.to_u128_le();
+
+ assert_eq!(v_in, v_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_u64_pair_roundtrip() {
+ let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
+ let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
+
+ let u = Uuid::from_u64_pair(high_in, low_in);
+ let (high_out, low_out) = u.as_u64_pair();
+
+ assert_eq!(high_in, high_out);
+ assert_eq!(low_in, low_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_u128_le_is_actually_le() {
+ let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
+
+ let u = Uuid::from_u128(v_in);
+ let v_out = u.to_u128_le();
+
+ assert_eq!(v_in, v_out.swap_bytes());
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_slice() {
+ let b = [
+ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8,
+ ];
+
+ let u = Uuid::from_slice(&b).unwrap();
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+
+ assert_eq!(u.simple().to_string(), expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_from_bytes() {
+ let b = [
+ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8,
+ ];
+
+ let u = Uuid::from_bytes(b);
+ let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
+
+ assert_eq!(u.simple().to_string(), expected);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_as_bytes() {
+ let u = new();
+ let ub = u.as_bytes();
+ let ur = u.as_ref();
+
+ assert_eq!(ub.len(), 16);
+ assert_eq!(ur.len(), 16);
+ assert!(!ub.iter().all(|&b| b == 0));
+ assert!(!ur.iter().all(|&b| b == 0));
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_bytes_roundtrip() {
+ let b_in: crate::Bytes = [
+ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8,
+ ];
+
+ let u = Uuid::from_slice(&b_in).unwrap();
+
+ let b_out = u.as_bytes();
+
+ assert_eq!(&b_in, b_out);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_bytes_le_roundtrip() {
+ let b = [
+ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8,
+ ];
+
+ let u1 = Uuid::from_bytes(b);
+
+ let b_le = u1.to_bytes_le();
+
+ let u2 = Uuid::from_bytes_le(b_le);
+
+ assert_eq!(u1, u2);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_iterbytes_impl_for_uuid() {
+ let mut set = std::collections::HashSet::new();
+ let id1 = new();
+ let id2 = new2();
+ set.insert(id1.clone());
+
+ assert!(set.contains(&id1));
+ assert!(!set.contains(&id2));
+ }
+}
diff --git a/third_party/rust/uuid/src/macros.rs b/third_party/rust/uuid/src/macros.rs
new file mode 100644
index 0000000000..281c5335f2
--- /dev/null
+++ b/third_party/rust/uuid/src/macros.rs
@@ -0,0 +1,99 @@
+macro_rules! define_uuid_macro {
+ {$(#[$doc:meta])*} => {
+ $(#[$doc])*
+ #[cfg(feature = "macro-diagnostics")]
+ #[macro_export]
+ macro_rules! uuid {
+ ($uuid:literal) => {{
+ $crate::Uuid::from_bytes($crate::uuid_macro_internal::parse_lit!($uuid))
+ }};
+ }
+
+ $(#[$doc])*
+ #[cfg(not(feature = "macro-diagnostics"))]
+ #[macro_export]
+ macro_rules! uuid {
+ ($uuid:literal) => {{
+ const OUTPUT: $crate::Uuid = match $crate::Uuid::try_parse($uuid) {
+ Ok(u) => u,
+ Err(_) => {
+ // here triggers const_err
+ // const_panic requires 1.57
+ #[allow(unconditional_panic)]
+ let _ = ["invalid uuid representation"][1];
+
+ loop {} // -> never type
+ }
+ };
+ OUTPUT
+ }};
+ }
+ }
+}
+
+define_uuid_macro! {
+/// Parse [`Uuid`][uuid::Uuid]s from string literals at compile time.
+///
+/// ## Usage
+///
+/// This macro transforms the string literal representation of a
+/// [`Uuid`][uuid::Uuid] into the bytes representation, raising a compilation
+/// error if it cannot properly be parsed.
+///
+/// ## Examples
+///
+/// Setting a global constant:
+///
+/// ```
+/// # use uuid::{uuid, Uuid};
+/// pub const SCHEMA_ATTR_CLASS: Uuid = uuid!("00000000-0000-0000-0000-ffff00000000");
+/// pub const SCHEMA_ATTR_UUID: Uuid = uuid!("00000000-0000-0000-0000-ffff00000001");
+/// pub const SCHEMA_ATTR_NAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000002");
+/// ```
+///
+/// Defining a local variable:
+///
+/// ```
+/// # use uuid::uuid;
+/// let uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");
+/// ```
+///
+/// ## Compilation Failures
+///
+/// Invalid UUIDs are rejected:
+///
+/// ```compile_fail
+/// # use uuid::uuid;
+/// let uuid = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
+/// ```
+///
+/// Enable the feature `macro-diagnostics` to see the error messages below.
+///
+/// Provides the following compilation error:
+///
+/// ```txt
+/// error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found Z at 9
+/// |
+/// | let id = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
+/// | ^
+/// ```
+///
+/// Tokens that aren't string literals are also rejected:
+///
+/// ```compile_fail
+/// # use uuid::uuid;
+/// let uuid_str: &str = "550e8400e29b41d4a716446655440000";
+/// let uuid = uuid!(uuid_str);
+/// ```
+///
+/// Provides the following compilation error:
+///
+/// ```txt
+/// error: expected string literal
+/// |
+/// | let uuid = uuid!(uuid_str);
+/// | ^^^^^^^^
+/// ```
+///
+/// [uuid::Uuid]: https://docs.rs/uuid/*/uuid/struct.Uuid.html
+}
diff --git a/third_party/rust/uuid/src/md5.rs b/third_party/rust/uuid/src/md5.rs
new file mode 100644
index 0000000000..fce5d9b872
--- /dev/null
+++ b/third_party/rust/uuid/src/md5.rs
@@ -0,0 +1,14 @@
+#[cfg(feature = "v3")]
+pub(crate) fn hash(ns: &[u8], src: &[u8]) -> [u8; 16] {
+ use md_5::{Digest, Md5};
+
+ let mut hasher = Md5::new();
+
+ hasher.update(ns);
+ hasher.update(src);
+
+ let mut bytes = [0; 16];
+ bytes.copy_from_slice(&hasher.finalize()[..16]);
+
+ bytes
+}
diff --git a/third_party/rust/uuid/src/parser.rs b/third_party/rust/uuid/src/parser.rs
new file mode 100644
index 0000000000..bc5f82638d
--- /dev/null
+++ b/third_party/rust/uuid/src/parser.rs
@@ -0,0 +1,521 @@
+// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! [`Uuid`] parsing constructs and utilities.
+//!
+//! [`Uuid`]: ../struct.Uuid.html
+
+use crate::{
+ error::*,
+ std::{convert::TryFrom, str},
+ Uuid,
+};
+
+impl str::FromStr for Uuid {
+ type Err = Error;
+
+ fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {
+ Uuid::parse_str(uuid_str)
+ }
+}
+
+impl TryFrom<&'_ str> for Uuid {
+ type Error = Error;
+
+ fn try_from(uuid_str: &'_ str) -> Result<Self, Self::Error> {
+ Uuid::parse_str(uuid_str)
+ }
+}
+
+impl Uuid {
+ /// Parses a `Uuid` from a string of hexadecimal digits with optional
+ /// hyphens.
+ ///
+ /// Any of the formats generated by this module (simple, hyphenated, urn,
+ /// Microsoft GUID) are supported by this parsing function.
+ ///
+ /// Prefer [`try_parse`] unless you need detailed user-facing diagnostics.
+ /// This method will be eventually deprecated in favor of `try_parse`.
+ ///
+ /// # Examples
+ ///
+ /// Parse a hyphenated UUID:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version, Variant};
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000")?;
+ ///
+ /// assert_eq!(Some(Version::Random), uuid.get_version());
+ /// assert_eq!(Variant::RFC4122, uuid.get_variant());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`try_parse`]: #method.try_parse
+ pub fn parse_str(input: &str) -> Result<Uuid, Error> {
+ try_parse(input.as_bytes())
+ .map(Uuid::from_bytes)
+ .map_err(InvalidUuid::into_err)
+ }
+
+ /// Parses a `Uuid` from a string of hexadecimal digits with optional
+ /// hyphens.
+ ///
+ /// This function is similar to [`parse_str`], in fact `parse_str` shares
+ /// the same underlying parser. The difference is that if `try_parse`
+ /// fails, it won't generate very useful error messages. The `parse_str`
+ /// function will eventually be deprecated in favor or `try_parse`.
+ ///
+ /// To parse a UUID from a byte stream instead of a UTF8 string, see
+ /// [`try_parse_ascii`].
+ ///
+ /// # Examples
+ ///
+ /// Parse a hyphenated UUID:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version, Variant};
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::try_parse("550e8400-e29b-41d4-a716-446655440000")?;
+ ///
+ /// assert_eq!(Some(Version::Random), uuid.get_version());
+ /// assert_eq!(Variant::RFC4122, uuid.get_variant());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`parse_str`]: #method.parse_str
+ /// [`try_parse_ascii`]: #method.try_parse_ascii
+ pub const fn try_parse(input: &str) -> Result<Uuid, Error> {
+ Self::try_parse_ascii(input.as_bytes())
+ }
+
+ /// Parses a `Uuid` from a string of hexadecimal digits with optional
+ /// hyphens.
+ ///
+ /// The input is expected to be a string of ASCII characters. This method
+ /// can be more convenient than [`try_parse`] if the UUID is being
+ /// parsed from a byte stream instead of from a UTF8 string.
+ ///
+ /// # Examples
+ ///
+ /// Parse a hyphenated UUID:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version, Variant};
+ /// # fn main() -> Result<(), uuid::Error> {
+ /// let uuid = Uuid::try_parse_ascii(b"550e8400-e29b-41d4-a716-446655440000")?;
+ ///
+ /// assert_eq!(Some(Version::Random), uuid.get_version());
+ /// assert_eq!(Variant::RFC4122, uuid.get_variant());
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`try_parse`]: #method.try_parse
+ pub const fn try_parse_ascii(input: &[u8]) -> Result<Uuid, Error> {
+ match try_parse(input) {
+ Ok(bytes) => Ok(Uuid::from_bytes(bytes)),
+ // If parsing fails then we don't know exactly what went wrong
+ // In this case, we just return a generic error
+ Err(_) => Err(Error(ErrorKind::Other)),
+ }
+ }
+}
+
+const fn try_parse(input: &[u8]) -> Result<[u8; 16], InvalidUuid> {
+ let result = match (input.len(), input) {
+ // Inputs of 32 bytes must be a non-hyphenated UUID
+ (32, s) => parse_simple(s),
+ // Hyphenated UUIDs may be wrapped in various ways:
+ // - `{UUID}` for braced UUIDs
+ // - `urn:uuid:UUID` for URNs
+ // - `UUID` for a regular hyphenated UUID
+ (36, s)
+ | (38, [b'{', s @ .., b'}'])
+ | (45, [b'u', b'r', b'n', b':', b'u', b'u', b'i', b'd', b':', s @ ..]) => {
+ parse_hyphenated(s)
+ }
+ // Any other shaped input is immediately invalid
+ _ => Err(()),
+ };
+
+ match result {
+ Ok(b) => Ok(b),
+ Err(()) => Err(InvalidUuid(input)),
+ }
+}
+
+#[inline]
+const fn parse_simple(s: &[u8]) -> Result<[u8; 16], ()> {
+ // This length check here removes all other bounds
+ // checks in this function
+ if s.len() != 32 {
+ return Err(());
+ }
+
+ let mut buf: [u8; 16] = [0; 16];
+ let mut i = 0;
+
+ while i < 16 {
+ // Convert a two-char hex value (like `A8`)
+ // into a byte (like `10101000`)
+ let h1 = HEX_TABLE[s[i * 2] as usize];
+ let h2 = HEX_TABLE[s[i * 2 + 1] as usize];
+
+ // We use `0xff` as a sentinel value to indicate
+ // an invalid hex character sequence (like the letter `G`)
+ if h1 | h2 == 0xff {
+ return Err(());
+ }
+
+ // The upper nibble needs to be shifted into position
+ // to produce the final byte value
+ buf[i] = SHL4_TABLE[h1 as usize] | h2;
+ i += 1;
+ }
+
+ Ok(buf)
+}
+
+#[inline]
+const fn parse_hyphenated(s: &[u8]) -> Result<[u8; 16], ()> {
+ // This length check here removes all other bounds
+ // checks in this function
+ if s.len() != 36 {
+ return Err(());
+ }
+
+ // We look at two hex-encoded values (4 chars) at a time because
+ // that's the size of the smallest group in a hyphenated UUID.
+ // The indexes we're interested in are:
+ //
+ // uuid : 936da01f-9abd-4d9d-80c7-02af85c822a8
+ // | | || || || || | |
+ // hyphens : | | 8| 13| 18| 23| | |
+ // positions: 0 4 9 14 19 24 28 32
+
+ // First, ensure the hyphens appear in the right places
+ match [s[8], s[13], s[18], s[23]] {
+ [b'-', b'-', b'-', b'-'] => {}
+ _ => return Err(()),
+ }
+
+ let positions: [u8; 8] = [0, 4, 9, 14, 19, 24, 28, 32];
+ let mut buf: [u8; 16] = [0; 16];
+ let mut j = 0;
+
+ while j < 8 {
+ let i = positions[j];
+
+ // The decoding here is the same as the simple case
+ // We're just dealing with two values instead of one
+ let h1 = HEX_TABLE[s[i as usize] as usize];
+ let h2 = HEX_TABLE[s[(i + 1) as usize] as usize];
+ let h3 = HEX_TABLE[s[(i + 2) as usize] as usize];
+ let h4 = HEX_TABLE[s[(i + 3) as usize] as usize];
+
+ if h1 | h2 | h3 | h4 == 0xff {
+ return Err(());
+ }
+
+ buf[j * 2] = SHL4_TABLE[h1 as usize] | h2;
+ buf[j * 2 + 1] = SHL4_TABLE[h3 as usize] | h4;
+ j += 1;
+ }
+
+ Ok(buf)
+}
+
+const HEX_TABLE: &[u8; 256] = &{
+ let mut buf = [0; 256];
+ let mut i: u8 = 0;
+
+ loop {
+ buf[i as usize] = match i {
+ b'0'..=b'9' => i - b'0',
+ b'a'..=b'f' => i - b'a' + 10,
+ b'A'..=b'F' => i - b'A' + 10,
+ _ => 0xff,
+ };
+
+ if i == 255 {
+ break buf;
+ }
+
+ i += 1
+ }
+};
+
+const SHL4_TABLE: &[u8; 256] = &{
+ let mut buf = [0; 256];
+ let mut i: u8 = 0;
+
+ loop {
+ buf[i as usize] = i.wrapping_shl(4);
+
+ if i == 255 {
+ break buf;
+ }
+
+ i += 1;
+ }
+};
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{std::string::ToString, tests::new};
+
+ #[test]
+ fn test_parse_uuid_v4_valid() {
+ let from_hyphenated = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
+ let from_simple = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8").unwrap();
+ let from_urn = Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
+ let from_guid = Uuid::parse_str("{67e55044-10b1-426f-9247-bb680e5fe0c8}").unwrap();
+
+ assert_eq!(from_hyphenated, from_simple);
+ assert_eq!(from_hyphenated, from_urn);
+ assert_eq!(from_hyphenated, from_guid);
+
+ assert!(Uuid::parse_str("00000000000000000000000000000000").is_ok());
+ assert!(Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
+ assert!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
+ assert!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8").is_ok());
+ assert!(Uuid::parse_str("01020304-1112-2122-3132-414243444546").is_ok());
+ assert!(Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
+ assert!(Uuid::parse_str("{6d93bade-bd9f-4e13-8914-9474e1e3567b}").is_ok());
+
+ // Nil
+ let nil = Uuid::nil();
+ assert_eq!(
+ Uuid::parse_str("00000000000000000000000000000000").unwrap(),
+ nil
+ );
+ assert_eq!(
+ Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(),
+ nil
+ );
+ }
+
+ #[test]
+ fn test_parse_uuid_v4_invalid() {
+ // Invalid
+ assert_eq!(
+ Uuid::parse_str(""),
+ Err(Error(ErrorKind::SimpleLength { len: 0 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("!"),
+ Err(Error(ErrorKind::Char {
+ character: '!',
+ index: 1,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45"),
+ Err(Error(ErrorKind::GroupLength {
+ group: 4,
+ len: 13,
+ index: 25,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4"),
+ Err(Error(ErrorKind::GroupLength {
+ group: 3,
+ len: 3,
+ index: 20,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4"),
+ Err(Error(ErrorKind::Char {
+ character: 'G',
+ index: 21,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2F4faaFB6BFF329BF39FA1E4"),
+ Err(Error(ErrorKind::GroupCount { count: 2 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faaFB6BFF329BF39FA1E4"),
+ Err(Error(ErrorKind::GroupCount { count: 3 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4"),
+ Err(Error(ErrorKind::GroupCount { count: 4 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa"),
+ Err(Error(ErrorKind::GroupCount { count: 3 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4"),
+ Err(Error(ErrorKind::Char {
+ character: 'X',
+ index: 19,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("{F9168C5E-CEB2-4faa9B6BFF329BF39FA1E41"),
+ Err(Error(ErrorKind::Char {
+ character: '{',
+ index: 1,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("{F9168C5E-CEB2-4faa9B6BFF329BF39FA1E41}"),
+ Err(Error(ErrorKind::GroupCount { count: 3 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4"),
+ Err(Error(ErrorKind::GroupLength {
+ group: 1,
+ len: 3,
+ index: 10,
+ }))
+ );
+
+ // // (group, found, expecting)
+ // //
+ assert_eq!(
+ Uuid::parse_str("01020304-1112-2122-3132-41424344"),
+ Err(Error(ErrorKind::GroupLength {
+ group: 4,
+ len: 8,
+ index: 25,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c"),
+ Err(Error(ErrorKind::SimpleLength { len: 31 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88"),
+ Err(Error(ErrorKind::SimpleLength { len: 33 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8"),
+ Err(Error(ErrorKind::Char {
+ character: 'g',
+ index: 32,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8"),
+ Err(Error(ErrorKind::Char {
+ character: '%',
+ index: 16,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("231231212212423424324323477343246663"),
+ Err(Error(ErrorKind::SimpleLength { len: 36 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("{00000000000000000000000000000000}"),
+ Err(Error(ErrorKind::GroupCount { count: 1 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c"),
+ Err(Error(ErrorKind::SimpleLength { len: 31 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd"),
+ Err(Error(ErrorKind::Char {
+ character: 'X',
+ index: 7,
+ }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c"),
+ Err(Error(ErrorKind::GroupCount { count: 2 }))
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4"),
+ Err(Error(ErrorKind::GroupLength {
+ group: 3,
+ len: 5,
+ index: 20,
+ }))
+ );
+ }
+
+ #[test]
+ fn test_roundtrip_default() {
+ let uuid_orig = new();
+ let orig_str = uuid_orig.to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+ }
+
+ #[test]
+ fn test_roundtrip_hyphenated() {
+ let uuid_orig = new();
+ let orig_str = uuid_orig.hyphenated().to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+ }
+
+ #[test]
+ fn test_roundtrip_simple() {
+ let uuid_orig = new();
+ let orig_str = uuid_orig.simple().to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+ }
+
+ #[test]
+ fn test_roundtrip_urn() {
+ let uuid_orig = new();
+ let orig_str = uuid_orig.urn().to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+ }
+
+ #[test]
+ fn test_roundtrip_braced() {
+ let uuid_orig = new();
+ let orig_str = uuid_orig.braced().to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+ }
+
+ #[test]
+ fn test_try_parse_ascii_non_utf8() {
+ assert!(Uuid::try_parse_ascii(b"67e55044-10b1-426f-9247-bb680e5\0e0c8").is_err());
+ }
+}
diff --git a/third_party/rust/uuid/src/rng.rs b/third_party/rust/uuid/src/rng.rs
new file mode 100644
index 0000000000..dcfbb8d665
--- /dev/null
+++ b/third_party/rust/uuid/src/rng.rs
@@ -0,0 +1,39 @@
+#[cfg(any(feature = "v4", feature = "v7"))]
+pub(crate) fn bytes() -> [u8; 16] {
+ #[cfg(not(feature = "fast-rng"))]
+ {
+ let mut bytes = [0u8; 16];
+
+ getrandom::getrandom(&mut bytes).unwrap_or_else(|err| {
+ // NB: getrandom::Error has no source; this is adequate display
+ panic!("could not retrieve random bytes for uuid: {}", err)
+ });
+
+ bytes
+ }
+
+ #[cfg(feature = "fast-rng")]
+ {
+ rand::random()
+ }
+}
+
+#[cfg(any(feature = "v1", feature = "v6"))]
+pub(crate) fn u16() -> u16 {
+ #[cfg(not(feature = "fast-rng"))]
+ {
+ let mut bytes = [0u8; 2];
+
+ getrandom::getrandom(&mut bytes).unwrap_or_else(|err| {
+ // NB: getrandom::Error has no source; this is adequate display
+ panic!("could not retrieve random bytes for uuid: {}", err)
+ });
+
+ ((bytes[0] as u16) << 8) | (bytes[1] as u16)
+ }
+
+ #[cfg(feature = "fast-rng")]
+ {
+ rand::random()
+ }
+}
diff --git a/third_party/rust/uuid/src/sha1.rs b/third_party/rust/uuid/src/sha1.rs
new file mode 100644
index 0000000000..14ca302f28
--- /dev/null
+++ b/third_party/rust/uuid/src/sha1.rs
@@ -0,0 +1,14 @@
+#[cfg(feature = "v5")]
+pub(crate) fn hash(ns: &[u8], src: &[u8]) -> [u8; 16] {
+ use sha1_smol::Sha1;
+
+ let mut hasher = Sha1::new();
+
+ hasher.update(ns);
+ hasher.update(src);
+
+ let mut bytes = [0; 16];
+ bytes.copy_from_slice(&hasher.digest().bytes()[..16]);
+
+ bytes
+}
diff --git a/third_party/rust/uuid/src/timestamp.rs b/third_party/rust/uuid/src/timestamp.rs
new file mode 100644
index 0000000000..2f95ac4e93
--- /dev/null
+++ b/third_party/rust/uuid/src/timestamp.rs
@@ -0,0 +1,409 @@
+//! Generating UUIDs from timestamps.
+//!
+//! Timestamps are used in a few UUID versions as a source of decentralized
+//! uniqueness (as in versions 1 and 6), and as a way to enable sorting (as
+//! in versions 6 and 7). Timestamps aren't encoded the same way by all UUID
+//! versions so this module provides a single [`Timestamp`] type that can
+//! convert between them.
+//!
+//! # Timestamp representations in UUIDs
+//!
+//! Versions 1 and 6 UUIDs use a bespoke timestamp that consists of the
+//! number of 100ns ticks since `1582-10-15 00:00:00`, along with
+//! a counter value to avoid duplicates.
+//!
+//! Version 7 UUIDs use a more standard timestamp that consists of the
+//! number of millisecond ticks since the Unix epoch (`1970-01-01 00:00:00`).
+//!
+//! # References
+//!
+//! * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
+//! * [Timestamp in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-6.1)
+
+use crate::Uuid;
+
+/// The number of 100 nanosecond ticks between the RFC4122 epoch
+/// (`1582-10-15 00:00:00`) and the Unix epoch (`1970-01-01 00:00:00`).
+pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
+
+/// A timestamp that can be encoded into a UUID.
+///
+/// This type abstracts the specific encoding, so versions 1, 6, and 7
+/// UUIDs can both be supported through the same type, even
+/// though they have a different representation of a timestamp.
+///
+/// # References
+///
+/// * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
+/// * [Timestamp in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-6.1)
+/// * [Clock Sequence in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.5)
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Timestamp {
+ pub(crate) seconds: u64,
+ pub(crate) nanos: u32,
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ pub(crate) counter: u16,
+}
+
+impl Timestamp {
+ /// Get a timestamp representing the current system time.
+ ///
+ /// This method defers to the standard library's `SystemTime` type.
+ ///
+ /// # Panics
+ ///
+ /// This method will panic if calculating the elapsed time since the Unix epoch fails.
+ #[cfg(feature = "std")]
+ pub fn now(context: impl ClockSequence<Output = u16>) -> Self {
+ #[cfg(not(any(feature = "v1", feature = "v6")))]
+ {
+ let _ = context;
+ }
+
+ let (seconds, nanos) = now();
+
+ Timestamp {
+ seconds,
+ nanos,
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ counter: context.generate_sequence(seconds, nanos),
+ }
+ }
+
+ /// Construct a `Timestamp` from an RFC4122 timestamp and counter, as used
+ /// in versions 1 and 6 UUIDs.
+ pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
+ #[cfg(not(any(feature = "v1", feature = "v6")))]
+ {
+ let _ = counter;
+ }
+
+ let (seconds, nanos) = Self::rfc4122_to_unix(ticks);
+
+ Timestamp {
+ seconds,
+ nanos,
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ counter,
+ }
+ }
+
+ /// Construct a `Timestamp` from a Unix timestamp, as used in version 7 UUIDs.
+ pub fn from_unix(context: impl ClockSequence<Output = u16>, seconds: u64, nanos: u32) -> Self {
+ #[cfg(not(any(feature = "v1", feature = "v6")))]
+ {
+ let _ = context;
+
+ Timestamp { seconds, nanos }
+ }
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ {
+ let counter = context.generate_sequence(seconds, nanos);
+
+ Timestamp {
+ seconds,
+ nanos,
+ counter,
+ }
+ }
+ }
+
+ /// Get the value of the timestamp as an RFC4122 timestamp and counter,
+ /// as used in versions 1 and 6 UUIDs.
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ pub const fn to_rfc4122(&self) -> (u64, u16) {
+ (
+ Self::unix_to_rfc4122_ticks(self.seconds, self.nanos),
+ self.counter,
+ )
+ }
+
+ /// Get the value of the timestamp as a Unix timestamp, as used in version 7 UUIDs.
+ pub const fn to_unix(&self) -> (u64, u32) {
+ (self.seconds, self.nanos)
+ }
+
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ const fn unix_to_rfc4122_ticks(seconds: u64, nanos: u32) -> u64 {
+ let ticks = UUID_TICKS_BETWEEN_EPOCHS + seconds * 10_000_000 + nanos as u64 / 100;
+
+ ticks
+ }
+
+ const fn rfc4122_to_unix(ticks: u64) -> (u64, u32) {
+ (
+ (ticks - UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
+ ((ticks - UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32 * 100,
+ )
+ }
+
+ #[deprecated(note = "use `to_unix` instead")]
+ /// Get the number of fractional nanoseconds in the Unix timestamp.
+ ///
+ /// This method is deprecated and probably doesn't do what you're expecting it to.
+ /// It doesn't return the timestamp as nanoseconds since the Unix epoch, it returns
+ /// the fractional seconds of the timestamp.
+ pub const fn to_unix_nanos(&self) -> u32 {
+ // NOTE: This method never did what it said on the tin: instead of
+ // converting the timestamp into nanos it simply returned the nanoseconds
+ // part of the timestamp.
+ //
+ // We can't fix the behavior because the return type is too small to fit
+ // a useful value for nanoseconds since the epoch.
+ self.nanos
+ }
+}
+
+pub(crate) const fn encode_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Uuid {
+ let time_low = (ticks & 0xFFFF_FFFF) as u32;
+ let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
+ let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
+
+ let mut d4 = [0; 8];
+
+ d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
+ d4[1] = (counter & 0xFF) as u8;
+ d4[2] = node_id[0];
+ d4[3] = node_id[1];
+ d4[4] = node_id[2];
+ d4[5] = node_id[3];
+ d4[6] = node_id[4];
+ d4[7] = node_id[5];
+
+ Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
+}
+
+pub(crate) const fn decode_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
+ let bytes = uuid.as_bytes();
+
+ let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
+ | (bytes[7] as u64) << 48
+ | (bytes[4] as u64) << 40
+ | (bytes[5] as u64) << 32
+ | (bytes[0] as u64) << 24
+ | (bytes[1] as u64) << 16
+ | (bytes[2] as u64) << 8
+ | (bytes[3] as u64);
+
+ let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
+
+ (ticks, counter)
+}
+
+#[cfg(uuid_unstable)]
+pub(crate) const fn encode_sorted_rfc4122_timestamp(
+ ticks: u64,
+ counter: u16,
+ node_id: &[u8; 6],
+) -> Uuid {
+ let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
+ let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
+ let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
+
+ let mut d4 = [0; 8];
+
+ d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
+ d4[1] = (counter & 0xFF) as u8;
+ d4[2] = node_id[0];
+ d4[3] = node_id[1];
+ d4[4] = node_id[2];
+ d4[5] = node_id[3];
+ d4[6] = node_id[4];
+ d4[7] = node_id[5];
+
+ Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
+}
+
+#[cfg(uuid_unstable)]
+pub(crate) const fn decode_sorted_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
+ let bytes = uuid.as_bytes();
+
+ let ticks: u64 = ((bytes[0]) as u64) << 52
+ | (bytes[1] as u64) << 44
+ | (bytes[2] as u64) << 36
+ | (bytes[3] as u64) << 28
+ | (bytes[4] as u64) << 20
+ | (bytes[5] as u64) << 12
+ | ((bytes[6] & 0xF) as u64) << 8
+ | (bytes[7] as u64);
+
+ let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
+
+ (ticks, counter)
+}
+
+#[cfg(uuid_unstable)]
+pub(crate) const fn encode_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Uuid {
+ let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
+ let millis_low = (millis & 0xFFFF) as u16;
+
+ let random_and_version =
+ (random_bytes[0] as u16 | ((random_bytes[1] as u16) << 8) & 0x0FFF) | (0x7 << 12);
+
+ let mut d4 = [0; 8];
+
+ d4[0] = (random_bytes[2] & 0x3F) | 0x80;
+ d4[1] = random_bytes[3];
+ d4[2] = random_bytes[4];
+ d4[3] = random_bytes[5];
+ d4[4] = random_bytes[6];
+ d4[5] = random_bytes[7];
+ d4[6] = random_bytes[8];
+ d4[7] = random_bytes[9];
+
+ Uuid::from_fields(millis_high, millis_low, random_and_version, &d4)
+}
+
+#[cfg(uuid_unstable)]
+pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
+ let bytes = uuid.as_bytes();
+
+ let millis: u64 = (bytes[0] as u64) << 40
+ | (bytes[1] as u64) << 32
+ | (bytes[2] as u64) << 24
+ | (bytes[3] as u64) << 16
+ | (bytes[4] as u64) << 8
+ | (bytes[5] as u64);
+
+ millis
+}
+
+#[cfg(all(feature = "std", feature = "js", target_arch = "wasm32"))]
+fn now() -> (u64, u32) {
+ use wasm_bindgen::prelude::*;
+
+ #[wasm_bindgen]
+ extern "C" {
+ #[wasm_bindgen(js_namespace = Date)]
+ fn now() -> f64;
+ }
+
+ let now = now();
+
+ let secs = (now / 1_000.0) as u64;
+ let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
+
+ dbg!((secs, nanos))
+}
+
+#[cfg(all(feature = "std", any(not(feature = "js"), not(target_arch = "wasm32"))))]
+fn now() -> (u64, u32) {
+ let dur = std::time::SystemTime::UNIX_EPOCH
+ .elapsed()
+ .expect("Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality");
+
+ (dur.as_secs(), dur.subsec_nanos())
+}
+
+/// A counter that can be used by version 1 and version 6 UUIDs to support
+/// the uniqueness of timestamps.
+///
+/// # References
+///
+/// * [Clock Sequence in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.5)
+pub trait ClockSequence {
+ /// The type of sequence returned by this counter.
+ type Output;
+
+ /// Get the next value in the sequence to feed into a timestamp.
+ ///
+ /// This method will be called each time a [`Timestamp`] is constructed.
+ fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
+}
+
+impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
+ type Output = T::Output;
+ fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
+ (**self).generate_sequence(seconds, subsec_nanos)
+ }
+}
+
+/// Default implementations for the [`ClockSequence`] trait.
+pub mod context {
+ use super::ClockSequence;
+
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ use atomic::{Atomic, Ordering};
+
+ /// An empty counter that will always return the value `0`.
+ ///
+ /// This type should be used when constructing timestamps for version 7 UUIDs,
+ /// since they don't need a counter for uniqueness.
+ #[derive(Debug, Clone, Copy, Default)]
+ pub struct NoContext;
+
+ impl ClockSequence for NoContext {
+ type Output = u16;
+
+ fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
+ 0
+ }
+ }
+
+ #[cfg(all(any(feature = "v1", feature = "v6"), feature = "std", feature = "rng"))]
+ static CONTEXT: Context = Context {
+ count: Atomic::new(0),
+ };
+
+ #[cfg(all(any(feature = "v1", feature = "v6"), feature = "std", feature = "rng"))]
+ static CONTEXT_INITIALIZED: Atomic<bool> = Atomic::new(false);
+
+ #[cfg(all(any(feature = "v1", feature = "v6"), feature = "std", feature = "rng"))]
+ pub(crate) fn shared_context() -> &'static Context {
+ // If the context is in its initial state then assign it to a random value
+ // It doesn't matter if multiple threads observe `false` here and initialize the context
+ if CONTEXT_INITIALIZED
+ .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
+ .is_ok()
+ {
+ CONTEXT.count.store(crate::rng::u16(), Ordering::Release);
+ }
+
+ &CONTEXT
+ }
+
+ /// A thread-safe, wrapping counter that produces 14-bit numbers.
+ ///
+ /// This type should be used when constructing version 1 and version 6 UUIDs.
+ #[derive(Debug)]
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ pub struct Context {
+ count: Atomic<u16>,
+ }
+
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ impl Context {
+ /// Construct a new context that's initialized with the given value.
+ ///
+ /// The starting value should be a random number, so that UUIDs from
+ /// different systems with the same timestamps are less likely to collide.
+ /// When the `rng` feature is enabled, prefer the [`Context::new_random`] method.
+ pub const fn new(count: u16) -> Self {
+ Self {
+ count: Atomic::<u16>::new(count),
+ }
+ }
+
+ /// Construct a new context that's initialized with a random value.
+ #[cfg(feature = "rng")]
+ pub fn new_random() -> Self {
+ Self {
+ count: Atomic::<u16>::new(crate::rng::u16()),
+ }
+ }
+ }
+
+ #[cfg(any(feature = "v1", feature = "v6"))]
+ impl ClockSequence for Context {
+ type Output = u16;
+
+ fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
+ // RFC4122 reserves 2 bits of the clock sequence so the actual
+ // maximum value is smaller than `u16::MAX`. Since we unconditionally
+ // increment the clock sequence we want to wrap once it becomes larger
+ // than what we can represent in a "u14". Otherwise there'd be patches
+ // where the clock sequence doesn't change regardless of the timestamp
+ self.count.fetch_add(1, Ordering::AcqRel) % (u16::MAX >> 2)
+ }
+ }
+}
diff --git a/third_party/rust/uuid/src/v1.rs b/third_party/rust/uuid/src/v1.rs
new file mode 100644
index 0000000000..e19c8a3fba
--- /dev/null
+++ b/third_party/rust/uuid/src/v1.rs
@@ -0,0 +1,175 @@
+//! The implementation for Version 1 UUIDs.
+//!
+//! This module is soft-deprecated. Instead of using the `Context` type re-exported here,
+//! use the one from the crate root.
+
+use crate::{Builder, Uuid};
+
+#[deprecated(note = "use types from the crate root instead")]
+pub use crate::{timestamp::context::Context, Timestamp};
+
+impl Uuid {
+ /// Create a new version 1 UUID using the current system time and node ID.
+ ///
+ /// This method is only available if both the `std` and `rng` features are enabled.
+ ///
+ /// This method is a convenient alternative to [`Uuid::new_v1`] that uses the current system time
+ /// as the source timestamp.
+ ///
+ /// Note that usage of this method requires the `v1`, `std`, and `rng` features of this crate
+ /// to be enabled.
+ #[cfg(all(feature = "std", feature = "rng"))]
+ pub fn now_v1(node_id: &[u8; 6]) -> Self {
+ let ts = Timestamp::now(crate::timestamp::context::shared_context());
+
+ Self::new_v1(ts, node_id)
+ }
+
+ /// Create a new version 1 UUID using the given timestamp and node ID.
+ ///
+ /// Also see [`Uuid::now_v1`] for a convenient way to generate version 1
+ /// UUIDs using the current system time.
+ ///
+ /// When generating [`Timestamp`]s using a [`ClockSequence`], this function
+ /// is only guaranteed to produce unique values if the following conditions
+ /// hold:
+ ///
+ /// 1. The *node ID* is unique for this process,
+ /// 2. The *context* is shared across all threads which are generating version 1
+ /// UUIDs,
+ /// 3. The [`ClockSequence`] implementation reliably returns unique
+ /// clock sequences (this crate provides [`Context`] for this
+ /// purpose. However you can create your own [`ClockSequence`]
+ /// implementation, if [`Context`] does not meet your needs).
+ ///
+ /// Note that usage of this method requires the `v1` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// A UUID can be created from a unix [`Timestamp`] with a
+ /// [`ClockSequence`]. RFC4122 requires the clock sequence
+ /// is seeded with a random value:
+ ///
+ /// ```
+ /// # use uuid::{Timestamp, Context};
+ /// # use uuid::Uuid;
+ /// # fn random_seed() -> u16 { 42 }
+ /// let context = Context::new(random_seed());
+ /// let ts = Timestamp::from_unix(&context, 1497624119, 1234);
+ ///
+ /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "f3b4958c-52a1-11e7-802a-010203040506"
+ /// );
+ /// ```
+ ///
+ /// The timestamp can also be created manually as per RFC4122:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Timestamp, Context, ClockSequence};
+ /// let context = Context::new(42);
+ /// let ts = Timestamp::from_rfc4122(14976234442241191232, context.generate_sequence(0, 0));
+ ///
+ /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "b2c1ad40-45e0-1fd6-802a-010203040506"
+ /// );
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 1 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.2)
+ ///
+ /// [`Timestamp`]: v1/struct.Timestamp.html
+ /// [`ClockSequence`]: v1/trait.ClockSequence.html
+ /// [`Context`]: v1/struct.Context.html
+ pub fn new_v1(ts: Timestamp, node_id: &[u8; 6]) -> Self {
+ let (ticks, counter) = ts.to_rfc4122();
+
+ Builder::from_rfc4122_timestamp(ticks, counter, node_id).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use crate::{std::string::ToString, Variant, Version};
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ let time: u64 = 1_496_854_535;
+ let time_fraction: u32 = 812_946_000;
+ let node = [1, 2, 3, 4, 5, 6];
+ let context = Context::new(0);
+
+ let uuid = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ assert_eq!(uuid.get_version(), Some(Version::Mac));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ assert_eq!(
+ uuid.hyphenated().to_string(),
+ "20616934-4ba2-11e7-8000-010203040506"
+ );
+
+ let ts = uuid.get_timestamp().unwrap().to_rfc4122();
+
+ assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
+
+ // Ensure parsing the same UUID produces the same timestamp
+ let parsed = Uuid::parse_str("20616934-4ba2-11e7-8000-010203040506").unwrap();
+
+ assert_eq!(
+ uuid.get_timestamp().unwrap(),
+ parsed.get_timestamp().unwrap()
+ );
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ #[cfg(all(feature = "std", feature = "rng"))]
+ fn test_now() {
+ let node = [1, 2, 3, 4, 5, 6];
+
+ let uuid = Uuid::now_v1(&node);
+
+ assert_eq!(uuid.get_version(), Some(Version::Mac));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new_context() {
+ let time: u64 = 1_496_854_535;
+ let time_fraction: u32 = 812_946_000;
+ let node = [1, 2, 3, 4, 5, 6];
+
+ // This context will wrap
+ let context = Context::new((u16::MAX >> 2) - 1);
+
+ let uuid1 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ let time: u64 = 1_496_854_536;
+
+ let uuid2 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ assert_eq!(uuid1.get_timestamp().unwrap().to_rfc4122().1, 16382);
+ assert_eq!(uuid2.get_timestamp().unwrap().to_rfc4122().1, 0);
+
+ let time = 1_496_854_535;
+
+ let uuid3 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
+ let uuid4 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ assert_eq!(uuid3.get_timestamp().unwrap().to_rfc4122().1, 1);
+ assert_eq!(uuid4.get_timestamp().unwrap().to_rfc4122().1, 2);
+ }
+}
diff --git a/third_party/rust/uuid/src/v3.rs b/third_party/rust/uuid/src/v3.rs
new file mode 100644
index 0000000000..cc7cb9ac39
--- /dev/null
+++ b/third_party/rust/uuid/src/v3.rs
@@ -0,0 +1,151 @@
+use crate::Uuid;
+
+impl Uuid {
+ /// Creates a UUID using a name from a namespace, based on the MD5
+ /// hash.
+ ///
+ /// A number of namespaces are available as constants in this crate:
+ ///
+ /// * [`NAMESPACE_DNS`]
+ /// * [`NAMESPACE_OID`]
+ /// * [`NAMESPACE_URL`]
+ /// * [`NAMESPACE_X500`]
+ ///
+ /// Note that usage of this method requires the `v3` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// Generating a MD5 DNS UUID for `rust-lang.org`:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version};
+ /// let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, b"rust-lang.org");
+ ///
+ /// assert_eq!(Some(Version::Md5), uuid.get_version());
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 3 and 5 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.3)
+ ///
+ /// [`NAMESPACE_DNS`]: #associatedconstant.NAMESPACE_DNS
+ /// [`NAMESPACE_OID`]: #associatedconstant.NAMESPACE_OID
+ /// [`NAMESPACE_URL`]: #associatedconstant.NAMESPACE_URL
+ /// [`NAMESPACE_X500`]: #associatedconstant.NAMESPACE_X500
+ pub fn new_v3(namespace: &Uuid, name: &[u8]) -> Uuid {
+ crate::Builder::from_md5_bytes(crate::md5::hash(namespace.as_bytes(), name)).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ use crate::{std::string::ToString, Variant, Version};
+
+ static FIXTURE: &'static [(&'static Uuid, &'static str, &'static str)] = &[
+ (
+ &Uuid::NAMESPACE_DNS,
+ "example.org",
+ "04738bdf-b25a-3829-a801-b21a1d25095b",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "rust-lang.org",
+ "c6db027c-615c-3b4d-959e-1a917747ca5a",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "42",
+ "5aab6e0c-b7d3-379c-92e3-2bfbb5572511",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "lorem ipsum",
+ "4f8772e9-b59c-3cc9-91a9-5c823df27281",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "example.org",
+ "39682ca1-9168-3da2-a1bb-f4dbcde99bf9",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "rust-lang.org",
+ "7ed45aaf-e75b-3130-8e33-ee4d9253b19f",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "42",
+ "08998a0c-fcf4-34a9-b444-f2bfc15731dc",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "lorem ipsum",
+ "e55ad2e6-fb89-34e8-b012-c5dde3cd67f0",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "example.org",
+ "f14eec63-2812-3110-ad06-1625e5a4a5b2",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "rust-lang.org",
+ "6506a0ec-4d79-3e18-8c2b-f2b6b34f2b6d",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "42",
+ "ce6925a5-2cd7-327b-ab1c-4b375ac044e4",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "lorem ipsum",
+ "5dd8654f-76ba-3d47-bc2e-4d6d3a78cb09",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "example.org",
+ "64606f3f-bd63-363e-b946-fca13611b6f7",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "rust-lang.org",
+ "bcee7a9c-52f1-30c6-a3cc-8c72ba634990",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "42",
+ "c1073fa2-d4a6-3104-b21d-7a6bdcf39a23",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "lorem ipsum",
+ "02f09a3f-1624-3b1d-8409-44eff7708208",
+ ),
+ ];
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ for &(ref ns, ref name, _) in FIXTURE {
+ let uuid = Uuid::new_v3(*ns, name.as_bytes());
+ assert_eq!(uuid.get_version(), Some(Version::Md5));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ }
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_hyphenated_string() {
+ for &(ref ns, ref name, ref expected) in FIXTURE {
+ let uuid = Uuid::new_v3(*ns, name.as_bytes());
+ assert_eq!(uuid.hyphenated().to_string(), *expected);
+ }
+ }
+}
diff --git a/third_party/rust/uuid/src/v4.rs b/third_party/rust/uuid/src/v4.rs
new file mode 100644
index 0000000000..e78fb1e69a
--- /dev/null
+++ b/third_party/rust/uuid/src/v4.rs
@@ -0,0 +1,63 @@
+use crate::Uuid;
+
+impl Uuid {
+ /// Creates a random UUID.
+ ///
+ /// This uses the [`getrandom`] crate to utilise the operating system's RNG
+ /// as the source of random numbers. If you'd like to use a custom
+ /// generator, don't use this method: generate random bytes using your
+ /// custom generator and pass them to the
+ /// [`uuid::Builder::from_random_bytes`][from_random_bytes] function
+ /// instead.
+ ///
+ /// Note that usage of this method requires the `v4` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version};
+ /// let uuid = Uuid::new_v4();
+ ///
+ /// assert_eq!(Some(Version::Random), uuid.get_version());
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 4 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.4)
+ ///
+ /// [`getrandom`]: https://crates.io/crates/getrandom
+ /// [from_random_bytes]: struct.Builder.html#method.from_random_bytes
+ pub fn new_v4() -> Uuid {
+ crate::Builder::from_random_bytes(crate::rng::bytes()).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{Variant, Version};
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ let uuid = Uuid::new_v4();
+
+ assert_eq!(uuid.get_version(), Some(Version::Random));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_get_version() {
+ let uuid = Uuid::new_v4();
+
+ assert_eq!(uuid.get_version(), Some(Version::Random));
+ assert_eq!(uuid.get_version_num(), 4)
+ }
+}
diff --git a/third_party/rust/uuid/src/v5.rs b/third_party/rust/uuid/src/v5.rs
new file mode 100644
index 0000000000..c3dd44795d
--- /dev/null
+++ b/third_party/rust/uuid/src/v5.rs
@@ -0,0 +1,162 @@
+use crate::Uuid;
+
+impl Uuid {
+ /// Creates a UUID using a name from a namespace, based on the SHA-1 hash.
+ ///
+ /// A number of namespaces are available as constants in this crate:
+ ///
+ /// * [`NAMESPACE_DNS`]
+ /// * [`NAMESPACE_OID`]
+ /// * [`NAMESPACE_URL`]
+ /// * [`NAMESPACE_X500`]
+ ///
+ /// Note that usage of this method requires the `v5` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// Generating a SHA1 DNS UUID for `rust-lang.org`:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version};
+ /// let uuid = Uuid::new_v5(&Uuid::NAMESPACE_DNS, b"rust-lang.org");
+ ///
+ /// assert_eq!(Some(Version::Sha1), uuid.get_version());
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 3 and 5 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.3)
+ ///
+ /// [`NAMESPACE_DNS`]: struct.Uuid.html#associatedconst.NAMESPACE_DNS
+ /// [`NAMESPACE_OID`]: struct.Uuid.html#associatedconst.NAMESPACE_OID
+ /// [`NAMESPACE_URL`]: struct.Uuid.html#associatedconst.NAMESPACE_URL
+ /// [`NAMESPACE_X500`]: struct.Uuid.html#associatedconst.NAMESPACE_X500
+ pub fn new_v5(namespace: &Uuid, name: &[u8]) -> Uuid {
+ crate::Builder::from_sha1_bytes(crate::sha1::hash(namespace.as_bytes(), name)).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ use crate::{std::string::ToString, Variant, Version};
+
+ static FIXTURE: &'static [(&'static Uuid, &'static str, &'static str)] = &[
+ (
+ &Uuid::NAMESPACE_DNS,
+ "example.org",
+ "aad03681-8b63-5304-89e0-8ca8f49461b5",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "rust-lang.org",
+ "c66bbb60-d62e-5f17-a399-3a0bd237c503",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "42",
+ "7c411b5e-9d3f-50b5-9c28-62096e41c4ed",
+ ),
+ (
+ &Uuid::NAMESPACE_DNS,
+ "lorem ipsum",
+ "97886a05-8a68-5743-ad55-56ab2d61cf7b",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "example.org",
+ "54a35416-963c-5dd6-a1e2-5ab7bb5bafc7",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "rust-lang.org",
+ "c48d927f-4122-5413-968c-598b1780e749",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "42",
+ "5c2b23de-4bad-58ee-a4b3-f22f3b9cfd7d",
+ ),
+ (
+ &Uuid::NAMESPACE_URL,
+ "lorem ipsum",
+ "15c67689-4b85-5253-86b4-49fbb138569f",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "example.org",
+ "34784df9-b065-5094-92c7-00bb3da97a30",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "rust-lang.org",
+ "8ef61ecb-977a-5844-ab0f-c25ef9b8d5d6",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "42",
+ "ba293c61-ad33-57b9-9671-f3319f57d789",
+ ),
+ (
+ &Uuid::NAMESPACE_OID,
+ "lorem ipsum",
+ "6485290d-f79e-5380-9e64-cb4312c7b4a6",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "example.org",
+ "e3635e86-f82b-5bbc-a54a-da97923e5c76",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "rust-lang.org",
+ "26c9c3e9-49b7-56da-8b9f-a0fb916a71a3",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "42",
+ "e4b88014-47c6-5fe0-a195-13710e5f6e27",
+ ),
+ (
+ &Uuid::NAMESPACE_X500,
+ "lorem ipsum",
+ "b11f79a5-1e6d-57ce-a4b5-ba8531ea03d0",
+ ),
+ ];
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_get_version() {
+ let uuid = Uuid::new_v5(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
+
+ assert_eq!(uuid.get_version(), Some(Version::Sha1));
+ assert_eq!(uuid.get_version_num(), 5);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_hyphenated() {
+ for &(ref ns, ref name, ref expected) in FIXTURE {
+ let uuid = Uuid::new_v5(*ns, name.as_bytes());
+
+ assert_eq!(uuid.hyphenated().to_string(), *expected)
+ }
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ for &(ref ns, ref name, ref u) in FIXTURE {
+ let uuid = Uuid::new_v5(*ns, name.as_bytes());
+
+ assert_eq!(uuid.get_version(), Some(Version::Sha1));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ assert_eq!(Ok(uuid), u.parse());
+ }
+ }
+}
diff --git a/third_party/rust/uuid/src/v6.rs b/third_party/rust/uuid/src/v6.rs
new file mode 100644
index 0000000000..07644fd4fa
--- /dev/null
+++ b/third_party/rust/uuid/src/v6.rs
@@ -0,0 +1,177 @@
+//! The implementation for Version 6 UUIDs.
+//!
+//! Note that you need to enable the `v6` Cargo feature
+//! in order to use this module.
+
+use crate::{Builder, Timestamp, Uuid};
+
+impl Uuid {
+ /// Create a new version 6 UUID using the current system time and node ID.
+ ///
+ /// This method is only available if the `std` feature is enabled.
+ ///
+ /// This method is a convenient alternative to [`Uuid::new_v6`] that uses the current system time
+ /// as the source timestamp.
+ ///
+ /// Note that usage of this method requires the `v6`, `std`, and `rng` features of this crate
+ /// to be enabled.
+ #[cfg(all(feature = "std", feature = "rng"))]
+ pub fn now_v6(node_id: &[u8; 6]) -> Self {
+ let ts = Timestamp::now(crate::timestamp::context::shared_context());
+
+ Self::new_v6(ts, node_id)
+ }
+
+ /// Create a new version 6 UUID using the given timestamp and a node ID.
+ ///
+ /// This is similar to version 1 UUIDs, except that it is lexicographically sortable by timestamp.
+ ///
+ /// Also see [`Uuid::now_v6`] for a convenient way to generate version 6
+ /// UUIDs using the current system time.
+ ///
+ /// When generating [`Timestamp`]s using a [`ClockSequence`], this function
+ /// is only guaranteed to produce unique values if the following conditions
+ /// hold:
+ ///
+ /// 1. The *node ID* is unique for this process,
+ /// 2. The *context* is shared across all threads which are generating version 6
+ /// UUIDs,
+ /// 3. The [`ClockSequence`] implementation reliably returns unique
+ /// clock sequences (this crate provides [`Context`] for this
+ /// purpose. However you can create your own [`ClockSequence`]
+ /// implementation, if [`Context`] does not meet your needs).
+ ///
+ /// The NodeID must be exactly 6 bytes long.
+ ///
+ /// Note that usage of this method requires the `v6` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// A UUID can be created from a unix [`Timestamp`] with a
+ /// [`ClockSequence`]. RFC4122 requires the clock sequence
+ /// is seeded with a random value:
+ ///
+ /// ```rust
+ /// # use uuid::{Uuid, Timestamp, Context};
+ /// # fn random_seed() -> u16 { 42 }
+ /// let context = Context::new(random_seed());
+ /// let ts = Timestamp::from_unix(context, 1497624119, 1234);
+ ///
+ /// let uuid = Uuid::new_v6(ts, &[1, 2, 3, 4, 5, 6]);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "1e752a1f-3b49-658c-802a-010203040506"
+ /// );
+ /// ```
+ ///
+ /// The timestamp can also be created manually as per RFC4122:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Timestamp, Context, ClockSequence};
+ /// # fn random_seed() -> u16 { 42 }
+ /// let context = Context::new(random_seed());
+ /// let ts = Timestamp::from_rfc4122(14976241191231231313, context.generate_sequence(0, 0) );
+ ///
+ /// let uuid = Uuid::new_v6(ts, &[1, 2, 3, 4, 5, 6]);
+ ///
+ /// assert_eq!(
+ /// uuid.hyphenated().to_string(),
+ /// "fd64c041-1e91-6551-802a-010203040506"
+ /// );
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 6 UUIDs in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.1)
+ ///
+ /// [`Timestamp`]: v1/struct.Timestamp.html
+ /// [`ClockSequence`]: v1/trait.ClockSequence.html
+ /// [`Context`]: v1/struct.Context.html
+ pub fn new_v6(ts: Timestamp, node_id: &[u8; 6]) -> Self {
+ let (ticks, counter) = ts.to_rfc4122();
+
+ Builder::from_sorted_rfc4122_timestamp(ticks, counter, node_id).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{Context, Variant, Version};
+ use std::string::ToString;
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ let time: u64 = 1_496_854_535;
+ let time_fraction: u32 = 812_946_000;
+ let node = [1, 2, 3, 4, 5, 6];
+ let context = Context::new(0);
+
+ let uuid = Uuid::new_v6(Timestamp::from_unix(context, time, time_fraction), &node);
+
+ assert_eq!(uuid.get_version(), Some(Version::SortMac));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ assert_eq!(
+ uuid.hyphenated().to_string(),
+ "1e74ba22-0616-6934-8000-010203040506"
+ );
+
+ let ts = uuid.get_timestamp().unwrap().to_rfc4122();
+
+ assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
+
+ // Ensure parsing the same UUID produces the same timestamp
+ let parsed = Uuid::parse_str("1e74ba22-0616-6934-8000-010203040506").unwrap();
+
+ assert_eq!(
+ uuid.get_timestamp().unwrap(),
+ parsed.get_timestamp().unwrap()
+ );
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ #[cfg(all(feature = "std", feature = "rng"))]
+ fn test_now() {
+ let node = [1, 2, 3, 4, 5, 6];
+
+ let uuid = Uuid::now_v6(&node);
+
+ assert_eq!(uuid.get_version(), Some(Version::SortMac));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new_context() {
+ let time: u64 = 1_496_854_535;
+ let time_fraction: u32 = 812_946_000;
+ let node = [1, 2, 3, 4, 5, 6];
+
+ // This context will wrap
+ let context = Context::new((u16::MAX >> 2) - 1);
+
+ let uuid1 = Uuid::new_v6(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ let time: u64 = 1_496_854_536;
+
+ let uuid2 = Uuid::new_v6(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ assert_eq!(uuid1.get_timestamp().unwrap().to_rfc4122().1, 16382);
+ assert_eq!(uuid2.get_timestamp().unwrap().to_rfc4122().1, 0);
+
+ let time = 1_496_854_535;
+
+ let uuid3 = Uuid::new_v6(Timestamp::from_unix(&context, time, time_fraction), &node);
+ let uuid4 = Uuid::new_v6(Timestamp::from_unix(&context, time, time_fraction), &node);
+
+ assert_eq!(uuid3.get_timestamp().unwrap().counter, 1);
+ assert_eq!(uuid4.get_timestamp().unwrap().counter, 2);
+ }
+}
diff --git a/third_party/rust/uuid/src/v7.rs b/third_party/rust/uuid/src/v7.rs
new file mode 100644
index 0000000000..4497ea3f51
--- /dev/null
+++ b/third_party/rust/uuid/src/v7.rs
@@ -0,0 +1,124 @@
+//! The implementation for Version 7 UUIDs.
+//!
+//! Note that you need to enable the `v7` Cargo feature
+//! in order to use this module.
+
+use crate::{std::convert::TryInto, rng, timestamp::Timestamp, Builder, Uuid};
+
+impl Uuid {
+ /// Create a new version 7 UUID using the current time value and random bytes.
+ ///
+ /// This method is a convenient alternative to [`Uuid::new_v7`] that uses the current system time
+ /// as the source timestamp.
+ #[cfg(feature = "std")]
+ pub fn now_v7() -> Self {
+ Self::new_v7(Timestamp::now(crate::NoContext))
+ }
+
+ /// Create a new version 7 UUID using a time value and random bytes.
+ ///
+ /// When the `std` feature is enabled, you can also use [`Uuid::now_v7`].
+ ///
+ /// Note that usage of this method requires the `v7` feature of this crate
+ /// to be enabled.
+ ///
+ /// Also see [`Uuid::now_v7`] for a convenient way to generate version 7
+ /// UUIDs using the current system time.
+ ///
+ /// # Examples
+ ///
+ /// A v7 UUID can be created from a unix [`Timestamp`] plus a 128 bit
+ /// random number. When supplied as such, the data will be
+ ///
+ /// ```rust
+ /// # use uuid::{Uuid, Timestamp, NoContext};
+ /// let ts = Timestamp::from_unix(NoContext, 1497624119, 1234);
+ ///
+ /// let uuid = Uuid::new_v7(ts);
+ ///
+ /// assert!(
+ /// uuid.hyphenated().to_string().starts_with("015cb15a-86d8-7")
+ /// );
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 7 UUIDs in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.2)
+ pub fn new_v7(ts: Timestamp) -> Self {
+ let (secs, nanos) = ts.to_unix();
+ let millis = (secs * 1000).saturating_add(nanos as u64 / 1_000_000);
+
+ Builder::from_unix_timestamp_millis(millis, &rng::bytes()[..10].try_into().unwrap())
+ .into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{std::string::ToString, NoContext, Variant, Version};
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ let ts: u64 = 1645557742000;
+
+ let seconds = ts / 1000;
+ let nanos = ((ts % 1000) * 1_000_000) as u32;
+
+ let uuid = Uuid::new_v7(Timestamp::from_unix(NoContext, seconds, nanos));
+ let uustr = uuid.hyphenated().to_string();
+
+ assert_eq!(uuid.get_version(), Some(Version::SortRand));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ assert!(uuid.hyphenated().to_string().starts_with("017f22e2-79b0-7"));
+
+ // Ensure parsing the same UUID produces the same timestamp
+ let parsed = Uuid::parse_str(uustr.as_str()).unwrap();
+
+ assert_eq!(uuid, parsed);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ #[cfg(feature = "std")]
+ fn test_now() {
+ let uuid = Uuid::now_v7();
+
+ assert_eq!(uuid.get_version(), Some(Version::SortRand));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_sorting() {
+ let time1: u64 = 1_496_854_535;
+ let time_fraction1: u32 = 812_000_000;
+
+ let time2 = time1 + 4000;
+ let time_fraction2 = time_fraction1;
+
+ let uuid1 = Uuid::new_v7(Timestamp::from_unix(NoContext, time1, time_fraction1));
+ let uuid2 = Uuid::new_v7(Timestamp::from_unix(NoContext, time2, time_fraction2));
+
+ assert!(uuid1.as_bytes() < uuid2.as_bytes());
+ assert!(uuid1.to_string() < uuid2.to_string());
+ }
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new_timestamp_roundtrip() {
+ let time: u64 = 1_496_854_535;
+ let time_fraction: u32 = 812_000_000;
+
+ let ts = Timestamp::from_unix(NoContext, time, time_fraction);
+
+ let uuid = Uuid::new_v7(ts);
+
+ let decoded_ts = uuid.get_timestamp().unwrap();
+
+ assert_eq!(ts.to_unix(), decoded_ts.to_unix());
+ }
+}
diff --git a/third_party/rust/uuid/src/v8.rs b/third_party/rust/uuid/src/v8.rs
new file mode 100644
index 0000000000..a54a979805
--- /dev/null
+++ b/third_party/rust/uuid/src/v8.rs
@@ -0,0 +1,57 @@
+use crate::{Builder, Uuid};
+
+impl Uuid {
+ /// Creates a custom UUID comprised almost entirely of user-supplied bytes.
+ ///
+ /// This will inject the UUID Version at 4 bits starting at the 48th bit
+ /// and the Variant into 2 bits 64th bit. Any existing bits in the user-supplied bytes
+ /// at those locations will be overridden.
+ ///
+ /// Note that usage of this method requires the `v8` feature of this crate
+ /// to be enabled.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # use uuid::{Uuid, Version};
+ /// let buf: [u8; 16] = *b"abcdefghijklmnop";
+ /// let uuid = Uuid::new_v8(buf);
+ ///
+ /// assert_eq!(Some(Version::Custom), uuid.get_version());
+ /// ```
+ ///
+ /// # References
+ ///
+ /// * [Version 8 UUIDs in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.3)
+ pub fn new_v8(buf: [u8; 16]) -> Uuid {
+ Builder::from_custom_bytes(buf).into_uuid()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{Variant, Version};
+ use std::string::ToString;
+
+ #[cfg(target_arch = "wasm32")]
+ use wasm_bindgen_test::*;
+
+ #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn test_new() {
+ let buf: [u8; 16] = [
+ 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
+ ];
+ let uuid = Uuid::new_v8(buf);
+ assert_eq!(uuid.get_version(), Some(Version::Custom));
+ assert_eq!(uuid.get_variant(), Variant::RFC4122);
+ assert_eq!(uuid.get_version_num(), 8);
+ assert_eq!(
+ uuid.hyphenated().to_string(),
+ "0f0e0d0c-0b0a-8908-8706-050403020100"
+ );
+ }
+}
diff --git a/third_party/rust/uuid/tests/macros.rs b/third_party/rust/uuid/tests/macros.rs
new file mode 100644
index 0000000000..c7cf2a4298
--- /dev/null
+++ b/third_party/rust/uuid/tests/macros.rs
@@ -0,0 +1,11 @@
+#[cfg(feature = "macro-diagnostics")]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+
+ t.pass("tests/ui/compile_pass/*.rs");
+
+ if rustversion::cfg!(nightly) {
+ t.compile_fail("tests/ui/compile_fail/*.rs");
+ }
+}
diff --git a/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.rs b/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.rs
new file mode 100644
index 0000000000..f67456b935
--- /dev/null
+++ b/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.rs
@@ -0,0 +1,45 @@
+use uuid::{uuid, Uuid};
+
+const _: Uuid = uuid!("");
+const _: Uuid = uuid!("!");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4");
+const _: Uuid = uuid!("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4");
+const _: Uuid = uuid!("01020304-1112-2122-3132-41424344");
+const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c88");
+const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0cg8");
+const _: Uuid = uuid!("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8");
+
+// Test error reporting
+const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c");
+const _: Uuid = uuid!("67e550X410b1426f9247bb680e5fe0cd");
+const _: Uuid = uuid!("67e550-4105b1426f9247bb680e5fe0c");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4");
+
+
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+const _: Uuid = uuid!("01020304-1112-2122-3132-41424344");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");
+const _: Uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+const _: Uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-B2cBF-32BF39FA1E4");
+const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-B0a75-32BF39FA1E4}");
+
+const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-B6BF-329Bz39FA1E4}");
+
+// group 0 has invalid length
+const _: Uuid = uuid!("67e550-4105b1426f9247bb680e5fe0c");
+
+const _: Uuid = uuid!("504410岡林aab1426f9247bb680e5fe0c8");
+const _: Uuid = uuid!("504410😎👍aab1426f9247bb680e5fe0c8");
+
+const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-👍5-32BF39FA1E4}");
+
+const _: Uuid = uuid!("F916");
+const _: Uuid = uuid!("F916x");
+
+fn main() {}
diff --git a/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.stderr b/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.stderr
new file mode 100644
index 0000000000..b630494975
--- /dev/null
+++ b/third_party/rust/uuid/tests/ui/compile_fail/invalid_parse.stderr
@@ -0,0 +1,197 @@
+error: invalid length: expected length 32 for simple format, found 0
+ --> tests/ui/compile_fail/invalid_parse.rs:3:17
+ |
+3 | const _: Uuid = uuid!("");
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `!` at 1
+ --> tests/ui/compile_fail/invalid_parse.rs:4:24
+ |
+4 | const _: Uuid = uuid!("!");
+ | ^
+
+error: invalid group length in group 4: expected 12, found 13
+ --> tests/ui/compile_fail/invalid_parse.rs:5:48
+ |
+5 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45");
+ | ^^^^^^^^^^^^^
+
+error: invalid group length in group 3: expected 4, found 3
+ --> tests/ui/compile_fail/invalid_parse.rs:6:43
+ |
+6 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");
+ | ^^^
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `G` at 21
+ --> tests/ui/compile_fail/invalid_parse.rs:7:44
+ |
+7 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+ | ^
+
+error: invalid group count: expected 5, found 4
+ --> tests/ui/compile_fail/invalid_parse.rs:8:17
+ |
+8 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid group count: expected 5, found 3
+ --> tests/ui/compile_fail/invalid_parse.rs:9:17
+ |
+9 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `X` at 19
+ --> tests/ui/compile_fail/invalid_parse.rs:10:42
+ |
+10 | const _: Uuid = uuid!("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4");
+ | ^
+
+error: invalid group length in group 1: expected 4, found 3
+ --> tests/ui/compile_fail/invalid_parse.rs:11:33
+ |
+11 | const _: Uuid = uuid!("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4");
+ | ^^^
+
+error: invalid group length in group 4: expected 12, found 8
+ --> tests/ui/compile_fail/invalid_parse.rs:12:48
+ |
+12 | const _: Uuid = uuid!("01020304-1112-2122-3132-41424344");
+ | ^^^^^^^^
+
+error: invalid length: expected length 32 for simple format, found 33
+ --> tests/ui/compile_fail/invalid_parse.rs:13:17
+ |
+13 | const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c88");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `g` at 32
+ --> tests/ui/compile_fail/invalid_parse.rs:14:55
+ |
+14 | const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0cg8");
+ | ^
+
+error: invalid length: expected length 32 for simple format, found 31
+ --> tests/ui/compile_fail/invalid_parse.rs:18:17
+ |
+18 | const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `X` at 7
+ --> tests/ui/compile_fail/invalid_parse.rs:19:30
+ |
+19 | const _: Uuid = uuid!("67e550X410b1426f9247bb680e5fe0cd");
+ | ^
+
+error: invalid group count: expected 5, found 2
+ --> tests/ui/compile_fail/invalid_parse.rs:20:17
+ |
+20 | const _: Uuid = uuid!("67e550-4105b1426f9247bb680e5fe0c");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid group length in group 3: expected 4, found 5
+ --> tests/ui/compile_fail/invalid_parse.rs:21:43
+ |
+21 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4");
+ | ^^^^^
+
+error: invalid group length in group 3: expected 4, found 3
+ --> tests/ui/compile_fail/invalid_parse.rs:24:43
+ |
+24 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");
+ | ^^^
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `G` at 21
+ --> tests/ui/compile_fail/invalid_parse.rs:25:44
+ |
+25 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+ | ^
+
+error: invalid group length in group 4: expected 12, found 8
+ --> tests/ui/compile_fail/invalid_parse.rs:26:48
+ |
+26 | const _: Uuid = uuid!("01020304-1112-2122-3132-41424344");
+ | ^^^^^^^^
+
+error: invalid group count: expected 5, found 4
+ --> tests/ui/compile_fail/invalid_parse.rs:27:17
+ |
+27 | const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `G` at 30
+ --> tests/ui/compile_fail/invalid_parse.rs:28:53
+ |
+28 | const _: Uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");
+ | ^
+
+error: invalid group length in group 3: expected 4, found 5
+ --> tests/ui/compile_fail/invalid_parse.rs:29:52
+ |
+29 | const _: Uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-B2cBF-32BF39FA1E4");
+ | ^^^^^
+
+error: invalid group length in group 3: expected 4, found 5
+ --> tests/ui/compile_fail/invalid_parse.rs:30:44
+ |
+30 | const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-B0a75-32BF39FA1E4}");
+ | ^^^^^
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `z` at 30
+ --> tests/ui/compile_fail/invalid_parse.rs:32:53
+ |
+32 | const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-B6BF-329Bz39FA1E4}");
+ | ^
+
+error: invalid group count: expected 5, found 2
+ --> tests/ui/compile_fail/invalid_parse.rs:35:17
+ |
+35 | const _: Uuid = uuid!("67e550-4105b1426f9247bb680e5fe0c");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `岡` at 7
+ --> tests/ui/compile_fail/invalid_parse.rs:37:30
+ |
+37 | const _: Uuid = uuid!("504410岡林aab1426f9247bb680e5fe0c8");
+ | ^^
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `😎` at 7
+ --> tests/ui/compile_fail/invalid_parse.rs:38:30
+ |
+38 | const _: Uuid = uuid!("504410😎👍aab1426f9247bb680e5fe0c8");
+ | ^^
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `👍` at 21
+ --> tests/ui/compile_fail/invalid_parse.rs:40:44
+ |
+40 | const _: Uuid = uuid!("{F9168C5E-CEB2-4faa-👍5-32BF39FA1E4}");
+ | ^^
+
+error: invalid length: expected length 32 for simple format, found 4
+ --> tests/ui/compile_fail/invalid_parse.rs:42:17
+ |
+42 | const _: Uuid = uuid!("F916");
+ | ^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `uuid` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-zA-Z], found `x` at 5
+ --> tests/ui/compile_fail/invalid_parse.rs:43:28
+ |
+43 | const _: Uuid = uuid!("F916x");
+ | ^
diff --git a/third_party/rust/uuid/tests/ui/compile_pass/renamed.rs b/third_party/rust/uuid/tests/ui/compile_pass/renamed.rs
new file mode 100644
index 0000000000..321172efef
--- /dev/null
+++ b/third_party/rust/uuid/tests/ui/compile_pass/renamed.rs
@@ -0,0 +1,11 @@
+use ::uuid::{uuid as id, Uuid as Id};
+
+mod uuid {
+ struct MyType;
+}
+
+struct Uuid;
+
+const _: Id = id!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+
+fn main() {}
diff --git a/third_party/rust/uuid/tests/ui/compile_pass/valid.rs b/third_party/rust/uuid/tests/ui/compile_pass/valid.rs
new file mode 100644
index 0000000000..1f536dc043
--- /dev/null
+++ b/third_party/rust/uuid/tests/ui/compile_pass/valid.rs
@@ -0,0 +1,20 @@
+use uuid::{uuid, Uuid};
+
+const _: Uuid = uuid!("00000000000000000000000000000000");
+const _: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+const _: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+const _: Uuid = uuid!("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");
+const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c8");
+const _: Uuid = uuid!("01020304-1112-2122-3132-414243444546");
+const _: Uuid = uuid!("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8");
+
+// Nil
+const _: Uuid = uuid!("00000000000000000000000000000000");
+const _: Uuid = uuid!("00000000-0000-0000-0000-000000000000");
+
+// valid hyphenated
+const _: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
+// valid short
+const _: Uuid = uuid!("67e5504410b1426f9247bb680e5fe0c8");
+
+fn main() {}