fj_core/validate/
references.rs1use std::collections::HashMap;
2use std::hash::Hash;
3
4use crate::objects::{Cycle, Face, HalfEdge, Region, Shell};
5use crate::storage::Handle;
6
7#[derive(Default)]
8pub struct ReferenceCounter<T, U>(HashMap<Handle<T>, Vec<Handle<U>>>);
9
10impl<T: Eq + PartialEq + Hash, U> ReferenceCounter<T, U> {
11 pub fn new() -> Self {
12 Self(HashMap::new())
13 }
14
15 pub fn add_reference(
16 &mut self,
17 referenced: Handle<T>,
18 reference: Handle<U>,
19 ) {
20 self.0
21 .entry(referenced)
22 .and_modify(|references| references.push(reference.clone()))
23 .or_insert(vec![reference]);
24 }
25
26 pub fn get_multiples(&self) -> Vec<MultipleReferences<T, U>> {
27 self.0
28 .iter()
29 .filter(|(_, references)| references.len() > 1)
30 .map(|(referenced, references)| MultipleReferences {
31 referenced: referenced.clone(),
32 references: references.to_vec(),
33 })
34 .collect()
35 }
36}
37
38#[macro_export]
40macro_rules! validate_references {
41 ($errors:ident, $error_ty:ty;$($counter:ident, $err:ident;)*) => {
42 $(
43 $counter.get_multiples().iter().for_each(|multiple| {
44 let reference_error = ReferenceCountError::$err { references: multiple.clone() };
45 $errors.push(Into::<$error_ty>::into(reference_error).into());
46 });
47 )*
48 };
49}
50
51#[derive(Clone, Debug, thiserror::Error)]
54pub enum ReferenceCountError {
55 #[error(
57 "[`Region`] referenced by more than one [`Face`]\n{references:#?}"
58 )]
59 Region {
60 references: MultipleReferences<Region, Face>,
61 },
62 #[error("[`Face`] referenced by more than one [`Shell`]\n{references:#?}")]
64 Face {
65 references: MultipleReferences<Face, Shell>,
66 },
67 #[error(
69 "[`HalfEdge`] referenced by more than one [`Cycle`]\n{references:#?}"
70 )]
71 HalfEdge {
72 references: MultipleReferences<HalfEdge, Cycle>,
73 },
74 #[error(
76 "[`Cycle`] referenced by more than one [`Region`]\n{references:#?}"
77 )]
78 Cycle {
79 references: MultipleReferences<Cycle, Region>,
80 },
81}
82
83pub struct MultipleReferences<T, U> {
84 referenced: Handle<T>,
85 references: Vec<Handle<U>>,
86}
87
88use std::fmt::Debug;
89
90impl<T: Debug, U: Debug> Debug for MultipleReferences<T, U> {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 write!(
93 f,
94 "{:?} referenced by {:?}",
95 self.referenced, self.references
96 )
97 }
98}
99
100impl<T, U> Clone for MultipleReferences<T, U> {
101 fn clone(&self) -> Self {
102 Self {
103 referenced: self.referenced.clone(),
104 references: self.references.to_vec(),
105 }
106 }
107}