Snap for 10103804 from 58feb986aac5677eef643e848b5a7514b233493b to mainline-tzdata5-release

Change-Id: Ic73f3b299aabd9e847013e41e3cc7be72fc436c6
diff --git a/.cargo/.gitignore b/.cargo/.gitignore
deleted file mode 100644
index 9bff75a..0000000
--- a/.cargo/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/config

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 87a7cbe..6175168 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "b68733dfafb4cc384c50ca24af56221bfd2458d7"
-  }
-}
+    "sha1": "573362627c354bd13432e9aa9cdc3465e00aaff3"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index fb93c9d..97e1c2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,33 +1,33 @@
-### CLion ###

-# CMake

-cmake-build-debug/

-

-### IntelliJ ###

-.idea

-*.iws

-*.iml

-*.ipr

-

-### Vim ###

-# Swap

-[._]*.s[a-v][a-z]

-[._]*.sw[a-p]

-[._]s[a-rt-v][a-z]

-[._]ss[a-gi-z]

-[._]sw[a-p]

-

-# Session

-Session.vim

-

-# Temporary

-.netrwhist

-*~

-# Auto-generated tag files

-tags

-# Persistent undo

-[._]*.un~

-

-### Rust ###

-/target/

-Cargo.lock

-

+### CLion ###
+# CMake
+cmake-build-debug/
+
+### IntelliJ ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+
+# Temporary
+.netrwhist
+*~
+# Auto-generated tag files
+tags
+# Persistent undo
+[._]*.un~
+
+### Rust ###
+/target/
+Cargo.lock
+
diff --git a/.rustfmt.toml b/.rustfmt.toml
deleted file mode 100644
index 313c070..0000000
--- a/.rustfmt.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-max_width = 80

-hard_tabs = false

-tab_spaces = 4

-newline_style = "Unix"

-wrap_comments = true

-normalize_comments = true

-merge_derives = true

-force_explicit_abi = true

-unstable_features = false

diff --git a/Android.bp b/Android.bp
index 2f631a8..8d8b66d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,17 +43,20 @@
     host_supported: true,
     crate_name: "uuid",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.8.2",
+    cargo_pkg_version: "1.3.0",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
+        "atomic",
         "getrandom",
+        "rng",
         "serde",
         "std",
         "v1",
         "v4",
     ],
     rustlibs: [
+        "libatomic_rust",
         "libgetrandom",
         "libserde",
     ],
@@ -61,6 +64,8 @@
         "//apex_available:platform",
         "com.android.virt",
     ],
+    product_available: true,
+    vendor_available: true,
 }
 
 rust_library_rlib {
diff --git a/CODEOWNERS b/CODEOWNERS
deleted file mode 100644
index 4846ccc..0000000
--- a/CODEOWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-# CI

-.travis.yml     @kinggoesgaming @KodrAus @Dylan-DPC @radix

-appveyor.yml    @kinggoesgaming @KodrAus @Dylan-DPC @radix

-

-# Cargo.toml

-Cargo.toml      @kinggoesgaming @KodrAus @Dylan-DPC @radix

-

-# Rust

-*.rs            @kinggoesgaming @KodrAus @Dylan-DPC @radix

-

-# CODEOWNERS

-CODEOWNERS      @kinggoesgaming @KodrAus @Dylan-DPC @radix

-

-#>> Critical

-# bors.toml file

-bors.toml       @kinggoesgaming @KodrAus @Dylan-DPC @radix

diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 8ffa6a4..43ff03c 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,77 +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 the project team at report@uuid-rs.groups.io. 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
\ No newline at end of file
+# 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/CONTRIBUTING.md b/CONTRIBUTING.md
index baa7535..1025171 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,149 +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 [users.rust-lang.org][u-r-l-o], post

-on [uuid-rs mailing list] or join our [gitter] channel.

-

-> 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 still in flux. All features desired may not be present. As

-such you are welcome to request for new features. Keep in mind that `uuid` is

-a general purpose library. We want to provide features that most users would

-find useful. As such not every feature may be accepted.

-

-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, provided they have

-been discussed.

-

-[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 branch:

-* `master` when making non-breaking changes 

-* `breaking` when your changes alter the public API in a breaking manner

-

-If the pull request is still a work in progress, prepend`[WIP] ` in your 

-title. `WIP bot` will make sure that the PR doesn't accidentally get merged.

-

-> Uuid Project has a minimum rust version policy. Currently `uuid` should 

-compile with atleast `1.22.0`, and is enforced on our CI builds.

-

-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/master/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

-

-# Out-of-tree Contributions

-[Out-of-tree Contributions]: #out-of-tree-contributions

-

-You can contribute to Uuid in other ways:

-

-* Answer questions on [users.rust-lang.org][u-r-l-o], [uuid-rs mailing list] and/or

-[gitter] channel.

-* Find the [crates depending on `uuid`][dependent] and sending PRs to them,

-helping them keep their version of `uuid` up-to-date.

-

-[dependent]: https://crates.io/crates/uuid/reverse_dependencies

-

-# 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

-[uuid-rs mailing list]: https://uuid-rs.groups.io

-[gitter]: https://gitter.im/uuid-rs/Lobby

-[search existing issues]: https://github.com/uuid-rs/uuid/search?q=&type=Issues&utf8=%E2%9C%93

+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/COPYRIGHT b/COPYRIGHT
index fbcde1c..925929c 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,8 +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.

+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/Cargo.toml b/Cargo.toml
index 1803f73..e07072c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,56 +3,137 @@
 # 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
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# 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 = "0.8.2"
-authors = ["Ashley Mannix<ashleymannix@live.com.au>", "Christopher Armstrong", "Dylan DPC<dylan.dpc@gmail.com>", "Hunar Roop Kahlon<hunar.roop@gmail.com>"]
-exclude = [".github/**", ".travis.yml", "appveyor.yml", "bors.toml"]
+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"]
+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]
-default-target = "x86_64-pc-windows-msvc"
-features = ["guid", "serde", "slog", "v1", "v3", "v4", "v5"]
+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"]
-[dependencies.getrandom]
-version = "0.2.0"
+features = [
+    "serde",
+    "v1",
+    "v3",
+    "v4",
+    "v5",
+    "v6",
+    "v7",
+    "v8",
+]
+
+[dependencies.arbitrary]
+version = "1.1.3"
 optional = true
 
-[dependencies.md5]
-version = "0.7"
+[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]
-version = "0.6"
+[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"
 
@@ -62,21 +143,46 @@
 [dev-dependencies.serde_test]
 version = "1.0.56"
 
+[dev-dependencies.trybuild]
+version = "1.0.52"
+
 [features]
 default = ["std"]
-guid = ["winapi"]
+fast-rng = [
+    "rng",
+    "rand",
+]
+js = [
+    "wasm-bindgen",
+    "getrandom",
+    "getrandom/js",
+]
+macro-diagnostics = ["uuid-macro-internal"]
+md5 = ["md-5"]
+rng = ["getrandom"]
+sha1 = ["sha1_smol"]
 std = []
-stdweb = ["getrandom", "getrandom/js"]
-v1 = []
+v1 = ["atomic"]
 v3 = ["md5"]
-v4 = ["getrandom"]
+v4 = ["rng"]
 v5 = ["sha1"]
-wasm-bindgen = ["getrandom", "getrandom/js"]
-[target."cfg(windows)".dependencies.winapi]
+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"
-optional = true
-[badges.appveyor]
-repository = "uuid-rs/uuid"
+
+[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"
@@ -86,6 +192,3 @@
 
 [badges.maintenance]
 status = "actively-developed"
-
-[badges.travis-ci]
-repository = "uuid-rs/uuid"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index cafaecd..e4421b5 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,104 +1,184 @@
-[package]

-authors = [

-    "Ashley Mannix<ashleymannix@live.com.au>",

-    "Christopher Armstrong",

-    "Dylan DPC<dylan.dpc@gmail.com>",

-    "Hunar Roop Kahlon<hunar.roop@gmail.com>"

-]

-categories = [

-    "data-structures",

-    "no-std",

-    "parser-implementations",

-    "wasm"

-]

-description = "A library to generate and parse UUIDs."

-documentation = "https://docs.rs/uuid"

-edition = "2018"

-exclude = [

-    ".github/**",

-    ".travis.yml",

-    "appveyor.yml",

-    "bors.toml"

-]

-keywords = [

-    "guid",

-    "unique",

-    "uuid"

-]

-license = "Apache-2.0 OR MIT"

-homepage = "https://github.com/uuid-rs/uuid"

-name = "uuid"

-readme = "README.md"

-repository = "https://github.com/uuid-rs/uuid"

-version = "0.8.2" # remember to update html_root_url in lib.rs

-

-[package.metadata.docs.rs]

-features = [ "guid", "serde", "slog", "v1", "v3", "v4", "v5" ]

-default-target = "x86_64-pc-windows-msvc"

-

-[package.metadata.playground]

-features = ["serde", "v1", "v3", "v4", "v5"]

-

-[badges.appveyor]

-repository = "uuid-rs/uuid"

-

-[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"

-

-[badges.travis-ci]

-repository = "uuid-rs/uuid"

-

-[dependencies.getrandom]

-optional = true

-version = "0.2.0"

-

-[dependencies.md5]

-optional = true

-version = "0.7"

-

-[dependencies.serde]

-default-features = false

-optional = true

-version = "1.0.56"

-

-[dependencies.sha1]

-optional = true

-version = "0.6"

-

-[dependencies.slog]

-optional = true

-version = "2"

-

-[dev-dependencies.bincode]

-version = "1.0"

-

-[dev-dependencies.serde_derive]

-version = "1.0.79"

-

-[dev-dependencies.serde_json]

-version = "1.0"

-

-[dev-dependencies.serde_test]

-version = "1.0.56"

-

-[features]

-default = ["std"]

-guid = ["winapi"]

-std = []

-stdweb = ["getrandom", "getrandom/js"]

-v1 = []

-v3 = ["md5"]

-v4 = ["getrandom"]

-v5 = ["sha1"]

-wasm-bindgen = ["getrandom", "getrandom/js"]

-

-[target.'cfg(windows)'.dependencies.winapi]

-optional = true

-version = "0.3"

-

+[package]
+authors = [
+    "Ashley Mannix<ashleymannix@live.com.au>",
+    "Christopher Armstrong",
+    "Dylan DPC<dylan.dpc@gmail.com>",
+    "Hunar Roop Kahlon<hunar.roop@gmail.com>"
+]
+categories = [
+    "data-structures",
+    "no-std",
+    "parser-implementations",
+    "wasm"
+]
+description = "A library to generate and parse UUIDs."
+documentation = "https://docs.rs/uuid"
+edition = "2018"
+exclude = [
+    ".github/**"
+]
+keywords = [
+    "guid",
+    "unique",
+    "uuid"
+]
+license = "Apache-2.0 OR MIT"
+homepage = "https://github.com/uuid-rs/uuid"
+name = "uuid"
+readme = "README.md"
+repository = "https://github.com/uuid-rs/uuid"
+version = "1.3.0" # remember to update html_root_url in lib.rs
+
+[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"]
+
+[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"
+
+[features]
+default = ["std"]
+std = []
+macro-diagnostics = ["uuid-macro-internal"]
+
+# NOTE: When adding new features, check the `ci.yml` workflow                                              ..
+# and include them where necessary (you can follow along with existing features)
+v1 = ["atomic"]
+v3 = ["md5"]
+v4 = ["rng"]
+v5 = ["sha1"]
+v6 = ["atomic"]
+v7 = ["atomic", "rng"]
+v8 = []
+
+js = ["wasm-bindgen", "getrandom", "getrandom/js"]
+
+rng = ["getrandom"]
+fast-rng = ["rng", "rand"]
+
+sha1 = ["sha1_smol"]
+md5 = ["md-5"]
+
+# Public: Used in trait impls on `Uuid`
+[dependencies.serde]
+default-features = false
+optional = true
+version = "1.0.56"
+
+# Public: Used in trait impls on `Uuid`
+[dependencies.slog]
+optional = true
+version = "2"
+
+# Public: Used in trait impls on `Uuid`
+[dependencies.arbitrary]
+optional = true
+version = "1.1.3"
+
+# Public (unstable): Used in `zerocopy` derive
+# Unstable: also need RUSTFLAGS="--cfg uuid_unstable" to work
+# This feature may break between releases, or be removed entirely before
+# stabilization.
+# See: https://github.com/uuid-rs/uuid/issues/588
+[dependencies.zerocopy]
+optional = true
+version = "0.6"
+
+# Private
+# Don't depend on this optional feature directly: it may change at any time
+# use the `rng` feature instead
+[dependencies.getrandom]
+package = "getrandom"
+optional = true
+version = "0.2"
+
+# Private
+# Don't depend on this optional feature directly: it may change at any time
+# use the `fast-rng` feature instead
+[dependencies.rand]
+package = "rand"
+optional = true
+version = "0.8"
+
+# Private
+# Don't depend on this optional feature directly: it may change at any time
+# Use the `md5` feature instead
+[dependencies.md-5]
+package = "md-5"
+default-features = false
+optional = true
+version = "0.10"
+
+# Private
+# Don't depend on this optional feature directly: it may change at any time
+# Use the `sha1` feature instead
+[dependencies.sha1_smol]
+package = "sha1_smol"
+default-features = false
+optional = true
+version = "1"
+
+# Public: Re-exported
+# Don't depend on this optional feature directly: it may change at any time
+# Use the `macro-diagnostics` feature instead
+[dependencies.uuid-macro-internal]
+package = "uuid-macro-internal"
+version = "1.3.0"
+path = "macros"
+optional = true
+
+[dependencies.atomic]
+package = "atomic"
+default-features = false
+optional = true
+version = "0.5"
+
+[dependencies.wasm-bindgen]
+package = "wasm-bindgen"
+version = "0.2"
+optional = true
+
+[dev-dependencies.bincode]
+version = "1.0"
+
+[dev-dependencies.serde_derive]
+version = "1.0.79"
+
+[dev-dependencies.serde_json]
+version = "1.0"
+
+[dev-dependencies.serde_test]
+version = "1.0.56"
+
+[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen]
+package = "wasm-bindgen"
+version = "0.2"
+
+[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen-test]
+version = "0.3"
+
+[dev-dependencies.trybuild]
+version = "1.0.52"
+
+[dev-dependencies.rustversion]
+version = "1"
+
+[target.'cfg(windows)'.dev-dependencies.windows-sys]
+version = "0.45.0"
+features = ["Win32_System_Com"]
+
+[workspace]
+members = [
+    "macros"
+]
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index f47c941..16fe87b 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -1,201 +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.

+                              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/LICENSE-MIT b/LICENSE-MIT
index 21d90fa..99a3078 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,26 +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.

+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/METADATA b/METADATA
index 4d608b1..dbb7b95 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/uuid
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "uuid"
 description: "A library to generate and parse UUIDs."
 third_party {
@@ -7,14 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/uuid/uuid-0.8.2.crate"
+    value: "https://static.crates.io/crates/uuid/uuid-1.3.0.crate"
   }
-  version: "0.8.2"
-  # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same.
+  version: "1.3.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
+    year: 2023
     month: 3
-    day: 12
+    day: 29
   }
 }
diff --git a/README.md b/README.md
index 1592ffd..70a0799 100644
--- a/README.md
+++ b/README.md
@@ -1,141 +1,99 @@
-uuid

----------

-

-[![Latest Version](https://img.shields.io/crates/v/uuid.svg)](https://crates.io/crates/uuid)

-[![Join the chat at https://gitter.im/uuid-rs/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/uuid-rs/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)

-![Minimum rustc version](https://img.shields.io/badge/rustc-1.34.0+-yellow.svg)

-[![Build Status](https://ci.appveyor.com/api/projects/status/github/uuid-rs/uuid?branch=master&svg=true)](https://ci.appveyor.com/project/uuid-rs/uuid/branch/master)

-[![Build Status](https://travis-ci.org/uuid-rs/uuid.svg?branch=master)](https://travis-ci.org/uuid-rs/uuid)

-[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/uuid-rs/uuid.svg)](https://isitmaintained.com/project/uuid-rs/uuid "Average time to resolve an issue")

-[![Percentage of issues still open](https://isitmaintained.com/badge/open/uuid-rs/uuid.svg)](https://isitmaintained.com/project/uuid-rs/uuid "Percentage of issues still open")

-[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fuuid-rs%2Fuuid.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fuuid-rs%2Fuuid?ref=badge_shield)

-

----

-

-Generate and parse UUIDs.

-

-Provides support for Universally Unique Identifiers (UUIDs). A UUID is a

-unique 128-bit number, stored as 16 octets. UUIDs are used to  assign

-unique identifiers to entities without requiring a central allocating

-authority.

-

-They are particularly useful in distributed systems, though they 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.

-

-## Dependencies

-

-By default, this crate depends on nothing but `std` and cannot generate

-[`Uuid`]s. You need to enable the following Cargo features to enable

-various pieces of functionality:

-

-* `v1` - adds the `Uuid::new_v1` function and the ability to create a V1

-  using an implementation of `uuid::v1::ClockSequence` (usually

-`uuid::v1::Context`) and a timestamp from `time::timespec`.

-* `v3` - adds the `Uuid::new_v3` function and the ability to create a V3

-  UUID based on the MD5 hash of some data.

-* `v4` - adds the `Uuid::new_v4` function and the ability to randomly

-  generate a `Uuid`.

-* `v5` - adds the `Uuid::new_v5` function and the ability to create a V5

-  UUID based on the SHA1 hash of some data.

-* `serde` - adds the ability to serialize and deserialize a `Uuid` using the

-  `serde` crate.

-

-You need to enable one of the following Cargo features together with

-`v3`, `v4` or `v5` feature if you're targeting `wasm32-unknown-unknown` target:

-

-* `stdweb` - enables support for `OsRng` on `wasm32-unknown-unknown` via

-  `stdweb` combined with `cargo-web`

-* `wasm-bindgen` - `wasm-bindgen` enables support for `OsRng` on

-  `wasm32-unknown-unknown` via [`wasm-bindgen`]

-

-By default, `uuid` can be depended on with:

-

-```toml

-[dependencies]

-uuid = "0.8"

-```

-

-To activate various features, use syntax like:

-

-```toml

-[dependencies]

-uuid = { version = "0.8", features = ["serde", "v4"] }

-```

-

-You can disable default features with:

-

-```toml

-[dependencies]

-uuid = { version = "0.8", default-features = false }

-```

-

-## Examples

-

-To parse a UUID given in the simple format and print it as a urn:

-

-```rust

-use uuid::Uuid;

-

-fn main() -> Result<(), uuid::Error> {

-    let my_uuid =

-        Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8")?;

-    println!("{}", my_uuid.to_urn());

-    Ok(())

-}

-```

-

-To create a new random (V4) UUID and print it out in hexadecimal form:

-

-```rust

-// Note that this requires the `v4` feature enabled in the uuid crate.

-

-use uuid::Uuid;

-

-fn main() {

-    let my_uuid = Uuid::new_v4();

-    println!("{}", my_uuid);

-    Ok(())

-}

-```

-

-## Strings

-

-Examples of string representations:

-

-* simple: `936DA01F9ABD4d9d80C702AF85C822A8`

-* hyphenated: `550e8400-e29b-41d4-a716-446655440000`

-* urn: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`

-

-## 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)

-

-[`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen

-

-[`Uuid`]: https://docs.rs/uuid/0.8.2/uuid/struct.Uuid.html

-

----

-# 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

+# `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/README.tpl b/README.tpl
deleted file mode 100644
index 85faa79..0000000
--- a/README.tpl
+++ /dev/null
@@ -1,29 +0,0 @@
-{{crate}}

----------

-

-[![Latest Version](https://img.shields.io/crates/v/uuid.svg)](https://crates.io/crates/uuid)

-[![Join the chat at https://gitter.im/uuid-rs/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/uuid-rs/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)

-![Minimum rustc version](https://img.shields.io/badge/rustc-1.34.0+-yellow.svg)

-{{badges}}

-

----

-

-{{readme}}

-

-[`Uuid`]: https://docs.rs/uuid/{{version}}/uuid/struct.Uuid.html

-

----

-# 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.

-

-## 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.

diff --git a/benches/format_str.rs b/benches/format_str.rs
index 0ae576d..fab8929 100644
--- a/benches/format_str.rs
+++ b/benches/format_str.rs
@@ -1,66 +1,66 @@
-#![feature(test)]

-extern crate test;

-

-use std::io::Write;

-use test::Bencher;

-use uuid::Uuid;

-

-#[bench]

-fn bench_hyphen(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.to_hyphenated()).unwrap();

-        test::black_box(buffer);

-    });

-}

-

-#[bench]

-fn bench_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.to_simple()).unwrap();

-        test::black_box(buffer);

-    })

-}

-

-#[bench]

-fn bench_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.to_urn()).unwrap();

-        test::black_box(buffer);

-    })

-}

-

-#[bench]

-fn bench_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.to_hyphenated().encode_lower(&mut buffer);

-        test::black_box(buffer);

-    });

-}

-

-#[bench]

-fn bench_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.to_simple().encode_lower(&mut buffer);

-        test::black_box(buffer);

-    })

-}

-

-#[bench]

-fn bench_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.to_urn().encode_lower(&mut buffer);

-        test::black_box(buffer);

-    })

-}

