Merge "Update uuid to 1.12.0" into main
diff --git a/crates/uuid/.android-checksum.json b/crates/uuid/.android-checksum.json
index 6be07f6..2110fe1 100644
--- a/crates/uuid/.android-checksum.json
+++ b/crates/uuid/.android-checksum.json
@@ -1 +1 @@
-{"package":null,"files":{".cargo-checksum.json":"c80812a1ec6a2a6a3f9957359095bf9c1e8cbcdae4a531775a783dd6266ed46d","Android.bp":"2bbcb0aaf870704ac5aecc4279bbed1d684ffa6747cf84a77daca1029e1a2338","Cargo.toml":"d735a31bccbca378268ebb919e4a742f885ea62643b5349a31d61ca83cf74a81","LICENSE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-APACHE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-MIT":"08bc387e24ed88cdda3af9eb97d401d69c31dc98049e63a9c3dfd763dc45a29d","METADATA":"8e9891c6939ba8ab0c456a22f5eefd4accc485ceb747b34d3631bd234ed84a7a","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"8f1b5b3db24ce08b2b90aa46eca37567be46d499a86a6ed5a4e108bae714b58c","TEST_MAPPING":"e93962d7a70966b064fcb2f8429feb4f97dca1cfaeb526f4ec56a44305c6de69","cargo_embargo.json":"3bf1a98721509650cb9f52cad8d9432fc466b69a9556fc24726caee458caaf0b","rules.mk":"c6a05070a68ecf74533aa73ac4cef3a8ada1f5ef3de138d4c98a79c48f863482","src/builder.rs":"bbfcd69aad7e4eaabe0e987febd3f6c5f30ff58d76701f8c890e42f641682546","src/error.rs":"a074f13c8ebaef5c563e961fae295134bf75386bfc44efbea5fefbbef7f44f24","src/external.rs":"d5b9021ea1db870ed29525e3290fae1d6ef89ab615d54548830c6632a1353d4c","src/external/arbitrary_support.rs":"f508e7015c8c14c8304a133eb275b60fb946a194c7e431642fe2fa0959a9990c","src/external/borsh_support.rs":"9b7f8438d29dad79dc79efd5db412e8a37e29d567ae21c76f4f3f37febabcd07","src/external/serde_support.rs":"15e735ff56d72b5a8bb846f429cf463361ba1e50d83118df27222ea01a8b0cb3","src/external/slog_support.rs":"9f7009bf65d8ca6961ad9b170c33a5eb787820155286a070324ff0d5fd3c09a2","src/fmt.rs":"80c5fa5eec2e2afcc4d8bfb045b63b3c796ac72fb0b7646d297cf35aa9eabd38","src/lib.rs":"2ebd885a33317ff2ca93be509b96816000799cc6bd5af9a3cf07f60270a341bc","src/macros.rs":"59262f55948d70b7ca0dcee15c990b6a3ad4fca47705d36ba1e90f88e53e8839","src/md5.rs":"5612c79b17b868220029baf52a87bff31530e607ac2522afdf8677eecb28e780","src/parser.rs":"a0d125589f80f3e30bca52897b58c2fce10473eecca1f2b5253ccc024f19162b","src/rng.rs":"158c5d6336c10007f7fa8ede586e7b2fccc9e28186109c8ca060f6e0086c5bb2","src/sha1.rs":"173b844e6a3975270ea36d235f5b7e406e9612ba95833d811b3602f5107589f0","src/timestamp.rs":"0e7db00a98d997bf8b3caa2ad3d97a892cecfcf56d5f19f34d3a392997292431","src/v1.rs":"e52a27d89e344036ffe4408a7b5b5fb326d6fb18ae06704a090c6399b7eb3611","src/v3.rs":"7af107a0c0339cae9b50b8b084c5339caf850fe0cd60bc1b129577ee2f140e67","src/v4.rs":"20ae5609a8f891dca1bd8fd99421121dfe452d9ce7f51d635a6d14b4a09889b5","src/v5.rs":"2e435575aa2f5f8971709ffac815407e5f245fe24f64a4666881549a516e30d8","src/v6.rs":"b0f8cf1bec6df06aa7c3d06a465c1a795f02a0bb41328b9509a4662c7b4cf89d","src/v7.rs":"13eb4cc951ac6359aa0d751172cc3f2155dc76a9c89e65d6d5a3f3817d0b2b7c","src/v8.rs":"25b49a2e5e947cffad78ac4b6da187b75469193814eb340eb8a1a9c644021106"}}
\ No newline at end of file
+{"package":null,"files":{".cargo-checksum.json":"dea2b2b850b17d4c3c2bcac38bde6c8c53a18291e647d02a91a331f31ec288e8","Android.bp":"737eccb7bd5d9b2d254e30efef3965fd6c8a5697565633e22653170ad316b146","Cargo.toml":"705581536ed46491230879ed499840673b339b20383b8755fe26874e2ffb6625","LICENSE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-APACHE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-MIT":"08bc387e24ed88cdda3af9eb97d401d69c31dc98049e63a9c3dfd763dc45a29d","METADATA":"35cf8ca93bdc132c2acc772c50768a274b9ec7d24094a6c4b0a8646bb2e59830","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"70396bc90fbfe2aad4750ba42c49de7e300741052693364ec602845d3968531f","TEST_MAPPING":"e93962d7a70966b064fcb2f8429feb4f97dca1cfaeb526f4ec56a44305c6de69","cargo_embargo.json":"3bf1a98721509650cb9f52cad8d9432fc466b69a9556fc24726caee458caaf0b","rules.mk":"c6a05070a68ecf74533aa73ac4cef3a8ada1f5ef3de138d4c98a79c48f863482","src/builder.rs":"be1a3145dec9b84852e0308443e09d5961a6f7278a574336a42a91babf83018d","src/error.rs":"7d2913559d5179ff0ed4430abe0fea081cd6033c1c89f366c6fe91984f1151cd","src/external.rs":"d5b9021ea1db870ed29525e3290fae1d6ef89ab615d54548830c6632a1353d4c","src/external/arbitrary_support.rs":"e012688d57194c3eb03393fc4c768bba0afd57667c3525f7b36027bf7ab546cd","src/external/borsh_support.rs":"9b7f8438d29dad79dc79efd5db412e8a37e29d567ae21c76f4f3f37febabcd07","src/external/serde_support.rs":"86e708f535cdc16a8ece6f6bdf579c3beee453a7346077263b8636ee1d1d3e50","src/external/slog_support.rs":"beaa766f1e536a65bbe983192feefc3db8510058d81bf098a8265bc33100180b","src/fmt.rs":"80c5fa5eec2e2afcc4d8bfb045b63b3c796ac72fb0b7646d297cf35aa9eabd38","src/lib.rs":"ab6849d33bc1f1f1eceb8b3a611e194f7c25b8129c4ff68f92b6940d8e1fb04b","src/macros.rs":"59262f55948d70b7ca0dcee15c990b6a3ad4fca47705d36ba1e90f88e53e8839","src/md5.rs":"5612c79b17b868220029baf52a87bff31530e607ac2522afdf8677eecb28e780","src/non_nil.rs":"b09342ba0f2a92123a0b3578132e54f5968d7ab40f877eadaf6274847de27074","src/parser.rs":"a0d125589f80f3e30bca52897b58c2fce10473eecca1f2b5253ccc024f19162b","src/rng.rs":"158c5d6336c10007f7fa8ede586e7b2fccc9e28186109c8ca060f6e0086c5bb2","src/sha1.rs":"173b844e6a3975270ea36d235f5b7e406e9612ba95833d811b3602f5107589f0","src/timestamp.rs":"170a2a94271cd6ec9a672c7baa1c7a0adf09e1de06acd80c3bc06cf35600b20b","src/v1.rs":"e52a27d89e344036ffe4408a7b5b5fb326d6fb18ae06704a090c6399b7eb3611","src/v3.rs":"7af107a0c0339cae9b50b8b084c5339caf850fe0cd60bc1b129577ee2f140e67","src/v4.rs":"20ae5609a8f891dca1bd8fd99421121dfe452d9ce7f51d635a6d14b4a09889b5","src/v5.rs":"2e435575aa2f5f8971709ffac815407e5f245fe24f64a4666881549a516e30d8","src/v6.rs":"b0f8cf1bec6df06aa7c3d06a465c1a795f02a0bb41328b9509a4662c7b4cf89d","src/v7.rs":"6aa389648dd187a86766e420d7b055c79ed1437353590c2440fe04f713a7b650","src/v8.rs":"25b49a2e5e947cffad78ac4b6da187b75469193814eb340eb8a1a9c644021106"}}
\ No newline at end of file
diff --git a/crates/uuid/.cargo-checksum.json b/crates/uuid/.cargo-checksum.json
index 0cad08a..deb142e 100644
--- a/crates/uuid/.cargo-checksum.json
+++ b/crates/uuid/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3e129d39ba3ad1910e2492c75c2596faa848683660bcb0d443bd7b7a1a5ef726","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"436bc5a105d8e57dcd8778730f3754f7bf39c14d2f530e4cde4bd2d17a83ec3d","README.md":"383cbe6804afa72e448883bd0419087e2afd1e0ea7c5d66fdedfb228d1dc8e8a","src/builder.rs":"2f46ba8b4f9b333b0edc926a05c2a9a2d5bf3629cdad05a058532005e71ecc29","src/error.rs":"6a402cde971f7d186be3a184953bc6c89e8b8039fa95cd351e1e158fbe7378cb","src/external.rs":"a0640bdb98de1c24fcc9851a438a5abe6f7e3acb195885c817a64fac25521b9d","src/external/arbitrary_support.rs":"7e7fbcc4b8af5878b71858a1f5fa31e85d84fc2fd159614f8d450ba1fe06ac28","src/external/borsh_support.rs":"b49d82a59653445ba26db46a1515294b1ab480c0671dbe5499dfd1fb02588b3b","src/external/serde_support.rs":"b818f54e784143677146666a6737597bf95523d0de73fedc90b22d9c949b0997","src/external/slog_support.rs":"4fe1cc136b1eb5e27d8b308801bcd72872c129fd20ced1f2415af6760a83751b","src/fmt.rs":"3bf88d68d838bef81380a1e669a86eee46f24a8113effbd7b4e92da714ec97c7","src/lib.rs":"e005d6b2ffaa8e0e253a1e565878653bfb642dd4aa5d01cab5c2b368ca591880","src/macros.rs":"dff4a00bcbc37912d38d58edc3edfb8552ba8bb936403b8b33fe7dc3c2041908","src/md5.rs":"316d65b760ffa58beb6aa678be24359eb21a744e9e143bc99c11fe1907659245","src/parser.rs":"838e4a5af613a1d9b9dd6ca4b3c13a42e65fdea35fc02c93c34a416387dbdb7c","src/rng.rs":"d9cdd08ca225f28c103276c985db0540bb8db877a4bcb5348cb4a2648b29883e","src/sha1.rs":"e1a9657e11f1ed1ede33c0655f9c2641059b7c24f17be4ac425c930cc216e019","src/timestamp.rs":"b53c7ec88c4be2d73100d1300cfb684b3d0d93173f93e9fdcde54b75d463f661","src/v1.rs":"9c8254742e58a1d75b8374260108516fc914e2641f83e3a8ada75f05a62a62d1","src/v3.rs":"287860f5376e35d5292959d65948bdb0bbdb4605e3d2e463742c5400075bbe76","src/v4.rs":"c2f2844791cdb2c9e0c90bf7d9d155b96572f1f77aa9586104ddb77d44a5aeea","src/v5.rs":"70799f332c043b3d3ddf4aee791aa448296a5e05122be434945076f9cb29517c","src/v6.rs":"7bd0a52aa316e145ad55b99b0ad46ad3234b0936ab61a4935300f053f2030a56","src/v7.rs":"3ec7d26bbb457347f4c282f3feb90f123d18e62f81753b81196c995034c28256","src/v8.rs":"15a4c3b81afcca4ec406192f2099fac0ad43d734e12672b02a693ddcc38b6684"},"package":"b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4"}
\ No newline at end of file
+{"files":{"Cargo.toml":"286a84f2f8c07e743b2d4af0055f1723763a4175c1dc8c4d60e717f3662e7738","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"436bc5a105d8e57dcd8778730f3754f7bf39c14d2f530e4cde4bd2d17a83ec3d","README.md":"151c7172b60dab055ec853b7534a2b1f5becafd70c3478d558fc578dd98ed317","src/builder.rs":"855c402ff7d6ac920ddc89fd75d365818187529970fdea17e3af32f255ea8b4e","src/error.rs":"2d1c71fe562fe695cd690e6e2371f998424472bfb8c5e31bc36d953d5523040b","src/external.rs":"a0640bdb98de1c24fcc9851a438a5abe6f7e3acb195885c817a64fac25521b9d","src/external/arbitrary_support.rs":"a7e0f0686c7c79e3af797f6d3f1976bee13fa9c3d8cb40f58bd10ff6ebdadae3","src/external/borsh_support.rs":"b49d82a59653445ba26db46a1515294b1ab480c0671dbe5499dfd1fb02588b3b","src/external/serde_support.rs":"4275abf9b543e5a1ebc20823208d0a983e5e34131da4d41648b4685f4a81df63","src/external/slog_support.rs":"d9bab6f91a80c773e77326ce40d84976beb2b2946ab708de21f25afe5b9ece13","src/fmt.rs":"3bf88d68d838bef81380a1e669a86eee46f24a8113effbd7b4e92da714ec97c7","src/lib.rs":"3166822eef37e2a67fc9eccf2639bda04d83350ff0a40181e1dfe8a932d10624","src/macros.rs":"dff4a00bcbc37912d38d58edc3edfb8552ba8bb936403b8b33fe7dc3c2041908","src/md5.rs":"316d65b760ffa58beb6aa678be24359eb21a744e9e143bc99c11fe1907659245","src/non_nil.rs":"a1cfe91f63cad13ef4d0a9e8e4c9aad55b8b29ec67c6c3897e8093d669d890fe","src/parser.rs":"838e4a5af613a1d9b9dd6ca4b3c13a42e65fdea35fc02c93c34a416387dbdb7c","src/rng.rs":"d9cdd08ca225f28c103276c985db0540bb8db877a4bcb5348cb4a2648b29883e","src/sha1.rs":"e1a9657e11f1ed1ede33c0655f9c2641059b7c24f17be4ac425c930cc216e019","src/timestamp.rs":"ad68e5b71953fb9df544fad858f9bde878a7d483f6a273523d8ee073511078d5","src/v1.rs":"9c8254742e58a1d75b8374260108516fc914e2641f83e3a8ada75f05a62a62d1","src/v3.rs":"287860f5376e35d5292959d65948bdb0bbdb4605e3d2e463742c5400075bbe76","src/v4.rs":"c2f2844791cdb2c9e0c90bf7d9d155b96572f1f77aa9586104ddb77d44a5aeea","src/v5.rs":"70799f332c043b3d3ddf4aee791aa448296a5e05122be434945076f9cb29517c","src/v6.rs":"7bd0a52aa316e145ad55b99b0ad46ad3234b0936ab61a4935300f053f2030a56","src/v7.rs":"bc737c502247c83189f3627c7f1612e0af2638c5919d47aeffee3647b9ec63a0","src/v8.rs":"15a4c3b81afcca4ec406192f2099fac0ad43d734e12672b02a693ddcc38b6684"},"package":"744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"}
\ No newline at end of file
diff --git a/crates/uuid/Android.bp b/crates/uuid/Android.bp
index 7642834..867c937 100644
--- a/crates/uuid/Android.bp
+++ b/crates/uuid/Android.bp
@@ -18,7 +18,7 @@
     host_supported: true,
     crate_name: "uuid",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.11.1",
+    cargo_pkg_version: "1.12.0",
     crate_root: "src/lib.rs",
     edition: "2018",
     features: [
@@ -47,7 +47,7 @@
     host_supported: true,
     crate_name: "uuid",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.11.1",
+    cargo_pkg_version: "1.12.0",
     crate_root: "src/lib.rs",
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -81,7 +81,7 @@
     name: "libuuid_nostd",
     crate_name: "uuid",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.11.1",
+    cargo_pkg_version: "1.12.0",
     crate_root: "src/lib.rs",
     edition: "2018",
     apex_available: [
diff --git a/crates/uuid/Cargo.toml b/crates/uuid/Cargo.toml
index 0065894..0882340 100644
--- a/crates/uuid/Cargo.toml
+++ b/crates/uuid/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2018"
 rust-version = "1.63.0"
 name = "uuid"
-version = "1.11.1"
+version = "1.12.0"
 authors = [
     "Ashley Mannix<[email protected]>",
     "Dylan DPC<[email protected]>",
@@ -141,7 +141,7 @@
 optional = true
 
 [dependencies.uuid-macro-internal]
-version = "1.11.1"
+version = "1.12.0"
 optional = true
 
 [dependencies.zerocopy]
diff --git a/crates/uuid/METADATA b/crates/uuid/METADATA
index 80f6f51..754e4f6 100644
--- a/crates/uuid/METADATA
+++ b/crates/uuid/METADATA
@@ -1,17 +1,17 @@
 name: "uuid"
 description: "A library to generate and parse UUIDs."
 third_party {
-  version: "1.11.1"
+  version: "1.12.0"
   license_type: NOTICE
   last_upgrade_date {
     year: 2025
     month: 1
-    day: 13
+    day: 14
   }
   homepage: "https://crates.io/crates/uuid"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/uuid/uuid-1.11.1.crate"
-    version: "1.11.1"
+    value: "https://static.crates.io/crates/uuid/uuid-1.12.0.crate"
+    version: "1.12.0"
   }
 }
diff --git a/crates/uuid/README.md b/crates/uuid/README.md
index bc85103..f76e2fd 100644
--- a/crates/uuid/README.md
+++ b/crates/uuid/README.md
@@ -28,7 +28,7 @@
 
 ```toml
 [dependencies.uuid]
-version = "1.11.1"
+version = "1.12.0"
 features = [
     "v4",                # Lets you generate random UUIDs
     "fast-rng",          # Use a faster (but still sufficiently random) RNG
@@ -65,11 +65,11 @@
 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.11.1/uuid).
+For more details on using `uuid`, [see the library documentation](https://docs.rs/uuid/1.12.0/uuid).
 
 ## References
 
-* [`uuid` library docs](https://docs.rs/uuid/1.11.1/uuid).
+* [`uuid` library docs](https://docs.rs/uuid/1.12.0/uuid).
 * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier).
 * [RFC 9562: Universally Unique IDentifiers (UUID)](https://www.ietf.org/rfc/rfc9562.html).
 
diff --git a/crates/uuid/src/builder.rs b/crates/uuid/src/builder.rs
index f1b6811..6a07a30 100644
--- a/crates/uuid/src/builder.rs
+++ b/crates/uuid/src/builder.rs
@@ -909,7 +909,7 @@
 #[doc(hidden)]
 impl Builder {
     #[deprecated(
-        since = "1.11.1",
+        since = "1.10.0",
         note = "use `Builder::from_gregorian_timestamp(ticks, counter, node_id)`"
     )]
     pub const fn from_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Self {
@@ -917,7 +917,7 @@
     }
 
     #[deprecated(
-        since = "1.11.1",
+        since = "1.10.0",
         note = "use `Builder::from_sorted_gregorian_timestamp(ticks, counter, node_id)`"
     )]
     pub const fn from_sorted_rfc4122_timestamp(
diff --git a/crates/uuid/src/error.rs b/crates/uuid/src/error.rs
index 30e0175..7a65c2d 100644
--- a/crates/uuid/src/error.rs
+++ b/crates/uuid/src/error.rs
@@ -30,6 +30,8 @@
     },
     /// The input was not a valid UTF8 string
     InvalidUTF8,
+    /// The UUID is nil.
+    Nil,
     /// Some other error occurred.
     Other,
 }
@@ -158,6 +160,7 @@
                 )
             }
             ErrorKind::InvalidUTF8 => write!(f, "non-UTF8 input"),
+            ErrorKind::Nil => write!(f, "the UUID is nil"),
             ErrorKind::Other => write!(f, "failed to parse a UUID"),
         }
     }
diff --git a/crates/uuid/src/external/arbitrary_support.rs b/crates/uuid/src/external/arbitrary_support.rs
index 40c11f5..c753f74 100644
--- a/crates/uuid/src/external/arbitrary_support.rs
+++ b/crates/uuid/src/external/arbitrary_support.rs
@@ -1,4 +1,8 @@
-use crate::{std::convert::TryInto, Builder, Uuid};
+use crate::{
+    non_nil::NonNilUuid,
+    std::convert::{TryFrom, TryInto},
+    Builder, Uuid,
+};
 
 use arbitrary::{Arbitrary, Unstructured};
 
@@ -16,6 +20,16 @@
         (16, Some(16))
     }
 }
+impl arbitrary::Arbitrary<'_> for NonNilUuid {
+    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
+        let uuid = Uuid::arbitrary(u)?;
+        Self::try_from(uuid).map_err(|_| arbitrary::Error::IncorrectFormat)
+    }
+
+    fn size_hint(_: usize) -> (usize, Option<usize>) {
+        (16, Some(16))
+    }
+}
 
 #[cfg(test)]
 mod tests {
@@ -42,4 +56,16 @@
 
         assert!(uuid.is_err());
     }
+
+    #[test]
+    fn test_arbitrary_non_nil() {
+        let mut bytes = Unstructured::new(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+        let non_nil_uuid = NonNilUuid::arbitrary(&mut bytes).unwrap();
+        let uuid: Uuid = non_nil_uuid.into();
+
+        assert_eq!(Some(Version::Random), uuid.get_version());
+        assert_eq!(Variant::RFC4122, uuid.get_variant());
+        assert!(!uuid.is_nil());
+    }
 }
diff --git a/crates/uuid/src/external/serde_support.rs b/crates/uuid/src/external/serde_support.rs
index f389271..954a349 100644
--- a/crates/uuid/src/external/serde_support.rs
+++ b/crates/uuid/src/external/serde_support.rs
@@ -10,8 +10,10 @@
 // except according to those terms.
 
 use crate::{
+    convert::TryFrom,
     error::*,
     fmt::{Braced, Hyphenated, Simple, Urn},
+    non_nil::NonNilUuid,
     std::fmt,
     Uuid,
 };
@@ -30,6 +32,15 @@
     }
 }
 
+impl Serialize for NonNilUuid {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        Uuid::from(*self).serialize(serializer)
+    }
+}
+
 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()))
@@ -127,6 +138,17 @@
     }
 }
 
+impl<'de> Deserialize<'de> for NonNilUuid {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let uuid = Uuid::deserialize(deserializer)?;
+
+        NonNilUuid::try_from(uuid).map_err(|_| de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID"))
+    }
+}
+
 enum ExpectedFormat {
     Simple,
     Braced,
@@ -732,4 +754,14 @@
             "UUID parsing failed: invalid length: expected 16 bytes, found 11",
         );
     }
+
+    #[test]
+    fn test_serde_non_nil_uuid() {
+        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
+        let uuid = Uuid::parse_str(uuid_str).unwrap();
+        let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap();
+
+        serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
+        serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]);
+    }
 }
diff --git a/crates/uuid/src/external/slog_support.rs b/crates/uuid/src/external/slog_support.rs
index cb06255..7e1c419 100644
--- a/crates/uuid/src/external/slog_support.rs
+++ b/crates/uuid/src/external/slog_support.rs
@@ -9,7 +9,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use crate::Uuid;
+use crate::{non_nil::NonNilUuid, Uuid};
 
 impl slog::Value for Uuid {
     fn serialize(
@@ -22,6 +22,17 @@
     }
 }
 
+impl slog::Value for NonNilUuid {
+    fn serialize(
+        &self,
+        record: &slog::Record<'_>,
+        key: slog::Key,
+        serializer: &mut dyn slog::Serializer,
+    ) -> Result<(), slog::Error> {
+        Uuid::from(*self).serialize(record, key, serializer)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::new;
diff --git a/crates/uuid/src/lib.rs b/crates/uuid/src/lib.rs
index 7d9ed42..7843d7d 100644
--- a/crates/uuid/src/lib.rs
+++ b/crates/uuid/src/lib.rs
@@ -38,7 +38,7 @@
 //!
 //! ```toml
 //! [dependencies.uuid]
-//! version = "1.11.1"
+//! version = "1.12.0"
 //! features = [
 //!     "v4",                # Lets you generate random UUIDs
 //!     "fast-rng",          # Use a faster (but still sufficiently random) RNG
@@ -138,7 +138,7 @@
 //!
 //! ```toml
 //! [dependencies.uuid]
-//! version = "1.11.1"
+//! version = "1.12.0"
 //! features = [
 //!     "v4",
 //!     "v7",
@@ -153,7 +153,7 @@
 //!
 //! ```toml
 //! [dependencies.uuid]
-//! version = "1.11.1"
+//! version = "1.12.0"
 //! default-features = false
 //! ```
 //!
@@ -211,7 +211,7 @@
 #![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.11.1"
+    html_root_url = "https://docs.rs/uuid/1.12.0"
 )]
 
 #[cfg(any(feature = "std", test))]
@@ -222,11 +222,9 @@
 #[macro_use]
 extern crate core as std;
 
-#[cfg(all(uuid_unstable, feature = "zerocopy"))]
-use zerocopy::{IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned};
-
 mod builder;
 mod error;
+mod non_nil;
 mod parser;
 
 pub mod fmt;
@@ -281,7 +279,7 @@
 
 use crate::std::convert;
 
-pub use crate::{builder::Builder, error::Error};
+pub use crate::{builder::Builder, error::Error, non_nil::NonNilUuid};
 
 /// A 128-bit (16 byte) buffer containing the UUID.
 ///
@@ -436,15 +434,16 @@
 ///
 /// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+// NOTE: Also check `NonNilUuid` when ading new derives here
 #[cfg_attr(
     all(uuid_unstable, feature = "zerocopy"),
-    derive(IntoBytes, FromBytes, KnownLayout, Immutable, Unaligned)
+    derive(zerocopy::IntoBytes, zerocopy::FromBytes, zerocopy::KnownLayout, zerocopy::Immutable, zerocopy::Unaligned)
 )]
 #[cfg_attr(
     feature = "borsh",
     derive(borsh_derive::BorshDeserialize, borsh_derive::BorshSerialize)
 )]
