diff --git a/crates/fj-kernel/src/stores/handle.rs b/crates/fj-kernel/src/stores/handle.rs index e18c6856b..f227516ec 100644 --- a/crates/fj-kernel/src/stores/handle.rs +++ b/crates/fj-kernel/src/stores/handle.rs @@ -153,3 +153,76 @@ unsafe impl Sync for Handle {} /// See [`Handle::id`]. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct ObjectId(u64); + +/// A wrapper around [`Handle`] to define equality based on identity +/// +/// This is a utility type that implements [`Eq`]/[`PartialEq`] and other common +/// traits that are based on those, based on the identity of object that the +/// wrapped handle references. This is useful, if a type of object doesn't +/// implement `Eq`/`PartialEq`, which means handles referencing it won't +/// implement those types either. +/// +/// Typically, if an object doesn't implement [`Eq`]/[`PartialEq`], it will do +/// so for good reason. If you need something that represents the object and +/// implements those missing traits, you might want to be explicit about what +/// you're doing, and access its ID via [`Handle::id`] instead. +/// +/// But if you have a struct that owns a [`Handle`] to such an object, and you +/// want to be able to derive various traits that are not available for the +/// [`Handle`] itself, this wrapper is for you. +pub struct HandleWrapper(pub Handle); + +impl Deref for HandleWrapper { + type Target = Handle; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Clone for HandleWrapper { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Eq for HandleWrapper {} + +impl PartialEq for HandleWrapper { + fn eq(&self, other: &Self) -> bool { + self.0.id().eq(&other.0.id()) + } +} + +impl Hash for HandleWrapper { + fn hash(&self, state: &mut H) { + self.0.id().hash(state) + } +} + +impl Ord for HandleWrapper { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.id().cmp(&other.0.id()) + } +} + +impl PartialOrd for HandleWrapper { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.id().partial_cmp(&other.0.id()) + } +} + +impl fmt::Debug for HandleWrapper { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl From> for HandleWrapper { + fn from(handle: Handle) -> Self { + Self(handle) + } +} + +unsafe impl Send for HandleWrapper {} +unsafe impl Sync for HandleWrapper {} diff --git a/crates/fj-kernel/src/stores/mod.rs b/crates/fj-kernel/src/stores/mod.rs index 3b871d8a6..3d2c6b257 100644 --- a/crates/fj-kernel/src/stores/mod.rs +++ b/crates/fj-kernel/src/stores/mod.rs @@ -7,7 +7,7 @@ mod store; use crate::objects::GlobalCurve; pub use self::{ - handle::{Handle, ObjectId}, + handle::{Handle, HandleWrapper, ObjectId}, store::{Iter, Reservation, Store}, };