+#![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/benches/invalid_parse_str.rs b/benches/invalid_parse_str.rs
deleted file mode 100644
index 447fa80..0000000
--- a/benches/invalid_parse_str.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#![feature(test)]

-extern crate test;

-

-use test::Bencher;

-use uuid::Uuid;

-

-#[bench]

-fn bench_parse_invalid_strings(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("");

-        let _ = Uuid::parse_str("!");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4");

-        let _ = Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4");

-        let _ = Uuid::parse_str("01020304-1112-2122-3132-41424344");

-        let _ = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88");

-        let _ = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8");

-        let _ = Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8");

-

-        // Test error reporting

-        let _ = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c");

-        let _ = Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd");

-        let _ = Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4");

-    });

-}

-

-#[bench]

-fn bench_parse_invalid_len(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4");

-    })

-}

-

-#[bench]

-fn bench_parse_invalid_character(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4");

-    })

-}

-

-#[bench]

-fn bench_parse_invalid_group_len(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("01020304-1112-2122-3132-41424344");

-    });

-}

-

-#[bench]

-fn bench_parse_invalid_groups(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4");

-    });

-}

diff --git a/benches/mod.rs b/benches/mod.rs
deleted file mode 100644
index 61045c6..0000000
--- a/benches/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![feature(test)]

-

-#[cfg(feature = "slog")]

-pub mod slog_support;

diff --git a/benches/parse_str.rs b/benches/parse_str.rs
new file mode 100644
index 0000000..e53ba24
--- /dev/null
+++ b/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/benches/serde_support.rs b/benches/serde_support.rs
deleted file mode 100644
index 9ec38a6..0000000
--- a/benches/serde_support.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#![cfg(feature = "serde")]

-#![feature(test)]

-

-use bincode;

-use serde_json;

-extern crate test;

-

-use test::Bencher;

-use uuid::Uuid;

-

-#[bench]

-fn bench_json_encode(b: &mut Bencher) {

-    let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();

-    let mut buffer = [0_u8; 38];

-    b.iter(|| {

-        serde_json::to_writer(&mut buffer as &mut [u8], &uuid).unwrap();

-        test::black_box(buffer);

-    });

-    b.bytes = buffer.len() as u64;

-}

-

-#[bench]

-fn bench_json_decode(b: &mut Bencher) {

-    let s = "\"F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4\"";

-    b.iter(|| serde_json::from_str::<Uuid>(s).unwrap());

-    b.bytes = s.len() as u64;

-}

-

-#[bench]

-fn bench_bincode_encode(b: &mut Bencher) {

-    let uuid = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").unwrap();

-    let mut buffer = [0_u8; 24];

-    b.iter(|| {

-        bincode::serialize_into(&mut buffer as &mut [u8], &uuid).unwrap();

-        test::black_box(buffer);

-    });

-    b.bytes = buffer.len() as u64;

-}

-

-#[bench]

-fn bench_bincode_decode(b: &mut Bencher) {

-    let bytes = [

-        16, 0, 0, 0, 0, 0, 0, 0, 249, 22, 140, 94, 206, 178, 79, 170, 182, 191,

-        50, 155, 243, 159, 161, 228,

-    ];

-    b.iter(|| bincode::deserialize::<Uuid>(&bytes).unwrap());

-    b.bytes = bytes.len() as u64;

-}

diff --git a/benches/slog_support/mod.rs b/benches/slog_support/mod.rs
deleted file mode 100644
index 12b38c8..0000000
--- a/benches/slog_support/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod parse_str;

diff --git a/benches/slog_support/parse_str.rs b/benches/slog_support/parse_str.rs
deleted file mode 100644
index 1c837f5..0000000
--- a/benches/slog_support/parse_str.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-extern crate test;

-

-#[bench]

-#[cfg(feature = "slog")]

-pub fn bench_log_discard_kv(b: &mut test::Bencher) {

-    let u1 =

-        uuid::Uuid::parse_str("F9168C5E-CEB2-4FAB-B6BF-329BF39FA1E4").unwrap();

-    let root =

-        slog::Logger::root(::slog::Drain::fuse(::slog::Discard), slog::o!());

-

-    b.iter(|| {

-        #[cfg(feature = "slog")]

-        slog::crit!(root, "test"; "u1" => u1);

-    });

-}

diff --git a/benches/v4.rs b/benches/v4.rs
new file mode 100644
index 0000000..61c3246
--- /dev/null
+++ b/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/benches/valid_parse_str.rs b/benches/valid_parse_str.rs
deleted file mode 100644
index 7e36676..0000000
--- a/benches/valid_parse_str.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#![feature(test)]

-

-extern crate test;

-

-use test::Bencher;

-use uuid::Uuid;

-

-#[bench]

-fn bench_parse_valid_strings(b: &mut Bencher) {

-    b.iter(|| {

-        // Valid

-        let _ = Uuid::parse_str("00000000000000000000000000000000");

-        let _ = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8");

-        let _ = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8");

-        let _ = Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");

-        let _ = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8");

-        let _ = Uuid::parse_str("01020304-1112-2122-3132-414243444546");

-        let _ =

-            Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8");

-

-        // Nil

-        let _ = Uuid::parse_str("00000000000000000000000000000000");

-        let _ = Uuid::parse_str("00000000-0000-0000-0000-000000000000");

-    });

-}

-

-#[bench]

-fn bench_valid_hyphenated(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8");

-    });

-}

-

-#[bench]

-fn bench_valid_short(b: &mut Bencher) {

-    b.iter(|| {

-        let _ = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8");

-    });

-}

diff --git a/cargo2android_nostd.bp b/cargo2android_nostd.bp
index da60055..15fa75b 100644
--- a/cargo2android_nostd.bp
+++ b/cargo2android_nostd.bp
@@ -5,9 +5,6 @@
     cargo_pkg_version: "0.8.2",
     srcs: ["src/lib.rs"],
     edition: "2018",
-    features: [
-        "macro-diagnostics",
-    ],
     prefer_rlib: true,
     no_stdlibs: true,
     stdlibs: [
diff --git a/examples/random_uuid.rs b/examples/random_uuid.rs
new file mode 100644
index 0000000..897071c
--- /dev/null
+++ b/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/examples/sortable_uuid.rs b/examples/sortable_uuid.rs
new file mode 100644
index 0000000..dc12812
--- /dev/null
+++ b/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/examples/uuid_macro.rs b/examples/uuid_macro.rs
new file mode 100644
index 0000000..c4ff048
--- /dev/null
+++ b/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/examples/windows_guid.rs b/examples/windows_guid.rs
new file mode 100644
index 0000000..6cbc10e
--- /dev/null
+++ b/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/src/adapter/compact.rs b/src/adapter/compact.rs
deleted file mode 100644
index 1b53682..0000000
--- a/src/adapter/compact.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-//! Module for use with `#[serde(with = "...")]` to serialize a [`Uuid`]

-//! as a `[u8; 16]`.

-//!

-//! [`Uuid`]: ../../struct.Uuid.html

-

-/// Serializer for a [`Uuid`] into 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)

-}

