
# 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
36 lines
1.3 KiB
Rust
36 lines
1.3 KiB
Rust
//! 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<B<C>> and B<A<C>> 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)
|
|
}
|