From 13f2749021175c6377e6efe99f17a4e129fd33f4 Mon Sep 17 00:00:00 2001 From: Gino Valente <49806985+MrGVSV@users.noreply.github.com> Date: Sat, 25 Nov 2023 16:21:35 -0700 Subject: [PATCH] bevy_utils: Export `generate_composite_uuid` utility function (#10496) # Objective The `generate_composite_uuid` utility function hidden in `bevy_reflect::__macro_exports` could be generally useful to users. For example, I previously relied on `Hash` to generate a `u64` to create a deterministic `HandleId`. In v0.12, `HandleId` has been replaced by `AssetId` which now requires a `Uuid`, which I could generate with this function. ## Solution Relocate `generate_composite_uuid` from `bevy_reflect::__macro_exports` to `bevy_utils::uuid`. It is still re-exported under `bevy_reflect::__macro_exports` so there should not be any breaking changes (although, users should generally not rely on pseudo-private/hidden modules like `__macro_exports`). I chose to keep it in `bevy_reflect::__macro_exports` so as to not clutter up our public API and to reduce the number of changes in this PR. We could have also marked the export as `#[doc(hidden)]`, but personally I like that we have a dedicated module for this (makes it clear what is public and what isn't when just looking at the macro code). --- ## Changelog - Moved `generate_composite_uuid` to `bevy_utils::uuid` and made it public - Note: it was technically already public, just hidden --- crates/bevy_reflect/src/lib.rs | 27 +-------------------- crates/bevy_reflect/src/type_uuid.rs | 2 +- crates/bevy_utils/src/lib.rs | 4 +++- crates/bevy_utils/src/uuid.rs | 35 ++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 crates/bevy_utils/src/uuid.rs diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 84aae3675f..f7cc072057 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -542,32 +542,7 @@ extern crate alloc; #[doc(hidden)] pub mod __macro_exports { - use crate::Uuid; - - /// Generates a new UUID from the given UUIDs `a` and `b`, - /// where the bytes are generated by a bitwise `a ^ b.rotate_right(1)`. - /// The generated UUID will be a `UUIDv4` (meaning that the bytes should be random, not e.g. derived from the system time). - #[allow(clippy::unusual_byte_groupings)] // unusual byte grouping is meant to signal the relevant bits - pub const fn generate_composite_uuid(a: Uuid, b: Uuid) -> Uuid { - let mut new = [0; 16]; - let mut i = 0; - while i < new.len() { - // rotating ensures different uuids for A> and B> because: A ^ (B ^ C) = B ^ (A ^ C) - // notice that you have to rotate the second parameter: A.rr ^ (B.rr ^ C) = B.rr ^ (A.rr ^ C) - // Solution: A ^ (B ^ C.rr).rr != B ^ (A ^ C.rr).rr - new[i] = a.as_bytes()[i] ^ b.as_bytes()[i].rotate_right(1); - - i += 1; - } - - // Version: the most significant 4 bits in the 6th byte: 11110000 - new[6] = new[6] & 0b0000_1111 | 0b0100_0000; // set version to v4 - - // Variant: the most significant 3 bits in the 8th byte: 11100000 - new[8] = new[8] & 0b000_11111 | 0b100_00000; // set variant to rfc4122 - - Uuid::from_bytes(new) - } + pub use bevy_utils::uuid::generate_composite_uuid; } #[cfg(test)] diff --git a/crates/bevy_reflect/src/type_uuid.rs b/crates/bevy_reflect/src/type_uuid.rs index 79ccbb0217..7c02f998cd 100644 --- a/crates/bevy_reflect/src/type_uuid.rs +++ b/crates/bevy_reflect/src/type_uuid.rs @@ -1,5 +1,5 @@ pub use bevy_reflect_derive::TypeUuid; -pub use bevy_utils::Uuid; +pub use bevy_utils::uuid::Uuid; /// A trait for types with a statically associated UUID. pub trait TypeUuid { diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index 320bb407c9..245a9494aa 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -17,11 +17,14 @@ pub use short_names::get_short_name; pub mod synccell; pub mod syncunsafecell; +pub mod uuid; + mod cow_arc; mod default; mod float_ord; pub mod intern; +pub use crate::uuid::Uuid; pub use ahash::{AHasher, RandomState}; pub use bevy_utils_proc_macros::*; pub use cow_arc::*; @@ -32,7 +35,6 @@ pub use instant::{Duration, Instant}; pub use petgraph; pub use thiserror; pub use tracing; -pub use uuid::Uuid; #[allow(missing_docs)] pub mod nonmax { diff --git a/crates/bevy_utils/src/uuid.rs b/crates/bevy_utils/src/uuid.rs new file mode 100644 index 0000000000..35edd2353f --- /dev/null +++ b/crates/bevy_utils/src/uuid.rs @@ -0,0 +1,35 @@ +//! UUID utilities. +//! +//! This module re-exports the [`Uuid`] type from the [`uuid`] crate, +//! and provides additional utility functions. +//! +//! [`uuid`]: ::uuid + +pub use ::uuid::Uuid; + +/// Generates a new UUID from the given UUIDs `a` and `b`, +/// where the bytes are generated by a bitwise `a ^ b.rotate_right(1)`. +/// +/// The generated UUID will be a `UUIDv4` +/// (meaning that the bytes should be random, not e.g. derived from the system time). +#[allow(clippy::unusual_byte_groupings)] // unusual byte grouping is meant to signal the relevant bits +pub const fn generate_composite_uuid(a: Uuid, b: Uuid) -> Uuid { + let mut new = [0; 16]; + let mut i = 0; + while i < new.len() { + // rotating ensures different uuids for A> and B> because: A ^ (B ^ C) = B ^ (A ^ C) + // notice that you have to rotate the second parameter: A.rr ^ (B.rr ^ C) = B.rr ^ (A.rr ^ C) + // Solution: A ^ (B ^ C.rr).rr != B ^ (A ^ C.rr).rr + new[i] = a.as_bytes()[i] ^ b.as_bytes()[i].rotate_right(1); + + i += 1; + } + + // Version: the most significant 4 bits in the 6th byte: 11110000 + new[6] = new[6] & 0b0000_1111 | 0b0100_0000; // set version to v4 + + // Variant: the most significant 3 bits in the 8th byte: 11100000 + new[8] = new[8] & 0b000_11111 | 0b100_00000; // set variant to rfc4122 + + Uuid::from_bytes(new) +}