-

-/// Deserializer from a `[u8; 16]` into 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_test;

-

-    #[test]

-    fn test_serialize_compact() {

-        #[derive(

-            serde_derive::Serialize, Debug, serde_derive::Deserialize, PartialEq,

-        )]

-        struct UuidContainer {

-            #[serde(with = "super")]

-            u: crate::Uuid,

-        }

-        use serde_test::Configure;

-

-        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,

-            ],

-        )

-    }

-}

diff --git a/src/adapter/mod.rs b/src/adapter/mod.rs
deleted file mode 100644
index 412920e..0000000
--- a/src/adapter/mod.rs
+++ /dev/null
@@ -1,1027 +0,0 @@
-// 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 various formats for UUIDs

-

-use crate::prelude::*;

-use crate::std::{fmt, str};

-

-#[cfg(feature = "serde")]

-pub mod compact;

-

-/// An adaptor for formatting an [`Uuid`] as a hyphenated string.

-///

-/// Takes an owned instance of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct Hyphenated(Uuid);

-

-/// An adaptor for formatting an [`Uuid`] as a hyphenated string.

-///

-/// Takes a reference of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct HyphenatedRef<'a>(&'a Uuid);

-

-/// An adaptor for formatting an [`Uuid`] as a simple string.

-///

-/// Takes an owned instance of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct Simple(Uuid);

-

-/// An adaptor for formatting an [`Uuid`] as a simple string.

-///

-/// Takes a reference of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct SimpleRef<'a>(&'a Uuid);

-

-/// An adaptor for formatting an [`Uuid`] as a URN string.

-///

-/// Takes an owned instance of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct Urn(Uuid);

-

-/// An adaptor for formatting an [`Uuid`] as a URN string.

-///

-/// Takes a reference of the [`Uuid`].

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub struct UrnRef<'a>(&'a Uuid);

-

-impl Uuid {

-    /// Get a [`Hyphenated`] formatter.

-    ///

-    /// [`Hyphenated`]: adapter/struct.Hyphenated.html

-    #[inline]

-    pub const fn to_hyphenated(self) -> Hyphenated {

-        Hyphenated::from_uuid(self)

-    }

-

-    /// Get a borrowed [`HyphenatedRef`] formatter.

-    ///

-    /// [`HyphenatedRef`]: adapter/struct.HyphenatedRef.html

-    #[inline]

-    pub const fn to_hyphenated_ref(&self) -> HyphenatedRef<'_> {

-        HyphenatedRef::from_uuid_ref(self)

-    }

-

-    /// Get a [`Simple`] formatter.

-    ///

-    /// [`Simple`]: adapter/struct.Simple.html

-    #[inline]

-    pub const fn to_simple(self) -> Simple {

-        Simple::from_uuid(self)

-    }

-

-    /// Get a borrowed [`SimpleRef`] formatter.

-    ///

-    /// [`SimpleRef`]: adapter/struct.SimpleRef.html

-    #[inline]

-    pub const fn to_simple_ref(&self) -> SimpleRef<'_> {

-        SimpleRef::from_uuid_ref(self)

-    }

-

-    /// Get a [`Urn`] formatter.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    /// [`Urn`]: adapter/struct.Urn.html

-    #[inline]

-    pub const fn to_urn(self) -> Urn {

-        Urn::from_uuid(self)

-    }

-

-    /// Get a borrowed [`UrnRef`] formatter.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    /// [`UrnRef`]: adapter/struct.UrnRef.html

-    #[inline]

-    pub const fn to_urn_ref(&self) -> UrnRef<'_> {

-        UrnRef::from_uuid_ref(self)

-    }

-}

-

-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',

-];

-/// The segments of a UUID's [u8; 16] corresponding to each group.

-const BYTE_POSITIONS: [usize; 6] = [0, 4, 6, 8, 10, 16];

-/// The locations that hyphens are written into the buffer, after each

-/// group.

-const HYPHEN_POSITIONS: [usize; 4] = [8, 13, 18, 23];

-

-/// Encodes the `uuid` possibly with hyphens, and possibly in upper

-/// case, to full_buffer[start..] and returns the str sliced from

-/// full_buffer[..start + encoded_length].

-///

-/// The `start` parameter allows writing a prefix (such as

-/// "urn:uuid:") to the buffer that's included in the final encoded

-/// UUID.

-#[allow(clippy::needless_range_loop)]

-fn encode<'a>(

-    full_buffer: &'a mut [u8],

-    start: usize,

-    uuid: &Uuid,

-    hyphens: bool,

-    upper: bool,

-) -> &'a mut str {

-    let len = if hyphens { 36 } else { 32 };

-

-    {

-        let buffer = &mut full_buffer[start..start + len];

-        let bytes = uuid.as_bytes();

-

-        let hex = if upper { &UPPER } else { &LOWER };

-

-        for group in 0..5 {

-            // If we're writing hyphens, we need to shift the output

-            // location along by how many of them have been written

-            // before this point. That's exactly the (0-indexed) group

-            // number.

-            let hyphens_before = if hyphens { group } else { 0 };

-            for idx in BYTE_POSITIONS[group]..BYTE_POSITIONS[group + 1] {

-                let b = bytes[idx];

-                let out_idx = hyphens_before + 2 * idx;

-

-                buffer[out_idx] = hex[(b >> 4) as usize];

-                buffer[out_idx + 1] = hex[(b & 0b1111) as usize];

-            }

-

-            if group != 4 && hyphens {

-                buffer[HYPHEN_POSITIONS[group]] = b'-';

-            }

-        }

-    }

-

-    str::from_utf8_mut(&mut full_buffer[..start + len])

-        .expect("found non-ASCII output characters while encoding a UUID")

-}

-

-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.to_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.to_hyphenated().encode_lower(&mut buf);

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, &self.0, true, 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.to_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.to_hyphenated().encode_upper(&mut buf);

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, &self.0, true, true)

-    }

-}

-

-impl<'a> HyphenatedRef<'a> {

-    /// The length of a hyphenated [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    pub const LENGTH: usize = 36;

-

-    /// Creates a [`HyphenatedRef`] from a [`Uuid`] reference.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    /// [`HyphenatedRef`]: struct.HyphenatedRef.html

-    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {

-        HyphenatedRef(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.to_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.to_hyphenated().encode_lower(&mut buf);

-    ///     assert_eq!(

-    ///         uuid.to_hyphenated().encode_lower(&mut buf),

-    ///         "936da01f-9abd-4d9d-80c7-02af85c822a8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, self.0, true, 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.to_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];

-    ///     assert_eq!(

-    ///         uuid.to_hyphenated().encode_upper(&mut buf),

-    ///         "936DA01F-9ABD-4D9D-80C7-02AF85C822A8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, self.0, true, true)

-    }

-}

-

-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.to_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.to_simple().encode_lower(&mut buf),

-    ///         "936da01f9abd4d9d80c702af85c822a8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, &self.0, false, 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.to_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.to_simple().encode_upper(&mut buf),

-    ///         "936DA01F9ABD4D9D80C702AF85C822A8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, &self.0, false, true)

-    }

-}

-

-impl<'a> SimpleRef<'a> {

-    /// The length of a simple [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    pub const LENGTH: usize = 32;

-

-    /// Creates a [`SimpleRef`] from a [`Uuid`] reference.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    /// [`SimpleRef`]: struct.SimpleRef.html

-    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {

-        SimpleRef(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.to_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.to_simple().encode_lower(&mut buf),

-    ///         "936da01f9abd4d9d80c702af85c822a8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, self.0, false, 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.to_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.to_simple().encode_upper(&mut buf),

-    ///         "936DA01F9ABD4D9D80C702AF85C822A8"

-    ///     );

-    ///     assert_eq!(

-    ///         &buf as &[_],

-    ///         b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        encode(buffer, 0, self.0, false, true)

-    }

-}

-

-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.to_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.to_urn().encode_lower(&mut buf);

-    ///     assert_eq!(

-    ///         uuid.to_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(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        buffer[..9].copy_from_slice(b"urn:uuid:");

-        encode(buffer, 9, &self.0, true, 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.to_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.to_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(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        buffer[..9].copy_from_slice(b"urn:uuid:");

-        encode(buffer, 9, &self.0, true, true)

-    }

-}

-

-impl<'a> UrnRef<'a> {

-    /// The length of a URN [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    pub const LENGTH: usize = 45;

-

-    /// Creates a [`UrnRef`] from a [`Uuid`] reference.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    /// [`UrnRef`]: struct.UrnRef.html

-    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {

-        UrnRef(&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.to_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.to_urn().encode_lower(&mut buf);

-    ///     assert_eq!(

-    ///         uuid.to_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(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        buffer[..9].copy_from_slice(b"urn:uuid:");

-        encode(buffer, 9, self.0, true, 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.to_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.to_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(())

-    /// }

-    /// ```

-    /// */

-    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {

-        buffer[..9].copy_from_slice(b"urn:uuid:");

-        encode(buffer, 9, self.0, true, true)

-    }

-}

-

-macro_rules! impl_adapter_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 {

-                // TODO: Self doesn't work https://github.com/rust-lang/rust/issues/52808

-                f.write_str(self.encode_lower(&mut [0; $T::LENGTH]))

-            }

-        }

-

-        impl<$($a),*> fmt::UpperHex for $T<$($a),*> {

-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-                // TODO: Self doesn't work https://github.com/rust-lang/rust/issues/52808

-                f.write_str(self.encode_upper(&mut [0; $T::LENGTH]))

-            }

-        }

-

-        impl_adapter_from!($T<$($a),*>);

-    )+}

-}

-

-macro_rules! impl_adapter_from {

-    ($T:ident<>) => {

-        impl From<Uuid> for $T {

-            #[inline]

-            fn from(f: Uuid) -> Self {

-                $T::from_uuid(f)

-            }

-        }

-    };

-    ($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_adapter_traits! {

-    Hyphenated<>,

-    HyphenatedRef<'a>,

-    Simple<>,

-    SimpleRef<'a>,

-    Urn<>,

-    UrnRef<'a>

-}

-

-#[cfg(test)]

-mod tests {

-    use crate::prelude::*;

-

-    #[test]

-    fn hyphenated_trailing() {

-        let mut buf = [b'x'; 100];

-        let len = Uuid::nil().to_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().to_hyphenated().encode_lower(&mut buf).len();

-        assert_eq!(len, super::HyphenatedRef::LENGTH);

-        assert!(buf[len..].iter().all(|x| *x == b'x'));

-    }

-

-    #[test]

-    fn simple_trailing() {

-        let mut buf = [b'x'; 100];

-        let len = Uuid::nil().to_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().to_simple().encode_lower(&mut buf).len();

-        assert_eq!(len, super::SimpleRef::LENGTH);

-        assert!(buf[len..].iter().all(|x| *x == b'x'));

-    }

-

-    #[test]

-    fn urn_trailing() {

-        let mut buf = [b'x'; 100];

-        let len = Uuid::nil().to_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().to_urn().encode_lower(&mut buf).len();

-        assert_eq!(len, super::UrnRef::LENGTH);

-        assert!(buf[len..].iter().all(|x| *x == b'x'));

-    }

-

-    #[test]

-    #[should_panic]

-    fn hyphenated_too_small() {

-        Uuid::nil().to_hyphenated().encode_lower(&mut [0; 35]);

-    }

-

-    #[test]

-    #[should_panic]

-    fn hyphenated_ref_too_small() {

-        Uuid::nil().to_hyphenated_ref().encode_lower(&mut [0; 35]);

-    }

-

-    #[test]

-    #[should_panic]

-    fn simple_too_small() {

-        Uuid::nil().to_simple().encode_lower(&mut [0; 31]);

-    }

-    #[test]

-    #[should_panic]

-    fn simple_ref_too_small() {

-        Uuid::nil().to_simple_ref().encode_lower(&mut [0; 31]);

-    }

-    #[test]

-    #[should_panic]

-    fn urn_too_small() {

-        Uuid::nil().to_urn().encode_lower(&mut [0; 44]);

-    }

-    #[test]

-    #[should_panic]

-    fn urn_ref_too_small() {

-        Uuid::nil().to_urn_ref().encode_lower(&mut [0; 44]);

-    }

-}

diff --git a/src/builder.rs b/src/builder.rs
new file mode 100644
index 0000000..60aeb43
--- /dev/null
+++ b/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/src/builder/error.rs b/src/builder/error.rs
deleted file mode 100644
index ec7c2ac..0000000
--- a/src/builder/error.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use crate::std::fmt;

-

-/// The error that can occur when creating a [`Uuid`].

-///

-/// [`Uuid`]: struct.Uuid.html

-#[derive(Clone, Debug, Eq, Hash, PartialEq)]

-pub(crate) struct Error {

-    expected: usize,

-    found: usize,

-}

-

-impl Error {

-    /// The expected number of bytes.

-    #[inline]

-    const fn expected(&self) -> usize {

-        self.expected

-    }

-

-    /// The number of bytes found.

-    #[inline]

-    const fn found(&self) -> usize {

-        self.found

-    }

-

-    /// Create a new [`UuidError`].

-    ///

-    /// [`UuidError`]: struct.UuidError.html

-    #[inline]

-    pub(crate) const fn new(expected: usize, found: usize) -> Self {

-        Error { expected, found }

-    }

-}

-

-impl fmt::Display for Error {

-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-        write!(

-            f,

-            "invalid bytes length: expected {}, found {}",

-            self.expected(),

-            self.found()

-        )

-    }

-}

-

-#[cfg(feature = "std")]

-mod std_support {

-    use super::*;

-

-    use crate::std::error;

-

-    impl error::Error for Error {}

-}

diff --git a/src/builder/mod.rs b/src/builder/mod.rs
deleted file mode 100644
index 4360964..0000000
--- a/src/builder/mod.rs
+++ /dev/null
@@ -1,473 +0,0 @@
-// 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

-

-mod error;

-pub(crate) use self::error::Error;

-

-use crate::prelude::*;

-

-impl Uuid {

-    /// The 'nil UUID'.

-    ///

-    /// The nil UUID is special form of UUID that is specified to have all

-    /// 128 bits set to zero, as defined in [IETF RFC 4122 Section 4.1.7][RFC].

-    ///

-    /// [RFC]: https://tools.ietf.org/html/rfc4122.html#section-4.1.7

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// let uuid = Uuid::nil();

-    ///

-    /// assert_eq!(

-    ///     uuid.to_hyphenated().to_string(),

-    ///     "00000000-0000-0000-0000-000000000000"

-    /// );

-    /// ```

-    pub const fn nil() -> Self {

-        Uuid::from_bytes([0; 16])

-    }

-

-    /// Creates a UUID from four field values in big-endian order.

-    ///

-    /// # Errors

-    ///

-    /// This function will return an error if `d4`'s length is not 8 bytes.

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];

-    ///

-    /// let uuid = Uuid::from_fields(42, 12, 5, &d4);

-    /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());