-#[repr(transparent)]
 #[cfg_attr(
     feature = "bytemuck",
     derive(bytemuck::Zeroable, bytemuck::Pod, bytemuck::TransparentWrapper)
diff --git a/crates/uuid/src/non_nil.rs b/crates/uuid/src/non_nil.rs
new file mode 100644
index 0000000..ee235a1
--- /dev/null
+++ b/crates/uuid/src/non_nil.rs
@@ -0,0 +1,142 @@
+//! A wrapper type for nil UUIDs that provides a more memory-efficient
+//! `Option<NonNilUuid>` representation.
+
+use core::convert::TryFrom;
+use std::{fmt, num::NonZeroU128};
+
+use crate::{
+    error::{Error, ErrorKind},
+    Uuid,
+};
+
+/// A UUID that is guaranteed not to be the [nil UUID](https://www.ietf.org/rfc/rfc9562.html#name-nil-uuid).
+///
+/// This is useful for representing optional UUIDs more efficiently, as `Option<NonNilUuid>`
+/// takes up the same space as `Uuid`.
+///
+/// Note that `Uuid`s created by the following methods are guaranteed to be non-nil:
+///
+/// - [`Uuid::new_v1`]
+/// - [`Uuid::now_v1`]
+/// - [`Uuid::new_v3`]
+/// - [`Uuid::new_v4`]
+/// - [`Uuid::new_v5`]
+/// - [`Uuid::new_v6`]
+/// - [`Uuid::now_v6`]
+/// - [`Uuid::new_v7`]
+/// - [`Uuid::now_v7`]
+/// - [`Uuid::new_v8`]
+///
+/// # ABI
+///
+/// The `NonNilUuid` type does not yet have a stable ABI. Its representation or alignment
+/// may change. It is currently only guaranteed that `NonNilUuid` and `Option<NonNilUuid>`
+/// are the same size as `Uuid`.
+#[repr(transparent)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct NonNilUuid(NonZeroU128);
+
+impl fmt::Display for NonNilUuid {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", Uuid::from(*self))
+    }
+}
+
+impl PartialEq<Uuid> for NonNilUuid {
+    fn eq(&self, other: &Uuid) -> bool {
+        self.get() == *other
+    }
+}
+
+impl PartialEq<NonNilUuid> for Uuid {
+    fn eq(&self, other: &NonNilUuid) -> bool {
+        *self == other.get()
+    }
+}
+
+impl NonNilUuid {
+    /// Creates a non-nil UUID if the value is non-nil.
+    pub const fn new(uuid: Uuid) -> Option<Self> {
+        match NonZeroU128::new(uuid.as_u128()) {
+            Some(non_nil) => Some(NonNilUuid(non_nil)),
+            None => None,
+        }
+    }
+
+    /// Creates a non-nil without checking whether the value is non-nil. This results in undefined behavior if the value is nil.
+    ///
+    /// # Safety
+    ///
+    /// The value must not be nil.
+    pub const unsafe fn new_unchecked(uuid: Uuid) -> Self {
+        NonNilUuid(unsafe { NonZeroU128::new_unchecked(uuid.as_u128()) })
+    }
+
+    /// Get the underlying [`Uuid`] value.
+    #[inline]
+    pub const fn get(self) -> Uuid {
+        Uuid::from_u128(self.0.get())
+    }
+}
+
+impl From<NonNilUuid> for Uuid {
+    /// Converts a [`NonNilUuid`] back into a [`Uuid`].
+    ///
+    /// # Examples
+    /// ```
+    /// # use std::convert::TryFrom;
+    /// # use uuid::{NonNilUuid, Uuid};
+    /// let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
+    /// let non_nil = NonNilUuid::try_from(uuid).unwrap();
+    /// let uuid_again = Uuid::from(non_nil);
+    ///
+    /// assert_eq!(uuid, uuid_again);
+    /// ```
+    fn from(non_nil: NonNilUuid) -> Self {
+        Uuid::from_u128(non_nil.0.get())
+    }
+}
+
+impl TryFrom<Uuid> for NonNilUuid {
+    type Error = Error;
+
+    /// Attempts to convert a [`Uuid`] into a [`NonNilUuid`].
+    ///
+    /// # Examples
+    /// ```
+    /// # use std::convert::TryFrom;
+    /// # use uuid::{NonNilUuid, Uuid};
+    /// let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
+    /// let non_nil = NonNilUuid::try_from(uuid).unwrap();
+    /// ```
+    fn try_from(uuid: Uuid) -> Result<Self, Self::Error> {
+        NonZeroU128::new(uuid.as_u128())
+            .map(Self)
+            .ok_or(Error(ErrorKind::Nil))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_non_nil_with_option_size() {
+        assert_eq!(
+            std::mem::size_of::<Option<NonNilUuid>>(),
+            std::mem::size_of::<Uuid>()
+        );
+    }
+
+    #[test]
+    fn test_non_nil() {
+        let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
+
+        assert_eq!(Uuid::from(NonNilUuid::try_from(uuid).unwrap()), uuid);
+        assert_eq!(NonNilUuid::new(uuid).unwrap(), uuid);
+        assert_eq!(unsafe { NonNilUuid::new_unchecked(uuid) }, uuid);
+
+        assert!(NonNilUuid::try_from(Uuid::nil()).is_err());
+        assert!(NonNilUuid::new(Uuid::nil()).is_none());
+    }
+}
diff --git a/crates/uuid/src/timestamp.rs b/crates/uuid/src/timestamp.rs
index 56262f1..d30df5b 100644
--- a/crates/uuid/src/timestamp.rs
+++ b/crates/uuid/src/timestamp.rs
@@ -128,7 +128,7 @@
     ///
     /// If conversion from the internal timestamp format to ticks would overflow
     /// then it will wrap.
-    /// 
+    ///
     /// If the internal counter is wider than 14 bits then it will be truncated to 14 bits.
     pub const fn to_gregorian(&self) -> (u64, u16) {
         (
@@ -165,17 +165,23 @@
 
 #[doc(hidden)]
 impl Timestamp {
-    #[deprecated(since = "1.11.1", note = "use `Timestamp::from_gregorian(ticks, counter)`")]
+    #[deprecated(
+        since = "1.10.0",
+        note = "use `Timestamp::from_gregorian(ticks, counter)`"
+    )]
     pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
         Timestamp::from_gregorian(ticks, counter)
     }
 
-    #[deprecated(since = "1.11.1", note = "use `Timestamp::to_gregorian()`")]
+    #[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
     pub const fn to_rfc4122(&self) -> (u64, u16) {
         self.to_gregorian()
     }
 
-    #[deprecated(since = "1.2.0", note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")]
+    #[deprecated(
+        since = "1.2.0",
+        note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
+    )]
     pub const fn to_unix_nanos(&self) -> u32 {
         panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
     }
