Skip to content

Commit

Permalink
refactor(core): replace Any by UnknownAttributeStorage to handle …
Browse files Browse the repository at this point in the history
…collections in attribute manager (#97)

* add downcast_rs dependency

this will be required as long as `trait_upcasting` isn't stabilized

* impl Downcast for UnknownAttributeStorage

* replace Any with UnknownStorageAttribute in manager struct

* split attribute-specific from manager-wide methods impl blocks

* move downcast macros to attribute-specific section

* add skeleton for merging methods

* fix extend method

* add split methods skeleton

* add doc entries for merge/split methods

* fix warnings

* add module-level doc
  • Loading branch information
imrn99 authored Jun 12, 2024
1 parent 93c2733 commit 162fa81
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ cfg-if = "1"
rustversion = "1.0.15"

# core
downcast-rs = "1.2.1"
num = "0.4.2"
vtkio = { version = "0.6.3" }

Expand Down
1 change: 1 addition & 0 deletions honeycomb-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ utils = []

[dependencies]
cfg-if.workspace = true
downcast-rs.workspace = true
num.workspace = true
vtkio = { workspace = true, optional = true }

Expand Down
296 changes: 277 additions & 19 deletions honeycomb-core/src/attributes/manager.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//! Module short description
//! attribute super structure code
//!
//! Should you interact with this module directly?
//!
//! Content description if needed
//! this module contains all code used to implement a manager struct, used to handle generic
//! attributes embedded in a given combinatorial map.
// ------ IMPORTS

use crate::{AttributeBind, AttributeStorage, OrbitPolicy, UnknownAttributeStorage};
use std::any::{Any, TypeId};
use crate::{
AttributeBind, AttributeStorage, DartIdentifier, OrbitPolicy, UnknownAttributeStorage,
};
use std::any::TypeId;
use std::collections::HashMap;

// ------ CONTENT
Expand Down Expand Up @@ -72,15 +73,247 @@ pub enum ManagerError {
#[derive(Default)]
pub struct AttrStorageManager {
/// Vertex attributes' storages.
vertices: HashMap<TypeId, Box<dyn Any>>,
vertices: HashMap<TypeId, Box<dyn UnknownAttributeStorage>>,
/// Edge attributes' storages.
edges: HashMap<TypeId, Box<dyn Any>>,
edges: HashMap<TypeId, Box<dyn UnknownAttributeStorage>>,
/// Face attributes' storages.
faces: HashMap<TypeId, Box<dyn Any>>,
faces: HashMap<TypeId, Box<dyn UnknownAttributeStorage>>,
/// Other storages.
others: HashMap<TypeId, Box<dyn Any>>, // Orbit::Custom
others: HashMap<TypeId, Box<dyn UnknownAttributeStorage>>, // Orbit::Custom
}

// --- manager-wide methods

impl AttrStorageManager {
/// Extend the size of all storages in the manager.
///
/// # Arguments
///
/// - `length: usize` -- Length by which storages should be extended.
pub fn extend_storages(&mut self, length: usize) {
for storage in self.vertices.values_mut() {
storage.extend(length);
}
for storage in self.edges.values_mut() {
storage.extend(length);
}
for storage in self.faces.values_mut() {
storage.extend(length);
}
for storage in self.others.values_mut() {
storage.extend(length);
}
}

// merges

/// Execute a merging operation on all attributes associated with a given orbit
/// for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_attributes(
&mut self,
orbit_policy: &OrbitPolicy,
id_out: DartIdentifier,
id_in_lhs: DartIdentifier,
id_in_rhs: DartIdentifier,
) {
match orbit_policy {
OrbitPolicy::Vertex => self.merge_vertex_attributes(id_out, id_in_lhs, id_in_rhs),
OrbitPolicy::Edge => self.merge_edge_attributes(id_out, id_in_lhs, id_in_rhs),
OrbitPolicy::Face => self.merge_face_attributes(id_out, id_in_lhs, id_in_rhs),
OrbitPolicy::Custom(_) => {
self.merge_other_attributes(orbit_policy, id_out, id_in_lhs, id_in_rhs);
}
}
}

/// Execute a merging operation on all attributes associated with vertices for specified cells.
///
/// # Arguments
///
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_vertex_attributes(
&mut self,
id_out: DartIdentifier,
id_in_lhs: DartIdentifier,
id_in_rhs: DartIdentifier,
) {
for storage in self.vertices.values_mut() {
storage.merge(id_out, id_in_lhs, id_in_rhs);
}
}

/// Execute a merging operation on all attributes associated with edges for specified cells.
///
/// # Arguments
///
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_edge_attributes(
&mut self,
id_out: DartIdentifier,
id_in_lhs: DartIdentifier,
id_in_rhs: DartIdentifier,
) {
for storage in self.edges.values_mut() {
storage.merge(id_out, id_in_lhs, id_in_rhs);
}
}

/// Execute a merging operation on all attributes associated with faces for specified cells.
///
/// # Arguments
///
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_face_attributes(
&mut self,
id_out: DartIdentifier,
id_in_lhs: DartIdentifier,
id_in_rhs: DartIdentifier,
) {
for storage in self.faces.values_mut() {
storage.merge(id_out, id_in_lhs, id_in_rhs);
}
}

/// Execute a merging operation on all attributes associated with a given orbit
/// for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_other_attributes(
&mut self,
_orbit_policy: &OrbitPolicy,
_id_out: DartIdentifier,
_id_in_lhs: DartIdentifier,
_id_in_rhs: DartIdentifier,
) {
todo!("custom orbit binding is a special case that will be treated later")
}

// splits

/// Execute a splitting operation on all attributes associated with a given orbit
/// for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_attributes(
&mut self,
orbit_policy: &OrbitPolicy,
id_out_lhs: DartIdentifier,
id_out_rhs: DartIdentifier,
id_in: DartIdentifier,
) {
match orbit_policy {
OrbitPolicy::Vertex => self.split_vertex_attributes(id_out_lhs, id_out_rhs, id_in),
OrbitPolicy::Edge => self.split_edge_attributes(id_out_lhs, id_out_rhs, id_in),
OrbitPolicy::Face => self.split_face_attributes(id_out_lhs, id_out_rhs, id_in),
OrbitPolicy::Custom(_) => {
self.split_other_attributes(orbit_policy, id_out_lhs, id_out_rhs, id_in);
}
}
}