-    ///

-    /// let expected_uuid =

-    ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    pub fn from_fields(

-        d1: u32,

-        d2: u16,

-        d3: u16,

-        d4: &[u8],

-    ) -> Result<Uuid, crate::Error> {

-        const D4_LEN: usize = 8;

-

-        let len = d4.len();

-

-        if len != D4_LEN {

-            Err(Error::new(D4_LEN, len))?;

-        }

-

-        Ok(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 converted into big-endian order.

-    ///

-    /// # Examples

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// let d1 = 0xAB3F1097u32;

-    /// let d2 = 0x501Eu16;

-    /// let d3 = 0xB736u16;

-    /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];

-    ///

-    /// let uuid = Uuid::from_fields_le(d1, d2, d3, &d4);

-    /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());

-    ///

-    /// let expected_uuid =

-    ///     Ok(String::from("97103fab-1e50-36b7-0c03-0938362b0809"));

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    pub fn from_fields_le(

-        d1: u32,

-        d2: u16,

-        d3: u16,

-        d4: &[u8],

-    ) -> Result<Uuid, crate::Error> {

-        const D4_LEN: usize = 8;

-

-        let len = d4.len();

-

-        if len != D4_LEN {

-            Err(Error::new(D4_LEN, len))?;

-        }

-

-        Ok(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 in big-endian order.

-    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.

-    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 using the supplied big-endian bytes.

-    ///

-    /// # Errors

-    ///

-    /// This function will return an error if `b` has any length other than 16.

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];

-    ///

-    /// let uuid = Uuid::from_slice(&bytes);

-    /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());

-    ///

-    /// let expected_uuid =

-    ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    ///

-    /// An incorrect number of bytes:

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];

-    ///

-    /// let uuid = Uuid::from_slice(&bytes);

-    ///

-    /// assert!(uuid.is_err());

-    /// ```

-    pub fn from_slice(b: &[u8]) -> Result<Uuid, crate::Error> {

-        const BYTES_LEN: usize = 16;

-

-        let len = b.len();

-

-        if len != BYTES_LEN {

-            Err(Error::new(BYTES_LEN, len))?;

-        }

-

-        let mut bytes: Bytes = [0; 16];

-        bytes.copy_from_slice(b);

-        Ok(Uuid::from_bytes(bytes))

-    }

-

-    /// Creates a UUID using the supplied big-endian bytes.

-    pub const fn from_bytes(bytes: Bytes) -> Uuid {

-        Uuid(bytes)

-    }

-}

-

-/// A builder struct for creating a UUID.

-///

-/// # Examples

-///

-/// Creating a v4 UUID from externally generated bytes:

-///

-/// ```

-/// 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_bytes(random_bytes)

-///     .set_variant(Variant::RFC4122)

-///     .set_version(Version::Random)

-///     .build();

-/// ```

-// TODO: remove in 1.0.0

-#[allow(dead_code)]

-#[deprecated]

-pub type Builder = crate::Builder;

-

-impl crate::Builder {

-    /// Creates a `Builder` using the supplied big-endian bytes.

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// let bytes: uuid::Bytes = [

-    ///     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,

-    /// ];

-    ///

-    /// let mut builder = uuid::Builder::from_bytes(bytes);

-    /// let uuid = builder.build().to_hyphenated().to_string();

-    ///

-    /// let expected_uuid = String::from("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e");

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    ///

-    /// An incorrect number of bytes:

-    ///

-    /// ```compile_fail

-    /// let bytes: uuid::Bytes = [4, 54, 67, 12, 43, 2, 98, 76]; // doesn't compile

-    ///

-    /// let uuid = uuid::Builder::from_bytes(bytes);

-    /// ```

-    pub const fn from_bytes(b: Bytes) -> Self {

-        Builder(b)

-    }

-

-    /// Creates a `Builder` using the supplied big-endian bytes.

-    ///

-    /// # Errors

-    ///

-    /// This function will return an error if `b` has any length other than 16.

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];

-    ///

-    /// let builder = uuid::Builder::from_slice(&bytes);

-    /// let uuid =

-    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());

-    ///

-    /// let expected_uuid =

-    ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    ///

-    /// An incorrect number of bytes:

-    ///

-    /// ```

-    /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];

-    ///

-    /// let builder = uuid::Builder::from_slice(&bytes);

-    ///

-    /// assert!(builder.is_err());

-    /// ```

-    pub fn from_slice(b: &[u8]) -> Result<Self, crate::Error> {

-        const BYTES_LEN: usize = 16;

-

-        let len = b.len();

-

-        if len != BYTES_LEN {

-            Err(Error::new(BYTES_LEN, len))?;

-        }

-

-        let mut bytes: crate::Bytes = [0; 16];

-        bytes.copy_from_slice(b);

-        Ok(Self::from_bytes(bytes))

-    }

-

-    /// Creates a `Builder` from four big-endian field values.

-    ///

-    /// # Errors

-    ///

-    /// This function will return an error if `d4`'s length is not 8 bytes.

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];

-    ///

-    /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);

-    /// let uuid =

-    ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());

-    ///

-    /// let expected_uuid =

-    ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));

-    ///

-    /// assert_eq!(expected_uuid, uuid);

-    /// ```

-    ///

-    /// An invalid length:

-    ///

-    /// ```

-    /// let d4 = [12];

-    ///

-    /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);

-    ///

-    /// assert!(builder.is_err());

-    /// ```

-    pub fn from_fields(

-        d1: u32,

-        d2: u16,

-        d3: u16,

-        d4: &[u8],

-    ) -> Result<Self, crate::Error> {

-        Uuid::from_fields(d1, d2, d3, d4).map(|uuid| {

-            let bytes = *uuid.as_bytes();

-

-            crate::Builder::from_bytes(bytes)

-        })

-    }

-

-    /// Creates a `Builder` from a big-endian 128bit value.

-    pub fn from_u128(v: u128) -> Self {

-        crate::Builder::from_bytes(*Uuid::from_u128(v).as_bytes())

-    }

-

-    /// Creates a `Builder` with an initial [`Uuid::nil`].

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// use uuid::Builder;

-    ///

-    /// let mut builder = Builder::nil();

-    ///

-    /// assert_eq!(

-    ///     builder.build().to_hyphenated().to_string(),

-    ///     "00000000-0000-0000-0000-000000000000"

-    /// );

-    /// ```

-    pub const fn nil() -> Self {

-        Builder([0; 16])

-    }

-

-    /// Specifies the variant of the UUID.

-    pub fn set_variant(&mut self, v: crate::Variant) -> &mut Self {

-        let byte = self.0[8];

-

-        self.0[8] = match v {

-            crate::Variant::NCS => byte & 0x7f,

-            crate::Variant::RFC4122 => (byte & 0x3f) | 0x80,

-            crate::Variant::Microsoft => (byte & 0x1f) | 0xc0,

-            crate::Variant::Future => (byte & 0x1f) | 0xe0,

-        };

-

-        self

-    }

-

-    /// Specifies the version number of the UUID.

-    pub fn set_version(&mut self, v: crate::Version) -> &mut Self {

-        self.0[6] = (self.0[6] & 0x0f) | ((v as u8) << 4);

-

-        self

-    }

-

-    /// Hands over the internal constructed [`Uuid`].

-    ///

-    /// # Examples

-    ///

-    /// Basic usage:

-    ///

-    /// ```

-    /// use uuid::Builder;

-    ///

-    /// let uuid = Builder::nil().build();

-    ///

-    /// assert_eq!(

-    ///     uuid.to_hyphenated().to_string(),

-    ///     "00000000-0000-0000-0000-000000000000"

-    /// );

-    /// ```

-    ///

-    /// [`Uuid`]: struct.Uuid.html

-    pub fn build(&mut self) -> Uuid {

-        Uuid::from_bytes(self.0)

-    }

-}

diff --git a/src/error.rs b/src/error.rs
index 59f3f5e..e9aecbf 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,79 +1,172 @@
-use crate::std::fmt;

-use crate::{builder, parser};

-

-/// A general error that can occur when working with UUIDs.

-// TODO: improve the doc

-// BODY: This detail should be fine for initial merge

-#[derive(Clone, Debug, Eq, Hash, PartialEq)]

-pub struct Error(Inner);

-

-// TODO: write tests for Error

-// BODY: not immediately blocking, but should be covered for 1.0

-#[derive(Clone, Debug, Eq, Hash, PartialEq)]

-enum Inner {

-    /// An error occurred while handling [`Uuid`] bytes.

-    ///

-    /// See [`BytesError`]

-    ///

-    /// [`BytesError`]: struct.BytesError.html

-    /// [`Uuid`]: struct.Uuid.html

-    Build(builder::Error),

-

-    /// An error occurred while parsing a [`Uuid`] string.

-    ///

-    /// See [`parser::ParseError`]

-    ///

-    /// [`parser::ParseError`]: parser/enum.ParseError.html

-    /// [`Uuid`]: struct.Uuid.html

-    Parser(parser::Error),

-}

-

-impl From<builder::Error> for Error {

-    fn from(err: builder::Error) -> Self {

-        Error(Inner::Build(err))

-    }

-}

-

-impl From<parser::Error> for Error {

-    fn from(err: parser::Error) -> Self {

-        Error(Inner::Parser(err))

-    }

-}

-

-impl fmt::Display for Error {

-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-        match self.0 {

-            Inner::Build(ref err) => fmt::Display::fmt(&err, f),

-            Inner::Parser(ref err) => fmt::Display::fmt(&err, f),

-        }

-    }

-}

-

-#[cfg(feature = "std")]

-mod std_support {

-    use super::*;

-    use crate::std::error;

-

-    impl error::Error for Error {

-        fn source(&self) -> Option<&(dyn error::Error + 'static)> {

-            match self.0 {

-                Inner::Build(ref err) => Some(err),

-                Inner::Parser(ref err) => Some(err),

-            }

-        }

-    }

-}

-

-#[cfg(test)]

-mod test_util {

-    use super::*;

-

-    impl Error {

-        pub(crate) fn expect_parser(self) -> parser::Error {

-            match self.0 {

-                Inner::Parser(err) => err,

-                _ => panic!("expected a `parser::Error` variant"),

-            }

-        }

-    }

-}

+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/src/external.rs b/src/external.rs
new file mode 100644
index 0000000..219a923
--- /dev/null
+++ b/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/src/external/arbitrary_support.rs b/src/external/arbitrary_support.rs
new file mode 100644
index 0000000..38cce7c
--- /dev/null
+++ b/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/src/external/serde_support.rs b/src/external/serde_support.rs
new file mode 100644
index 0000000..5228daf
--- /dev/null
+++ b/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/src/slog_support.rs b/src/external/slog_support.rs
similarity index 85%
rename from src/slog_support.rs
rename to src/external/slog_support.rs
index 472b39a..2d6e817 100644
--- a/src/slog_support.rs
+++ b/src/external/slog_support.rs
@@ -1,39 +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::prelude::*;

-use slog;

-

-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 {

-

-    #[test]

-    fn test_slog_kv() {

-        use crate::test_util;

-        use slog;

-        use slog::{crit, Drain};

-

-        let root = slog::Logger::root(slog::Discard.fuse(), slog::o!());

-        let u1 = test_util::new();

-        crit!(root, "test"; "u1" => u1);

-    }

-}

+// 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/src/fmt.rs b/src/fmt.rs
new file mode 100644
index 0000000..92b4042
--- /dev/null
+++ b/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/src/lib.rs b/src/lib.rs
index 51d3877..05ebc2d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,1070 +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 UUIDs.

-//!

-//! Provides support for Universally Unique Identifiers (UUIDs). A UUID is a

-//! unique 128-bit number, stored as 16 octets. 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.

-//!

-//! # Dependencies

-//!

-//! By default, this crate depends on nothing but `std` and cannot generate

-//! UUIDs. You need to enable the following Cargo features to enable

-//! various pieces of functionality:

-//!

-//! * `v1` - adds the [`Uuid::new_v1`] function and the ability to create a V1

-//!   using an implementation of [`v1::ClockSequence`] (usually

-//! [`v1::Context`]) and a timestamp from `time::timespec`.

-//! * `v3` - adds the [`Uuid::new_v3`] function and the ability to create a V3

-//!   UUID based on the MD5 hash of some data.

-//! * `v4` - adds the [`Uuid::new_v4`] function and the ability to randomly

-//!   generate a UUID.

-//! * `v5` - adds the [`Uuid::new_v5`] function and the ability to create a V5

-//!   UUID based on the SHA1 hash of some data.

-//! * `serde` - adds the ability to serialize and deserialize a UUID using the

-//!   `serde` crate.

-//!

-//! For WebAssembly, enable one of the following features depending

-//! on your JavaScript interop toolchain of choice:

-//!

-//! * `stdweb` - for [`stdweb`] combined with [`cargo-web`]

-//! * `wasm-bindgen` - for [`wasm-bindgen`]

-//!

-//! By default, `uuid` can be depended on with:

-//!

-//! ```toml

-//! [dependencies]

-//! uuid = "0.8"

-//! ```

-//!

-//! To activate various features, use syntax like:

-//!