diff --git a/crates/uuid/src/v7.rs b/crates/uuid/src/v7.rs
index c2b4a22..d55cf94 100644
--- a/crates/uuid/src/v7.rs
+++ b/crates/uuid/src/v7.rs
@@ -31,7 +31,7 @@
     /// # 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 combined 
+    /// random number. When supplied as such, the data will be combined
     /// to ensure uniqueness and sortability at millisecond granularity.
     ///
     /// ```rust
diff --git a/pseudo_crate/Cargo.lock b/pseudo_crate/Cargo.lock
index c937ee0..6854b57 100644
--- a/pseudo_crate/Cargo.lock
+++ b/pseudo_crate/Cargo.lock
@@ -3319,18 +3319,6 @@
 
 [[package]]
 name = "mockall_derive"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2"
-dependencies = [
- "cfg-if",
- "proc-macro2 1.0.93",
- "quote 1.0.38",
- "syn 2.0.96",
-]
-
-[[package]]
-name = "mockall_derive"
 version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898"
@@ -5798,9 +5786,9 @@
 
 [[package]]
 name = "uuid"
-version = "1.11.1"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4"
+checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
 
 [[package]]
 name = "valuable"
diff --git a/pseudo_crate/Cargo.toml b/pseudo_crate/Cargo.toml
index fe9a92a..542fea7 100644
--- a/pseudo_crate/Cargo.toml
+++ b/pseudo_crate/Cargo.toml
@@ -372,7 +372,7 @@
 userfaultfd = "=0.8.1"
 userfaultfd-sys = "=0.5.0"
 utf-8 = "=0.7.6"
-uuid = "=1.11.1"
+uuid = "=1.12.0"
 vhost = "=0.8.1"
 vhost-user-backend = "=0.10.1"
 virtio-bindings = "=0.2.2"