From 30c9afea42887e5f555f452fe8d3b2e3842f6b2e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 30 Mar 2022 23:34:10 +0200 Subject: [PATCH] Merge `handle` into `stores` --- fj-kernel/src/shape/handle.rs | 63 ----------------------------------- fj-kernel/src/shape/mod.rs | 4 +-- fj-kernel/src/shape/stores.rs | 60 +++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 68 deletions(-) delete mode 100644 fj-kernel/src/shape/handle.rs diff --git a/fj-kernel/src/shape/handle.rs b/fj-kernel/src/shape/handle.rs deleted file mode 100644 index 3207bfc03b..0000000000 --- a/fj-kernel/src/shape/handle.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::hash::Hash; - -use slotmap::DefaultKey; - -use super::stores::Store; - -/// A handle to an object stored within [`Shape`] -/// -/// If an object of type `T` (this could be `Curve`, `Vertex`, etc.) is added to -/// `Shape`, a `Handle` is returned. This handle is then used in topological -/// types to refer to the object, instead of having those types own an instance -/// of the object. -/// -/// This approach has two advantages: -/// -/// 1. The object can't be mutated through the handle. Since an object can be -/// referred to by multiple other objects, mutating it locally would have no -/// effect on those other references. `Handle` preventing that removes this -/// source of errors. -/// 2. The object is guaranteed to be in `Shape`, as `Handle`s can't be created -/// any other way. This means that if the `Shape` needs to be modified, any -/// objects can be updated once, without requiring an update of all the other -/// objects that reference it. -/// -/// # Equality -/// -/// The equality of [`Handle`] is very strictly defined in terms of identity. -/// Two [`Handle`]s are considered equal, if they refer to objects in the same -/// memory location. -#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub struct Handle { - key: DefaultKey, - store: Store, -} - -impl Handle { - pub(super) fn new(key: DefaultKey, store: Store) -> Self { - Self { key, store } - } - - pub(super) fn key(&self) -> DefaultKey { - self.key - } - - pub(super) fn store(&self) -> &Store { - &self.store - } - - /// Access the object that the handle references - pub fn get(&self) -> T - where - T: Clone, - { - self.store - .read() - .get(self.key) - // Can't panic, unless the handle was invalid in the first place. - // Objects are never removed from `Store`, so if we have a handle - // pointing to it, it should be there. - .unwrap() - .clone() - } -} diff --git a/fj-kernel/src/shape/mod.rs b/fj-kernel/src/shape/mod.rs index 14bef36f74..a99f7772bd 100644 --- a/fj-kernel/src/shape/mod.rs +++ b/fj-kernel/src/shape/mod.rs @@ -4,7 +4,6 @@ mod api; mod geometry; -mod handle; mod stores; mod topology; mod validate; @@ -12,8 +11,7 @@ mod validate; pub use self::{ api::Shape, geometry::Geometry, - handle::Handle, - stores::Iter, + stores::{Handle, Iter}, topology::Topology, validate::{StructuralIssues, ValidationError, ValidationResult}, }; diff --git a/fj-kernel/src/shape/stores.rs b/fj-kernel/src/shape/stores.rs index 975e8bd9ca..27e590b853 100644 --- a/fj-kernel/src/shape/stores.rs +++ b/fj-kernel/src/shape/stores.rs @@ -12,8 +12,6 @@ use crate::{ topology::{Cycle, Edge, Face, Vertex}, }; -use super::Handle; - pub type Points = Store>; pub type Curves = Store; pub type Surfaces = Store; @@ -116,6 +114,64 @@ impl Hash for Store { pub type Objects = SlotMap; +/// A handle to an object stored within [`Shape`] +/// +/// If an object of type `T` (this could be `Curve`, `Vertex`, etc.) is added to +/// `Shape`, a `Handle` is returned. This handle is then used in topological +/// types to refer to the object, instead of having those types own an instance +/// of the object. +/// +/// This approach has two advantages: +/// +/// 1. The object can't be mutated through the handle. Since an object can be +/// referred to by multiple other objects, mutating it locally would have no +/// effect on those other references. `Handle` preventing that removes this +/// source of errors. +/// 2. The object is guaranteed to be in `Shape`, as `Handle`s can't be created +/// any other way. This means that if the `Shape` needs to be modified, any +/// objects can be updated once, without requiring an update of all the other +/// objects that reference it. +/// +/// # Equality +/// +/// The equality of [`Handle`] is very strictly defined in terms of identity. +/// Two [`Handle`]s are considered equal, if they refer to objects in the same +/// memory location. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Handle { + key: DefaultKey, + store: Store, +} + +impl Handle { + pub(super) fn new(key: DefaultKey, store: Store) -> Self { + Self { key, store } + } + + pub(super) fn key(&self) -> DefaultKey { + self.key + } + + pub(super) fn store(&self) -> &Store { + &self.store + } + + /// Access the object that the handle references + pub fn get(&self) -> T + where + T: Clone, + { + self.store + .read() + .get(self.key) + // Can't panic, unless the handle was invalid in the first place. + // Objects are never removed from `Store`, so if we have a handle + // pointing to it, it should be there. + .unwrap() + .clone() + } +} + /// An iterator over geometric or topological objects /// /// Returned by various methods of the [`Shape`] API.