-//! ```toml

-//! [dependencies]

-//! uuid = { version = "0.8", features = ["serde", "v4"] }

-//! ```

-//!

-//! You can disable default features with:

-//!

-//! ```toml

-//! [dependencies]

-//! uuid = { version = "0.8", default-features = false }

-//! ```

-//!

-//! # Examples

-//!

-//! To parse a UUID given in the simple format and print it as a urn:

-//!

-//! ```rust

-//! use uuid::Uuid;

-//!

-//! fn main() -> Result<(), uuid::Error> {

-//!     let my_uuid =

-//!         Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8")?;

-//!     println!("{}", my_uuid.to_urn());

-//!     Ok(())

-//! }

-//! ```

-//!

-//! To create a new random (V4) UUID and print it out in hexadecimal form:

-//!

-//! ```ignore,rust

-//! // Note that this requires the `v4` feature enabled in the uuid crate.

-//!

-//! use uuid::Uuid;

-//!

-//! fn main() -> Result<(), Box<dyn std::error::Error>> {

-//!     #[cfg(feature = "v4")] {

-//!         let my_uuid = Uuid::new_v4()?;

-//!         println!("{}", my_uuid);

-//!     }

-//!     Ok(())

-//! }

-//! ```

-//!

-//! # Strings

-//!

-//! Examples of string representations:

-//!

-//! * simple: `936DA01F9ABD4d9d80C702AF85C822A8`

-//! * hyphenated: `550e8400-e29b-41d4-a716-446655440000`

-//! * urn: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`

-//!

-//! # 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)

-//!

-//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen

-//! [`cargo-web`]: https://crates.io/crates/cargo-web

-//! [`stdweb`]: https://crates.io/crates/stdweb

-//! [`Uuid`]: struct.Uuid.html

-//! [`Uuid::new_v1`]: struct.Uuid.html#method.new_v1

-//! [`Uuid::new_v3`]: struct.Uuid.html#method.new_v3

-//! [`Uuid::new_v4`]: struct.Uuid.html#method.new_v4

-//! [`Uuid::new_v5`]: struct.Uuid.html#method.new_v5

-//! [`v1::ClockSequence`]: v1/trait.ClockSequence.html

-//! [`v1::Context`]: v1/struct.Context.html

-

-#![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/0.8.2"

-)]

-

-#[cfg(any(feature = "std", test))]

-#[macro_use]

-extern crate std;

-

-#[cfg(all(not(feature = "std"), not(test)))]

-#[macro_use]

-extern crate core as std;

-

-mod builder;

-mod error;

-mod parser;

-mod prelude;

-

-pub mod adapter;

-#[cfg(feature = "v1")]

-pub mod v1;

-

-#[cfg(feature = "serde")]

-mod serde_support;

-#[cfg(feature = "slog")]

-mod slog_support;

-#[cfg(test)]

-mod test_util;

-#[cfg(all(

-    feature = "v3",

-    any(

-        not(target_arch = "wasm32"),

-        target_os = "wasi",

-        all(

-            target_arch = "wasm32",

-            any(feature = "stdweb", feature = "wasm-bindgen")

-        )

-    )

-))]

-mod v3;

-#[cfg(all(

-    feature = "v4",

-    any(

-        not(target_arch = "wasm32"),

-        target_os = "wasi",

-        all(

-            target_arch = "wasm32",

-            any(feature = "stdweb", feature = "wasm-bindgen")

-        )

-    )

-))]

-mod v4;

-#[cfg(all(

-    feature = "v5",

-    any(

-        not(target_arch = "wasm32"),

-        target_os = "wasi",

-        all(

-            target_arch = "wasm32",

-            any(feature = "stdweb", feature = "wasm-bindgen")

-        )

-    )

-))]

-mod v5;

-#[cfg(all(windows, feature = "winapi"))]

-mod winapi_support;

-

-use crate::std::{fmt, str};

-

-pub use crate::error::Error;

-

-/// A builder struct for creating a UUID.

-///

-/// # Examples

-///

-/// Creating a v4 UUID from externally generated bytes:

-///

-/// ```

-/// 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_bytes(random_bytes)

-///     .set_variant(Variant::RFC4122)

-///     .set_version(Version::Random)

-///     .build();

-/// ```

-#[allow(missing_copy_implementations)]

-#[derive(Debug)]

-pub struct Builder(Bytes);

-

-/// A 128-bit (16 byte) buffer containing the ID.

-pub type Bytes = [u8; 16];

-

-/// The version of the UUID, denoting the generating algorithm.

-#[derive(Clone, Copy, Debug, PartialEq)]

-pub enum Version {

-    /// Special case for `nil` UUID.

-    Nil = 0,

-    /// Version 1: MAC address.

-    Mac,

-    /// Version 2: DCE Security.

-    Dce,

-    /// Version 3: MD5 hash.

-    Md5,

-    /// Version 4: Random.

-    Random,

-    /// Version 5: SHA-1 hash.

-    Sha1,

-}

-

-/// The reserved variants of UUIDs.

-#[derive(Clone, Copy, Debug, PartialEq)]

-pub enum Variant {

-    /// Reserved by the NCS for backward compatibility.

-    NCS = 0,

-    /// 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).

-#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]

-#[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.

-    /// Currently only the RFC4122 variant is generated by this module.

-    ///

-    /// * [Variant Reference](http://tools.ietf.org/html/rfc4122#section-4.1.1)

-    pub fn get_variant(&self) -> Option<Variant> {

-        match self.as_bytes()[8] {

-            x if x & 0x80 == 0x00 => Some(Variant::NCS),

-            x if x & 0xc0 == 0x80 => Some(Variant::RFC4122),

-            x if x & 0xe0 == 0xc0 => Some(Variant::Microsoft),

-            x if x & 0xe0 == 0xe0 => Some(Variant::Future),

-            _ => None,

-        }

-    }

-

-    /// Returns the version number of the UUID.

-    ///

-    /// This represents the algorithm used to generate the contents.

-    ///

-    /// Currently only the Random (V4) algorithm is supported by this

-    /// module.  There are security and privacy implications for using

-    /// older versions - see [Wikipedia: Universally Unique Identifier](

-    /// http://en.wikipedia.org/wiki/Universally_unique_identifier) for

-    /// details.

-    ///

-    /// * [Version Reference](http://tools.ietf.org/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 contents

-    pub fn get_version(&self) -> Option<Version> {

-        let v = self.as_bytes()[6] >> 4;

-        match v {

-            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),

-            _ => None,

-        }

-    }

-

-    /// Returns the four field values of the UUID in big-endian order.

-    ///

-    /// These values can be passed to the `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("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?;

-    ///     assert_eq!(

-    ///         uuid.as_fields(),

-    ///         (

-    ///             0x936DA01F,

-    ///             0x9ABD,

-    ///             0x4D9D,

-    ///             b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8"

-    ///         )

-    ///     );

-    ///

-    ///     Ok(())

-    /// }

-    /// ```

-    pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {

-        let d1 = u32::from(self.as_bytes()[0]) << 24

-            | u32::from(self.as_bytes()[1]) << 16

-            | u32::from(self.as_bytes()[2]) << 8

-            | u32::from(self.as_bytes()[3]);

-

-        let d2 =

-            u16::from(self.as_bytes()[4]) << 8 | u16::from(self.as_bytes()[5]);

-

-        let d3 =

-            u16::from(self.as_bytes()[6]) << 8 | u16::from(self.as_bytes()[7]);

-

-        let d4: &[u8; 8] =

-            unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) };

-        (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.

-    ///

-    /// # Examples

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// fn main() -> Result<(), uuid::Error> {

-    ///     let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?;

-    ///     assert_eq!(

-    ///         uuid.to_fields_le(),

-    ///         (

-    ///             0x1FA06D93,

-    ///             0xBD9A,

-    ///             0x9D4D,

-    ///             b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8"

-    ///         )

-    ///     );

-    ///     Ok(())

-    /// }

-    /// ```

-    pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {

-        let d1 = u32::from(self.as_bytes()[0])

-            | u32::from(self.as_bytes()[1]) << 8

-            | u32::from(self.as_bytes()[2]) << 16

-            | u32::from(self.as_bytes()[3]) << 24;

-

-        let d2 =

-            u16::from(self.as_bytes()[4]) | u16::from(self.as_bytes()[5]) << 8;

-

-        let d3 =

-            u16::from(self.as_bytes()[6]) | u16::from(self.as_bytes()[7]) << 8;

-

-        let d4: &[u8; 8] =

-            unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) };

-        (d1, d2, d3, d4)

-    }

-

-    /// Returns a 128bit value containing the UUID data.

-    ///

-    /// The bytes in the UUID will be packed into a `u128`, like the

-    /// [`Uuid::as_bytes`] method.

-    ///

-    /// # Examples

-    ///

-    /// ```

-    /// use uuid::Uuid;

-    ///

-    /// fn main() -> Result<(), uuid::Error> {

-    ///     let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?;

-    ///     assert_eq!(

-    ///         uuid.as_u128(),

-    ///         0x936DA01F9ABD4D9D80C702AF85C822A8,

-    ///     );

-    ///     Ok(())

-    /// }

-    /// ```

-    pub fn as_u128(&self) -> u128 {

-        u128::from(self.as_bytes()[0]) << 120

-            | u128::from(self.as_bytes()[1]) << 112

-            | u128::from(self.as_bytes()[2]) << 104

-            | u128::from(self.as_bytes()[3]) << 96

-            | u128::from(self.as_bytes()[4]) << 88

-            | u128::from(self.as_bytes()[5]) << 80

-            | u128::from(self.as_bytes()[6]) << 72

-            | u128::from(self.as_bytes()[7]) << 64

-            | u128::from(self.as_bytes()[8]) << 56

-            | u128::from(self.as_bytes()[9]) << 48

-            | u128::from(self.as_bytes()[10]) << 40

-            | u128::from(self.as_bytes()[11]) << 32

-            | u128::from(self.as_bytes()[12]) << 24

-            | u128::from(self.as_bytes()[13]) << 16

-            | u128::from(self.as_bytes()[14]) << 8

-            | u128::from(self.as_bytes()[15])

-    }

-

-    /// Returns a 128bit little-endian value containing the UUID data.

-    ///

-    /// The bytes in the UUID will be reversed and packed into a `u128`.

-    /// 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("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?;

-    ///

-    ///     assert_eq!(

-    ///         uuid.to_u128_le(),

-    ///         0xA822C885AF02C7809D4DBD9A1FA06D93,

-    ///     );

-    ///     Ok(())

-    /// }

-    /// ```

-    pub fn to_u128_le(&self) -> u128 {

-        u128::from(self.as_bytes()[0])

-            | u128::from(self.as_bytes()[1]) << 8

-            | u128::from(self.as_bytes()[2]) << 16

-            | u128::from(self.as_bytes()[3]) << 24

-            | u128::from(self.as_bytes()[4]) << 32

-            | u128::from(self.as_bytes()[5]) << 40

-            | u128::from(self.as_bytes()[6]) << 48

-            | u128::from(self.as_bytes()[7]) << 56

-            | u128::from(self.as_bytes()[8]) << 64

-            | u128::from(self.as_bytes()[9]) << 72

-            | u128::from(self.as_bytes()[10]) << 80

-            | u128::from(self.as_bytes()[11]) << 88

-            | u128::from(self.as_bytes()[12]) << 96

-            | u128::from(self.as_bytes()[13]) << 104

-            | u128::from(self.as_bytes()[14]) << 112

-            | u128::from(self.as_bytes()[15]) << 120

-    }

-

-    /// Returns an array of 16 octets containing the UUID data.

-    pub const fn as_bytes(&self) -> &Bytes {

-        &self.0

-    }

-

-    /// Tests if the UUID is nil.

-    pub fn is_nil(&self) -> bool {

-        self.as_bytes().iter().all(|&b| b == 0)

-    }

-

-    /// A buffer that can be used for `encode_...` calls, that is

-    /// guaranteed to be long enough for any of the adapters.

-    ///

-    /// # Examples

-    ///

-    /// ```rust

-    /// use uuid::Uuid;

-    ///

-    /// let uuid = Uuid::nil();

-    ///

-    /// assert_eq!(

-    ///     uuid.to_simple().encode_lower(&mut Uuid::encode_buffer()),

-    ///     "00000000000000000000000000000000"

-    /// );

-    ///

-    /// assert_eq!(

-    ///     uuid.to_hyphenated()

-    ///         .encode_lower(&mut Uuid::encode_buffer()),

-    ///     "00000000-0000-0000-0000-000000000000"

-    /// );

-    ///

-    /// assert_eq!(

-    ///     uuid.to_urn().encode_lower(&mut Uuid::encode_buffer()),

-    ///     "urn:uuid:00000000-0000-0000-0000-000000000000"

-    /// );

-    /// ```

-    pub const fn encode_buffer() -> [u8; adapter::Urn::LENGTH] {

-        [0; adapter::Urn::LENGTH]

-    }

-}

-

-impl 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.to_hyphenated_ref(), f)

-    }

-}

-

-impl fmt::UpperHex for Uuid {

-    #[inline]

-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-        fmt::UpperHex::fmt(&self.to_hyphenated_ref(), f)

-    }

-}

-

-impl str::FromStr for Uuid {

-    type Err = Error;

-

-    fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {

-        Uuid::parse_str(uuid_str)

-    }

-}

-

-impl Default for Uuid {

-    #[inline]

-    fn default() -> Self {

-        Uuid::nil()

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use crate::{

-        prelude::*,

-        std::string::{String, ToString},

-        test_util,

-    };

-

-    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);

-        };

-    }

-

-    #[test]

-    fn test_uuid_compare() {

-        let uuid1 = test_util::new();

-        let uuid2 = test_util::new2();

-

-        assert_eq!(uuid1, uuid1);

-        assert_eq!(uuid2, uuid2);

-

-        assert_ne!(uuid1, uuid2);

-        assert_ne!(uuid2, uuid1);

-    }

-

-    #[test]

-    fn test_uuid_default() {

-        let default_uuid = Uuid::default();

-        let nil_uuid = Uuid::nil();

-

-        assert_eq!(default_uuid, nil_uuid);

-    }