/// Execute a splitting operation on all attributes associated with vertices
/// for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_vertex_attributes(
&mut self,
id_out_lhs: DartIdentifier,
id_out_rhs: DartIdentifier,
id_in: DartIdentifier,
) {
for storage in self.vertices.values_mut() {
storage.split(id_out_lhs, id_out_rhs, id_in);
}
}

/// Execute a splitting operation on all attributes associated with edges for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_edge_attributes(
&mut self,
id_out_lhs: DartIdentifier,
id_out_rhs: DartIdentifier,
id_in: DartIdentifier,
) {
for storage in self.edges.values_mut() {
storage.split(id_out_lhs, id_out_rhs, id_in);
}
}

/// Execute a splitting operation on all attributes associated with faces for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_face_attributes(
&mut self,
id_out_lhs: DartIdentifier,
id_out_rhs: DartIdentifier,
id_in: DartIdentifier,
) {
for storage in self.faces.values_mut() {
storage.split(id_out_lhs, id_out_rhs, id_in);
}
}

/// Execute a splitting operation on all attributes associated with a given orbit
/// for specified cells.
///
/// # Arguments
///
/// - `orbit_policy: OrbitPolicy` -- Orbit associated with affected attributes.
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_other_attributes(
&mut self,
_orbit_policy: &OrbitPolicy,
_id_out_lhs: DartIdentifier,
_id_out_rhs: DartIdentifier,
_id_in: DartIdentifier,
) {
todo!("custom orbit binding is a special case that will be treated later")
}
}

// --- attribute-specific methods

macro_rules! get_storage {
($slf: ident, $id: ident) => {
let probably_storage = match A::binds_to() {
Expand Down Expand Up @@ -152,15 +385,6 @@ impl AttrStorageManager {
}
}

/// UNIMPLEMENTED
pub fn extend_storages(&mut self, _length: usize) {
// not sure if this is actually possible since we need to fetch the attribute from storages,
// which cannot be interpreted as such without the attribute in the first place
for _storage in self.vertices.values_mut() {
todo!()
}
}

/// Extend the size of the storage of a given attribute.
///
/// # Arguments
Expand Down Expand Up @@ -329,4 +553,38 @@ impl AttrStorageManager {
get_storage_mut!(self, storage);
storage.remove(id)
}

/// Merge given attribute values.
///
/// # Arguments
///
/// - `id_out: DartIdentifier` -- Identifier to write the result to.
/// - `id_in_lhs: DartIdentifier` -- Identifier of one attribute value to merge.
/// - `id_in_rhs: DartIdentifier` -- Identifier of the other attribute value to merge.
pub fn merge_attribute<A: AttributeBind>(
&mut self,
id_out: DartIdentifier,
id_in_lhs: DartIdentifier,
id_in_rhs: DartIdentifier,
) {
get_storage_mut!(self, storage);
storage.merge(id_out, id_in_lhs, id_in_rhs);
}

/// Split given attribute value.
///
/// # Arguments
///
/// - `id_out_lhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_out_rhs: DartIdentifier` -- Identifier to write the result to.
/// - `id_in: DartIdentifier` -- Identifier of the attribute value to split.
pub fn split_attribute<A: AttributeBind>(
&mut self,
id_out_lhs: DartIdentifier,
id_out_rhs: DartIdentifier,
id_in: DartIdentifier,
) {
get_storage_mut!(self, storage);
storage.split(id_out_lhs, id_out_rhs, id_in);
}
}
5 changes: 4 additions & 1 deletion honeycomb-core/src/attributes/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// ------ IMPORTS

use crate::{DartIdentifier, OrbitPolicy};
use downcast_rs::{impl_downcast, Downcast};
use std::any::Any;
use std::fmt::Debug;

Expand Down Expand Up @@ -131,7 +132,7 @@ pub trait AttributeBind: Debug + Sized + Any {
/// This trait contain attribute-agnostic function & methods.
///
/// The documentation of this trait describe the behavior each function & method should have.
pub trait UnknownAttributeStorage: Debug + Any {
pub trait UnknownAttributeStorage: Any + Debug + Downcast {
/// Constructor
///
/// # Arguments
Expand Down Expand Up @@ -205,6 +206,8 @@ pub trait UnknownAttributeStorage: Debug + Any {
fn split(&mut self, lhs_out: DartIdentifier, rhs_out: DartIdentifier, inp: DartIdentifier);
}

impl_downcast!(UnknownAttributeStorage);

/// Common trait implemented by generic attribute storages.
///
/// This trait contain attribute-specific methods.
Expand Down

0 comments on commit 162fa81

Please sign in to comment.