-

-    #[test]

-    fn test_uuid_display() {

-        use super::fmt::Write;

-

-        let uuid = test_util::new();

-        let s = uuid.to_string();

-        let mut buffer = String::new();

-

-        assert_eq!(s, uuid.to_hyphenated().to_string());

-

-        check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()

-            || c.is_digit(10)

-            || c == '-');

-    }

-

-    #[test]

-    fn test_uuid_lowerhex() {

-        use super::fmt::Write;

-

-        let mut buffer = String::new();

-        let uuid = test_util::new();

-

-        check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()

-            || c.is_digit(10)

-            || c == '-');

-    }

-

-    // noinspection RsAssertEqual

-    #[test]

-    fn test_uuid_operator_eq() {

-        let uuid1 = test_util::new();

-        let uuid1_dup = uuid1.clone();

-        let uuid2 = test_util::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]

-    fn test_uuid_to_string() {

-        use super::fmt::Write;

-

-        let uuid = test_util::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]

-    fn test_uuid_upperhex() {

-        use super::fmt::Write;

-

-        let mut buffer = String::new();

-        let uuid = test_util::new();

-

-        check!(buffer, "{:X}", uuid, 36, |c| c.is_uppercase()

-            || c.is_digit(10)

-            || c == '-');

-    }

-

-    #[test]

-    fn test_nil() {

-        let nil = Uuid::nil();

-        let not_nil = test_util::new();

-        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);

-

-        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))

-    }

-

-    #[test]

-    fn test_predefined_namespaces() {

-        assert_eq!(

-            Uuid::NAMESPACE_DNS.to_hyphenated().to_string(),

-            "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

-        );

-        assert_eq!(

-            Uuid::NAMESPACE_URL.to_hyphenated().to_string(),

-            "6ba7b811-9dad-11d1-80b4-00c04fd430c8"

-        );

-        assert_eq!(

-            Uuid::NAMESPACE_OID.to_hyphenated().to_string(),

-            "6ba7b812-9dad-11d1-80b4-00c04fd430c8"

-        );

-        assert_eq!(

-            Uuid::NAMESPACE_X500.to_hyphenated().to_string(),

-            "6ba7b814-9dad-11d1-80b4-00c04fd430c8"

-        );

-    }

-

-    #[cfg(feature = "v3")]

-    #[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]

-    fn test_get_variant() {

-        let uuid1 = test_util::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().unwrap(), Variant::RFC4122);

-        assert_eq!(uuid2.get_variant().unwrap(), Variant::RFC4122);

-        assert_eq!(uuid3.get_variant().unwrap(), Variant::RFC4122);

-        assert_eq!(uuid4.get_variant().unwrap(), Variant::Microsoft);

-        assert_eq!(uuid5.get_variant().unwrap(), Variant::Microsoft);

-        assert_eq!(uuid6.get_variant().unwrap(), Variant::NCS);

-    }

-

-    #[test]

-    fn test_to_simple_string() {

-        let uuid1 = test_util::new();

-        let s = uuid1.to_simple().to_string();

-

-        assert_eq!(s.len(), 32);

-        assert!(s.chars().all(|c| c.is_digit(16)));

-    }

-

-    #[test]

-    fn test_to_hyphenated_string() {

-        let uuid1 = test_util::new();

-        let s = uuid1.to_hyphenated().to_string();

-

-        assert!(s.len() == 36);

-        assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));

-    }

-

-    #[test]

-    fn test_upper_lower_hex() {

-        use std::fmt::Write;

-

-        let mut buf = String::new();

-        let u = test_util::new();

-

-        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);

-            };

-        }

-

-        check!(buf, "{:X}", u, 36, |c| c.is_uppercase()

-            || c.is_digit(10)

-            || c == '-');

-        check!(buf, "{:X}", u.to_hyphenated(), 36, |c| c.is_uppercase()

-            || c.is_digit(10)

-            || c == '-');

-        check!(buf, "{:X}", u.to_simple(), 32, |c| c.is_uppercase()

-            || c.is_digit(10));

-

-        check!(buf, "{:x}", u.to_hyphenated(), 36, |c| c.is_lowercase()

-            || c.is_digit(10)

-            || c == '-');

-        check!(buf, "{:x}", u.to_simple(), 32, |c| c.is_lowercase()

-            || c.is_digit(10));

-    }

-

-    #[test]

-    fn test_to_urn_string() {

-        let uuid1 = test_util::new();

-        let ss = uuid1.to_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]

-    fn test_to_simple_string_matching() {

-        let uuid1 = test_util::new();

-

-        let hs = uuid1.to_hyphenated().to_string();

-        let ss = uuid1.to_simple().to_string();

-

-        let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();

-

-        assert_eq!(hsn, ss);

-    }

-

-    #[test]

-    fn test_string_roundtrip() {

-        let uuid = test_util::new();

-

-        let hs = uuid.to_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]

-    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).unwrap();

-

-        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";

-        let result = u.to_simple().to_string();

-        assert_eq!(result, expected);

-    }

-

-    #[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).unwrap();

-

-        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";

-        let result = u.to_simple().to_string();

-        assert_eq!(result, expected);

-    }

-

-    #[test]

-    fn test_as_fields() {

-        let u = test_util::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]

-    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).unwrap();

-        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]

-    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).unwrap();

-        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]

-    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).unwrap();

-        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]

-    fn test_from_u128() {

-        let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;

-

-        let u = Uuid::from_u128(v_in);

-

-        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";

-        let result = u.to_simple().to_string();

-        assert_eq!(result, expected);

-    }

-

-    #[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.to_simple().to_string();

-        assert_eq!(result, expected);

-    }

-

-    #[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]

-    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]

-    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]

-    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.to_simple().to_string(), expected);

-    }

-

-    #[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.to_simple().to_string(), expected);

-    }

-

-    #[test]

-    fn test_as_bytes() {

-        let u = test_util::new();

-        let ub = u.as_bytes();

-

-        assert_eq!(ub.len(), 16);

-        assert!(!ub.iter().all(|&b| b == 0));

-    }

-

-    #[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]

-    fn test_iterbytes_impl_for_uuid() {

-        let mut set = std::collections::HashSet::new();

-        let id1 = test_util::new();

-        let id2 = test_util::new2();

-        set.insert(id1.clone());

-

-        assert!(set.contains(&id1));

-        assert!(!set.contains(&id2));

-    }

-}

+// 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/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..281c533
--- /dev/null
+++ b/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/src/md5.rs b/src/md5.rs
new file mode 100644
index 0000000..fce5d9b
--- /dev/null
+++ b/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/src/parser.rs b/src/parser.rs
new file mode 100644
index 0000000..bc5f826
--- /dev/null
+++ b/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/src/parser/error.rs b/src/parser/error.rs
deleted file mode 100644
index 01d76e8..0000000
--- a/src/parser/error.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::std::fmt;

-

-/// An error that can occur while parsing a [`Uuid`] string.

-///

-/// [`Uuid`]: ../struct.Uuid.html

-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]

-#[allow(clippy::enum_variant_names)]

-pub(crate) enum Error {

-    /// Invalid character in the [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    InvalidCharacter {

-        /// The expected characters.

-        expected: &'static str,

-        /// The invalid character found.

-        found: char,

-        /// The invalid character position.

-        index: usize,

-        /// Indicates the [`Uuid`] starts with `urn:uuid:`.

-        ///

-        /// This is a special case for [`Urn`] adapter parsing.

-        ///

-        /// [`Uuid`]: ../Uuid.html

-        urn: UrnPrefix,

-    },

-    /// Invalid number of segments in the [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    InvalidGroupCount {

-        /// The expected number of segments.

-        // TODO: explain multiple segment count.

-        // BODY: Parsers can expect a range of Uuid segment count.

-        //       This needs to be expanded on.

-        expected: ExpectedLength,

-        /// The number of segments found.

-        found: usize,

-    },

-    /// Invalid length of a segment in a [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    InvalidGroupLength {

-        /// The expected length of the segment.

-        expected: ExpectedLength,

-        /// The length of segment found.

-        found: usize,

-        /// The segment with invalid length.

-        group: usize,

-    },

-    /// Invalid length of the [`Uuid`] string.

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    InvalidLength {

-        /// The expected length(s).

-        // TODO: explain multiple lengths.

-        // BODY: Parsers can expect a range of Uuid lenghts.

-        //       This needs to be expanded on.

-        expected: ExpectedLength,

-        /// The invalid length found.

-        found: usize,

-    },

-}

-

-/// The expected length.

-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub(crate) enum ExpectedLength {

-    /// Expected any one of the given values.

-    Any(&'static [usize]),

-    /// Expected the given value.

-    Exact(usize),

-}

-

-/// Urn prefix value.

-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]

-pub(crate) enum UrnPrefix {

-    /// The `urn:uuid:` prefix should optionally provided.

-    Optional,

-}

-

-impl Error {

-    fn _description(&self) -> &str {

-        match *self {

-            Error::InvalidCharacter { .. } => "invalid character",

-            Error::InvalidGroupCount { .. } => "invalid number of groups",

-            Error::InvalidGroupLength { .. } => "invalid group length",

-            Error::InvalidLength { .. } => "invalid length",

-        }

-    }

-}

-

-impl fmt::Display for ExpectedLength {

-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-        match *self {

-            ExpectedLength::Any(crits) => write!(f, "one of {:?}", crits),

-            ExpectedLength::Exact(crit) => write!(f, "{}", crit),

-        }

-    }

-}

-

-impl fmt::Display for Error {

-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

-        write!(f, "{}: ", self._description())?;

-

-        match *self {

-            Error::InvalidCharacter {

-                expected,

-                found,

-                index,

-                urn,

-            } => {

-                let urn_str = match urn {

-                    UrnPrefix::Optional => {

-                        " an optional prefix of `urn:uuid:` followed by"

-                    }

-                };

-

-                write!(

-                    f,

-                    "expected{} {}, found {} at {}",

-                    urn_str, expected, found, index

-                )

-            }

-            Error::InvalidGroupCount {

-                ref expected,

-                found,

-            } => write!(f, "expected {}, found {}", expected, found),

-            Error::InvalidGroupLength {

-                ref expected,

-                found,

-                group,

-            } => write!(

-                f,

-                "expected {}, found {} in group {}",

-                expected, found, group,

-            ),

-            Error::InvalidLength {

-                ref expected,

-                found,

-            } => write!(f, "expected {}, found {}", expected, found),

-        }

-    }

-}

-

-#[cfg(feature = "std")]

-mod std_support {

-    use super::*;

-    use crate::std::error;

-

-    impl error::Error for Error {}

-}

diff --git a/src/parser/mod.rs b/src/parser/mod.rs
deleted file mode 100644
index a80f696..0000000
--- a/src/parser/mod.rs
+++ /dev/null
@@ -1,447 +0,0 @@
-// 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

-

-pub(crate) mod error;

-pub(crate) use self::error::Error;

-

-use crate::{adapter, Uuid};

-

-/// Check if the length matches any of the given criteria lengths.

-fn len_matches_any(len: usize, crits: &[usize]) -> bool {

-    for crit in crits {

-        if len == *crit {

-            return true;

-        }

-    }

-

-    false

-}

-

-/// Check if the length matches any criteria lengths in the given range

-/// (inclusive).

-#[allow(dead_code)]

-fn len_matches_range(len: usize, min: usize, max: usize) -> bool {

-    for crit in min..=max {

-        if len == crit {

-            return true;

-        }

-    }

-

-    false

-}

-

-// Accumulated length of each hyphenated group in hex digits.

-const ACC_GROUP_LENS: [usize; 5] = [8, 12, 16, 20, 32];

-

-// Length of each hyphenated group in hex digits.

-const GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];

-

-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)

-    /// are supported by this parsing function.

-    pub fn parse_str(mut input: &str) -> Result<Uuid, crate::Error> {

-        // Ensure length is valid for any of the supported formats

-        let len = input.len();

-

-        if len == adapter::Urn::LENGTH && input.starts_with("urn:uuid:") {

-            input = &input[9..];

-        } else if !len_matches_any(

-            len,

-            &[adapter::Hyphenated::LENGTH, adapter::Simple::LENGTH],

-        ) {

-            Err(Error::InvalidLength {

-                expected: error::ExpectedLength::Any(&[

-                    adapter::Hyphenated::LENGTH,

-                    adapter::Simple::LENGTH,

-                ]),

-                found: len,

-            })?;

-        }

-

-        // `digit` counts only hexadecimal digits, `i_char` counts all chars.

-        let mut digit = 0;

-        let mut group = 0;

-        let mut acc = 0;

-        let mut buffer = [0u8; 16];

-

-        for (i_char, chr) in input.bytes().enumerate() {

-            if digit as usize >= adapter::Simple::LENGTH && group != 4 {

-                if group == 0 {

-                    Err(Error::InvalidLength {

-                        expected: error::ExpectedLength::Any(&[

-                            adapter::Hyphenated::LENGTH,

-                            adapter::Simple::LENGTH,

-                        ]),

-                        found: len,

-                    })?;

-                }

-

-                Err(Error::InvalidGroupCount {

-                    expected: error::ExpectedLength::Any(&[1, 5]),

-                    found: group + 1,

-                })?;

-            }

-

-            if digit % 2 == 0 {

-                // First digit of the byte.

-                match chr {

-                    // Calulate upper half.

-                    b'0'..=b'9' => acc = chr - b'0',

-                    b'a'..=b'f' => acc = chr - b'a' + 10,

-                    b'A'..=b'F' => acc = chr - b'A' + 10,

-                    // Found a group delimiter

-                    b'-' => {

-                        // TODO: remove the u8 cast

-                        // BODY: this only needed until we switch to

-                        //       ParseError

-                        if ACC_GROUP_LENS[group] as u8 != digit {

-                            // Calculate how many digits this group consists of

-                            // in the input.

-                            let found = if group > 0 {

-                                // TODO: remove the u8 cast

-                                // BODY: this only needed until we switch to

-                                //       ParseError

-                                digit - ACC_GROUP_LENS[group - 1] as u8

-                            } else {

-                                digit

-                            };

-

-                            Err(Error::InvalidGroupLength {

-                                expected: error::ExpectedLength::Exact(

-                                    GROUP_LENS[group],

-                                ),

-                                found: found as usize,

-                                group,

-                            })?;

-                        }

-                        // Next group, decrement digit, it is incremented again

-                        // at the bottom.

-                        group += 1;

-                        digit -= 1;

-                    }

-                    _ => {

-                        Err(Error::InvalidCharacter {

-                            expected: "0123456789abcdefABCDEF-",

-                            found: input[i_char..].chars().next().unwrap(),

-                            index: i_char,

-                            urn: error::UrnPrefix::Optional,

-                        })?;

-                    }

-                }

-            } else {

-                // Second digit of the byte, shift the upper half.

-                acc *= 16;

-                match chr {

-                    b'0'..=b'9' => acc += chr - b'0',

-                    b'a'..=b'f' => acc += chr - b'a' + 10,

-                    b'A'..=b'F' => acc += chr - b'A' + 10,

-                    b'-' => {

-                        // The byte isn't complete yet.

-                        let found = if group > 0 {

-                            // TODO: remove the u8 cast

-                            // BODY: this only needed until we switch to

-                            //       ParseError

-                            digit - ACC_GROUP_LENS[group - 1] as u8

-                        } else {

-                            digit

-                        };

-

-                        Err(Error::InvalidGroupLength {

-                            expected: error::ExpectedLength::Exact(

-                                GROUP_LENS[group],

-                            ),

-                            found: found as usize,

-                            group,

-                        })?;

-                    }

-                    _ => {

-                        Err(Error::InvalidCharacter {

-                            expected: "0123456789abcdefABCDEF-",

-                            found: input[i_char..].chars().next().unwrap(),

-                            index: i_char,

-                            urn: error::UrnPrefix::Optional,

-                        })?;

-                    }

-                }

-                buffer[(digit / 2) as usize] = acc;

-            }

-            digit += 1;

-        }

-

-        // Now check the last group.

-        // TODO: remove the u8 cast

-        // BODY: this only needed until we switch to

-        //       ParseError

-        if ACC_GROUP_LENS[4] as u8 != digit {

-            Err(Error::InvalidGroupLength {

-                expected: error::ExpectedLength::Exact(GROUP_LENS[4]),

-                found: (digit as usize - ACC_GROUP_LENS[3]),

-                group,

-            })?;

-        }

-

-        Ok(Uuid::from_bytes(buffer))

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use super::*;

-    use crate::{adapter, std::string::ToString, test_util};

-

-    #[test]

-    fn test_parse_uuid_v4() {

-        const EXPECTED_UUID_LENGTHS: error::ExpectedLength =

-            error::ExpectedLength::Any(&[

-                adapter::Hyphenated::LENGTH,

-                adapter::Simple::LENGTH,

-            ]);

-

-        const EXPECTED_GROUP_COUNTS: error::ExpectedLength =

-            error::ExpectedLength::Any(&[1, 5]);

-

-        const EXPECTED_CHARS: &'static str = "0123456789abcdefABCDEF-";

-

-        // Invalid

-        assert_eq!(

-            Uuid::parse_str("").map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 0,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("!").map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 1

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 37,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 35

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidCharacter {

-                expected: EXPECTED_CHARS,

-                found: 'G',

-                index: 20,

-                urn: error::UrnPrefix::Optional,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2F4faaFB6BFF329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupCount {

-                expected: EXPECTED_GROUP_COUNTS,

-                found: 2

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faaFB6BFF329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupCount {

-                expected: EXPECTED_GROUP_COUNTS,

-                found: 3,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupCount {

-                expected: EXPECTED_GROUP_COUNTS,

-                found: 4,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 18,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidCharacter {

-                expected: EXPECTED_CHARS,

-                found: 'X',

-                index: 18,

-                urn: error::UrnPrefix::Optional,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupLength {

-                expected: error::ExpectedLength::Exact(4),

-                found: 3,

-                group: 1,

-            })

-        );

-        // (group, found, expecting)

-        //

-        assert_eq!(

-            Uuid::parse_str("01020304-1112-2122-3132-41424344")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupLength {

-                expected: error::ExpectedLength::Exact(12),

-                found: 8,

-                group: 4,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 31,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 33,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 33,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidCharacter {

-                expected: EXPECTED_CHARS,

-                found: '%',

-                index: 15,

-                urn: error::UrnPrefix::Optional,

-            })

-        );

-

-        assert_eq!(

-            Uuid::parse_str("231231212212423424324323477343246663")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 36,

-            })

-        );

-

-        // Valid

-        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());

-

-        // 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

-        );

-

-        // Round-trip

-        let uuid_orig = test_util::new();

-        let orig_str = uuid_orig.to_string();

-        let uuid_out = Uuid::parse_str(&orig_str).unwrap();

-        assert_eq!(uuid_orig, uuid_out);

-

-        // Test error reporting

-        assert_eq!(

-            Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidLength {

-                expected: EXPECTED_UUID_LENGTHS,

-                found: 31,

-            })

-        );

-        assert_eq!(

-            Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidCharacter {

-                expected: EXPECTED_CHARS,

-                found: 'X',

-                index: 6,

-                urn: error::UrnPrefix::Optional,

-            })

-        );

-        assert_eq!(

-            Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupLength {

-                expected: error::ExpectedLength::Exact(8),

-                found: 6,

-                group: 0,

-            })

-        );

-        assert_eq!(

-            Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4")

-                .map_err(crate::Error::expect_parser),

-            Err(Error::InvalidGroupLength {

-                expected: error::ExpectedLength::Exact(4),

-                found: 5,

-                group: 3,

-            })

-        );

-    }

-}

diff --git a/src/prelude.rs b/src/prelude.rs
deleted file mode 100644
index 63fbb4b..0000000
--- a/src/prelude.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.

-

-//! The [`uuid`] prelude.

-//!

-//! This module contains the most important items of the [`uuid`] crate.

-//!

-//! To use the prelude, include the following in your crate root:

-//!

-//! ```rust

-//! extern crate uuid;

-//! ```

-//!

-//! # Prelude Contents

-//!

-//! Currently the prelude reexports the following:

-//!

-//! [`uuid`]`::{`[`Error`], [`Uuid`], [`Variant`], [`Version`],

-//! builder::[`Builder`]`}`: The fundamental types used in [`uuid`] crate.

-//!

-//! [`uuid`]: ../index.html

-//! [`Error`]: ../enum.Error.html

-//! [`Uuid`]: ../struct.Uuid.html

-//! [`Variant`]: ../enum.Variant.html

-//! [`Version`]: ../enum.Version.html

-//! [`Builder`]: ../builder/struct.Builder.html

-//!

-#![cfg_attr(feature = "v1",

-doc = "

-[`uuid::v1`]`::{`[`ClockSequence`],[`Context`]`}`: The types useful for

-handling uuid version 1. Requires feature `v1`.

-

-[`uuid::v1`]: ../v1/index.html

-[`Context`]: ../v1/struct.Context.html

-[`ClockSequence`]: ../v1/trait.ClockSequence.html")]

-

-pub use super::{Builder, Bytes, Error, Uuid, Variant, Version};

-#[cfg(feature = "v1")]

-pub use crate::v1::{ClockSequence, Context};

diff --git a/src/rng.rs b/src/rng.rs
new file mode 100644
index 0000000..dcfbb8d
--- /dev/null
+++ b/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/src/serde_support.rs b/src/serde_support.rs
deleted file mode 100644
index 4ec2ffb..0000000
--- a/src/serde_support.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-// 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::prelude::*;

-use core::fmt;

-use serde::{de, 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.to_hyphenated().encode_lower(&mut [0; 36]))

-        } else {

-            serializer.serialize_bytes(self.as_bytes())

-        }

-    }

-}

-

-impl<'de> Deserialize<'de> for Uuid {

-    fn deserialize<D: Deserializer<'de>>(

-        deserializer: D,

-    ) -> Result<Self, D::Error> {

-        fn de_error<E: de::Error>(e: crate::Error) -> E {

-            E::custom(format_args!("UUID parsing failed: {}", e))

-        }

-

-        if deserializer.is_human_readable() {

-            struct UuidStringVisitor;

-

-            impl<'vi> de::Visitor<'vi> for UuidStringVisitor {

-                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)

-                }

-            }

-

-            deserializer.deserialize_str(UuidStringVisitor)

-        } 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)

-        }

-    }

-}

-

-#[cfg(test)]

-mod serde_tests {

-    use serde_test::{Compact, Configure, Readable, Token};

-

-    use crate::prelude::*;

-

-    #[test]

-    fn test_serialize_readable() {

-        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_serialize_compact() {

-        let uuid_bytes = b"F9168C5E-CEB2-4F";

-        let u = Uuid::from_slice(uuid_bytes).unwrap();

-        serde_test::assert_tokens(&u.compact(), &[Token::Bytes(uuid_bytes)]);

-    }

-

-    #[test]

-    fn test_de_failure() {

-        serde_test::assert_de_tokens_error::<Readable<Uuid>>(

-            &[Token::Str("hello_world")],

-            "UUID parsing failed: invalid length: expected one of [36, 32], found 11",

-        );

-

-        serde_test::assert_de_tokens_error::<Compact<Uuid>>(

-            &[Token::Bytes(b"hello_world")],

-            "UUID parsing failed: invalid bytes length: expected 16, found 11",

-        );

-    }

-}

diff --git a/src/sha1.rs b/src/sha1.rs
new file mode 100644
index 0000000..14ca302
--- /dev/null
+++ b/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/src/test_util.rs b/src/test_util.rs
deleted file mode 100644
index ebb45ab..0000000
--- a/src/test_util.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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::prelude::*;

-

-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,

-    ])

-}

diff --git a/src/timestamp.rs b/src/timestamp.rs
new file mode 100644
index 0000000..2f95ac4
--- /dev/null
+++ b/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/src/v1.rs b/src/v1.rs
index de692b7..e19c8a3 100644
--- a/src/v1.rs
+++ b/src/v1.rs
@@ -1,326 +1,175 @@
-//! The implementation for Version 1 UUIDs.

-//!

-//! Note that you need feature `v1` in order to use these features.

-

-use crate::prelude::*;

-use core::sync::atomic;

-

-/// The number of 100 ns ticks between the UUID epoch

-/// `1582-10-15 00:00:00` and the Unix epoch `1970-01-01 00:00:00`.

-const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;

-

-/// A thread-safe, stateful context for the v1 generator to help ensure

-/// process-wide uniqueness.

-#[derive(Debug)]

-pub struct Context {

-    count: atomic::AtomicUsize,

-}

-

-/// Stores the number of nanoseconds from an epoch and a counter for ensuring

-/// V1 ids generated on the same host are unique.

-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

-pub struct Timestamp {

-    ticks: u64,

-    counter: u16,

-}

-

-impl Timestamp {

-    /// Construct a `Timestamp` from its raw component values: an RFC4122

-    /// timestamp and counter.

-    ///

-    /// RFC4122, which defines the V1 UUID, specifies a 60-byte timestamp format

-    /// as the number of 100-nanosecond intervals elapsed since 00:00:00.00,

-    /// 15 Oct 1582, "the date of the Gregorian reform of the Christian

-    /// calendar."

-    ///

-    /// The counter value is used to differentiate between ids generated by

-    /// the same host computer in rapid succession (i.e. with the same observed

-    /// time). See the [`ClockSequence`] trait for a generic interface to any

-    /// counter generators that might be used.

-    ///

-    /// Internally, the timestamp is stored as a `u64`. For this reason, dates

-    /// prior to October 1582 are not supported.

-    ///

-    /// [`ClockSequence`]: trait.ClockSequence.html

-    pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {

-        Timestamp { ticks, counter }

-    }

-

-    /// Construct a `Timestamp` from a unix timestamp and sequence-generating

-    /// `context`.

-    ///

-    /// A unix timestamp represents the elapsed time since Jan 1 1970. Libc's

-    /// `clock_gettime` and other popular implementations traditionally

-    /// represent this duration as a `timespec`: a struct with `u64` and

-    /// `u32` fields representing the seconds, and "subsecond" or fractional

-    /// nanoseconds elapsed since the timestamp's second began,

-    /// respectively.

-    ///

-    /// This constructs a `Timestamp` from the seconds and fractional

-    /// nanoseconds of a unix timestamp, converting the duration since 1970

-    /// into the number of 100-nanosecond intervals since 00:00:00.00, 15

-    /// Oct 1582 specified by RFC4122 and used internally by `Timestamp`.

-    ///

-    /// The function is not guaranteed to produce monotonically increasing

-    /// values however. There is a slight possibility that two successive

-    /// equal time values could be supplied and the sequence counter wraps back

-    /// over to 0.

-    ///

-    /// If uniqueness and monotonicity is required, the user is responsible for

-    /// ensuring that the time value always increases between calls (including

-    /// between restarts of the process and device).

-    pub fn from_unix(

-        context: impl ClockSequence,

-        seconds: u64,

-        subsec_nanos: u32,

-    ) -> Self {

-        let counter = context.generate_sequence(seconds, subsec_nanos);

-        let ticks = UUID_TICKS_BETWEEN_EPOCHS

-            + seconds * 10_000_000

-            + u64::from(subsec_nanos) / 100;

-

-        Timestamp { ticks, counter }

-    }

-

-    /// Returns the raw RFC4122 timestamp and counter values stored by the

-    /// `Timestamp`.

-    ///

-    /// The timestamp (the first, `u64` element in the tuple) represents the

-    /// number of 100-nanosecond intervals since 00:00:00.00, 15 Oct 1582.

-    /// The counter is used to differentiate between ids generated on the

-    /// same host computer with the same observed time.

-    pub const fn to_rfc4122(&self) -> (u64, u16) {

-        (self.ticks, self.counter)

-    }

-

-    /// Returns the timestamp converted to the seconds and fractional

-    /// nanoseconds since Jan 1 1970.

-    ///

-    /// Internally, the time is stored in 100-nanosecond intervals,

-    /// thus the maximum precision represented by the fractional nanoseconds

-    /// value is less than its unit size (100 ns vs. 1 ns).

-    pub const fn to_unix(&self) -> (u64, u32) {

-        (

-            (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,

-            ((self.ticks - UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32

-                * 100,

-        )

-    }

-

-    /// Returns the timestamp converted into nanoseconds elapsed since Jan 1

-    /// 1970. Internally, the time is stored in 100-nanosecond intervals,

-    /// thus the maximum precision represented is less than the units it is

-    /// measured in (100 ns vs. 1 ns). The value returned represents the

-    /// same duration as [`Timestamp::to_unix`]; this provides it in nanosecond

-    /// units for convenience.

-    pub const fn to_unix_nanos(&self) -> u64 {

-        (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) * 100

-    }

-}

-

-/// A trait that abstracts over generation of UUID v1 "Clock Sequence" values.

-pub trait ClockSequence {

-    /// Return a 16-bit number that will be used as the "clock sequence" in

-    /// the UUID. The number must be different if the time has changed since

-    /// the last time a clock sequence was requested.

-    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16;

-}

-

-impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {

-    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16 {

-        (**self).generate_sequence(seconds, subsec_nanos)

-    }

-}

-

-impl Uuid {

-    /// Create a new UUID (version 1) using a time value + sequence +

-    /// *NodeId*.

-    ///

-    /// When generating [`Timestamp`]s using a [`ClockSequence`], this function

-    /// is only guaranteed to produce unique values if the following conditions

-    /// hold:

-    ///

-    /// 1. The *NodeId* is unique for this process,

-    /// 2. The *Context* is shared across all threads which are generating v1

-    ///    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 `v1` feature of this crate

-    /// to be enabled.

-    ///

-    /// # Examples

-    ///

-    /// A UUID can be created from a unix [`Timestamp`] with a

-    /// [`ClockSequence`]:

-    ///

-    /// ```rust

-    /// use uuid::v1::{Timestamp, Context};

-    /// use uuid::Uuid;

-    ///

-    /// let context = Context::new(42);

-    /// let ts = Timestamp::from_unix(&context, 1497624119, 1234);

-    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");

-    ///

-    /// assert_eq!(

-    ///     uuid.to_hyphenated().to_string(),

-    ///     "f3b4958c-52a1-11e7-802a-010203040506"

-    /// );

-    /// ```

-    ///

-    /// The timestamp can also be created manually as per RFC4122:

-    ///

-    /// ```

-    /// use uuid::v1::{Timestamp, Context};

-    /// use uuid::Uuid;

-    ///

-    /// let context = Context::new(42);

-    /// let ts = Timestamp::from_rfc4122(1497624119, 0);

-    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");

-    ///

-    /// assert_eq!(

-    ///     uuid.to_hyphenated().to_string(),

-    ///     "5943ee37-0000-1000-8000-010203040506"

-    /// );

-    /// ```

-    ///

-    /// [`Timestamp`]: v1/struct.Timestamp.html

-    /// [`ClockSequence`]: v1/struct.ClockSequence.html

-    /// [`Context`]: v1/struct.Context.html

-    pub fn new_v1(ts: Timestamp, node_id: &[u8]) -> Result<Self, crate::Error> {

-        const NODE_ID_LEN: usize = 6;

-

-        let len = node_id.len();

-        if len != NODE_ID_LEN {

-            Err(crate::builder::Error::new(NODE_ID_LEN, len))?;

-        }

-

-        let time_low = (ts.ticks & 0xFFFF_FFFF) as u32;

-        let time_mid = ((ts.ticks >> 32) & 0xFFFF) as u16;

-        let time_high_and_version =

-            (((ts.ticks >> 48) & 0x0FFF) as u16) | (1 << 12);

-

-        let mut d4 = [0; 8];

-

-        {

-            d4[0] = (((ts.counter & 0x3F00) >> 8) as u8) | 0x80;

-            d4[1] = (ts.counter & 0xFF) as u8;

-        }

-

-        d4[2..].copy_from_slice(node_id);

-

-        Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)

-    }

-

-    /// Returns an optional [`Timestamp`] storing 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.

-    ///

-    /// [`Timestamp`]: v1/struct.Timestamp.html

-    pub fn to_timestamp(&self) -> Option<Timestamp> {

-        if self

-            .get_version()

-            .map(|v| v != Version::Mac)

-            .unwrap_or(true)

-        {

-            return None;

-        }

-

-        let ticks: u64 = u64::from(self.as_bytes()[6] & 0x0F) << 56

-            | u64::from(self.as_bytes()[7]) << 48

-            | u64::from(self.as_bytes()[4]) << 40

-            | u64::from(self.as_bytes()[5]) << 32

-            | u64::from(self.as_bytes()[0]) << 24

-            | u64::from(self.as_bytes()[1]) << 16

-            | u64::from(self.as_bytes()[2]) << 8

-            | u64::from(self.as_bytes()[3]);

-

-        let counter: u16 = u16::from(self.as_bytes()[8] & 0x3F) << 8

-            | u16::from(self.as_bytes()[9]);

-

-        Some(Timestamp::from_rfc4122(ticks, counter))

-    }

-}

-

-impl Context {

-    /// Creates a thread-safe, internally mutable context to help ensure

-    /// uniqueness.

-    ///

-    /// This is a context which can be shared across threads. It maintains an

-    /// internal counter that is incremented at every request, the value ends

-    /// up in the clock_seq portion of the UUID (the fourth group). This

-    /// will improve the probability that the UUID is unique across the

-    /// process.

-    pub const fn new(count: u16) -> Self {

-        Self {

-            count: atomic::AtomicUsize::new(count as usize),

-        }

-    }

-}

-

-impl ClockSequence for Context {

-    fn generate_sequence(&self, _: u64, _: u32) -> u16 {

-        (self.count.fetch_add(1, atomic::Ordering::SeqCst) & 0xffff) as u16

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use super::*;

-

-    use crate::std::string::ToString;

-

-    #[test]

-    fn test_new_v1() {

-        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,

-            )

-            .unwrap();

-

-            assert_eq!(uuid.get_version(), Some(Version::Mac));

-            assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));

-            assert_eq!(

-                uuid.to_hyphenated().to_string(),

-                "20616934-4ba2-11e7-8000-010203040506"

-            );

-

-            let ts = uuid.to_timestamp().unwrap().to_rfc4122();

-

-            assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);

-            assert_eq!(ts.1, 0);

-        };

-

-        {

-            let uuid2 = Uuid::new_v1(

-                Timestamp::from_unix(&context, time, time_fraction),

-                &node,

-            )

-            .unwrap();

-

-            assert_eq!(

-                uuid2.to_hyphenated().to_string(),

-                "20616934-4ba2-11e7-8001-010203040506"

-            );

-            assert_eq!(uuid2.to_timestamp().unwrap().to_rfc4122().1, 1)

-        };

-    }

-}

+//! 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/src/v3.rs b/src/v3.rs
index 5be542b..cc7cb9a 100644
--- a/src/v3.rs
+++ b/src/v3.rs
@@ -1,146 +1,151 @@
-use crate::prelude::*;

-use md5;

-

-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.

-    ///

-    /// [`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 {

-        let mut context = md5::Context::new();

-

-        context.consume(namespace.as_bytes());

-        context.consume(name);

-

-        let computed = context.compute();

-        let bytes = computed.into();

-

-        let mut builder = crate::Builder::from_bytes(bytes);

-

-        builder

-            .set_variant(Variant::RFC4122)

-            .set_version(Version::Md5);

-

-        builder.build()

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use super::*;

-

-    use crate::std::string::ToString;

-

-    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]

-    fn test_new() {

-        for &(ref ns, ref name, _) in FIXTURE {

-            let uuid = Uuid::new_v3(*ns, name.as_bytes());

-            assert_eq!(uuid.get_version().unwrap(), Version::Md5);

-            assert_eq!(uuid.get_variant().unwrap(), Variant::RFC4122);

-        }

-    }

-

-    #[test]

-    fn test_to_hyphenated_string() {

-        for &(ref ns, ref name, ref expected) in FIXTURE {

-            let uuid = Uuid::new_v3(*ns, name.as_bytes());

-            assert_eq!(uuid.to_hyphenated().to_string(), *expected);

-        }

-    }

-}

+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/src/v4.rs b/src/v4.rs
index 0928dc7..e78fb1e 100644
--- a/src/v4.rs
+++ b/src/v4.rs
@@ -1,60 +1,63 @@
-use crate::prelude::*;

-

-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_bytes`][from_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;

-    ///

-    /// let uuid = Uuid::new_v4();

-    /// ```

-    ///

-    /// [`getrandom`]: https://crates.io/crates/getrandom

-    /// [from_bytes]: struct.Builder.html#method.from_bytes

-    pub fn new_v4() -> Uuid {

-        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 retreive random bytes for uuid: {}", err)

-        });

-

-        crate::Builder::from_bytes(bytes)

-            .set_variant(Variant::RFC4122)

-            .set_version(Version::Random)

-            .build()

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use crate::prelude::*;

-

-    #[test]

-    fn test_new() {

-        let uuid = Uuid::new_v4();

-

-        assert_eq!(uuid.get_version(), Some(Version::Random));

-        assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));

-    }

-

-    #[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)

-    }

-}

+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/src/v5.rs b/src/v5.rs
index e42d70d..c3dd447 100644
--- a/src/v5.rs
+++ b/src/v5.rs
@@ -1,158 +1,162 @@
-use crate::prelude::*;

-use sha1;

-

-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.

-    ///

-    /// [`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 {

-        let mut hash = sha1::Sha1::new();

-

-        hash.update(namespace.as_bytes());

-        hash.update(name);

-

-        let buffer = hash.digest().bytes();

-

-        let mut bytes = crate::Bytes::default();

-        bytes.copy_from_slice(&buffer[..16]);

-

-        let mut builder = crate::Builder::from_bytes(bytes);

-        builder

-            .set_variant(Variant::RFC4122)

-            .set_version(Version::Sha1);

-

-        builder.build()

-    }

-}

-

-#[cfg(test)]

-mod tests {

-    use super::*;

-

-    use crate::std::string::ToString;

-

-    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]

-    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]

-    fn test_hyphenated() {

-        for &(ref ns, ref name, ref expected) in FIXTURE {

-            let uuid = Uuid::new_v5(*ns, name.as_bytes());

-

-            assert_eq!(uuid.to_hyphenated().to_string(), *expected)

-        }

-    }

-

-    #[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_variant(), Some(Variant::RFC4122));

-            assert_eq!(uuid.get_version(), Some(Version::Sha1));

-            assert_eq!(Ok(uuid), u.parse());

-        }

-    }

-}

+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/src/v6.rs b/src/v6.rs
new file mode 100644
index 0000000..07644fd
--- /dev/null
+++ b/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/src/v7.rs b/src/v7.rs
new file mode 100644
index 0000000..4497ea3
--- /dev/null
+++ b/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/src/v8.rs b/src/v8.rs
new file mode 100644
index 0000000..a54a979
--- /dev/null
+++ b/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/src/winapi_support.rs b/src/winapi_support.rs
deleted file mode 100644
index 29bed06..0000000
--- a/src/winapi_support.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use crate::prelude::*;

-use winapi::shared::guiddef;

-

-#[cfg(feature = "guid")]

-impl Uuid {

-    /// Attempts to create a [`Uuid`] from a little endian winapi `GUID`

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    pub fn from_guid(guid: guiddef::GUID) -> Result<Uuid, crate::Error> {

-        Uuid::from_fields_le(

-            guid.Data1 as u32,

-            guid.Data2 as u16,

-            guid.Data3 as u16,

-            &(guid.Data4 as [u8; 8]),

-        )

-    }

-

-    /// Converts a [`Uuid`] into a little endian winapi `GUID`

-    ///

-    /// [`Uuid`]: ../struct.Uuid.html

-    pub fn to_guid(&self) -> guiddef::GUID {

-        let (data1, data2, data3, data4) = self.to_fields_le();

-

-        guiddef::GUID {

-            Data1: data1,

-            Data2: data2,

-            Data3: data3,

-            Data4: *data4,

-        }

-    }

-}

-

-#[cfg(feature = "guid")]

-#[cfg(test)]

-mod tests {

-    use super::*;

-

-    use crate::std::string::ToString;

-    use winapi::shared::guiddef;

-

-    #[test]

-    fn test_from_guid() {

-        let guid = guiddef::GUID {

-            Data1: 0x4a35229d,

-            Data2: 0x5527,

-            Data3: 0x4f30,

-            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],

-        };

-

-        let uuid = Uuid::from_guid(guid).unwrap();

-        assert_eq!(

-            "9d22354a-2755-304f-8647-9dc54e1ee1e8",

-            uuid.to_hyphenated().to_string()

-        );

-    }

-

-    #[test]

-    fn test_guid_roundtrip() {

-        let guid_in = guiddef::GUID {

-            Data1: 0x4a35229d,

-            Data2: 0x5527,

-            Data3: 0x4f30,

-            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],

-        };

-

-        let uuid = Uuid::from_guid(guid_in).unwrap();

-        let guid_out = uuid.to_guid();

-

-        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

-            )

-        );

-    }

-}

diff --git a/tests/macros.rs b/tests/macros.rs
new file mode 100644
index 0000000..c7cf2a4
--- /dev/null
+++ b/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/tests/ui/compile_fail/invalid_parse.rs b/tests/ui/compile_fail/invalid_parse.rs
new file mode 100644
index 0000000..f67456b
--- /dev/null
+++ b/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/tests/ui/compile_fail/invalid_parse.stderr b/tests/ui/compile_fail/invalid_parse.stderr
new file mode 100644
index 0000000..b630494
--- /dev/null
+++ b/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/tests/ui/compile_pass/renamed.rs b/tests/ui/compile_pass/renamed.rs
new file mode 100644
index 0000000..321172e
--- /dev/null
+++ b/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/tests/ui/compile_pass/valid.rs b/tests/ui/compile_pass/valid.rs
new file mode 100644
index 0000000..1f536dc
--- /dev/null
+++ b/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() {}