fj_kernel/objects/
object.rs

1use crate::{
2    objects::{
3        Cycle, Face, GlobalEdge, HalfEdge, Objects, Shell, Sketch, Solid,
4        Surface, Vertex,
5    },
6    storage::{Handle, HandleWrapper, ObjectId},
7    validate::{Validate, ValidationError},
8};
9
10macro_rules! object {
11    ($($ty:ident, $name:expr, $store:ident;)*) => {
12        /// An object
13        ///
14        /// This enum is generic over the form that the object takes. An
15        /// `Object<Bare>` contains bare objects, like `Curve`. An
16        /// `Object<BehindHandle>` contains handles, like `Handle<Curve>`.
17        #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
18        pub enum Object<F: Form> {
19            $(
20                #[doc = concat!("A ", $name)]
21                $ty(F::Form<$ty>),
22            )*
23        }
24
25        impl Object<BehindHandle> {
26            /// Access the ID of the object
27            pub fn id(&self) -> ObjectId {
28                match self {
29                    $(
30                        Self::$ty(handle) => handle.id(),
31                    )*
32                }
33            }
34
35            /// Validate the object
36            pub fn validate(&self, errors: &mut Vec<ValidationError>) {
37                match self {
38                    $(
39                        Self::$ty(object) => object.validate(errors),
40                    )*
41                }
42            }
43        }
44
45        impl Object<WithHandle> {
46            /// Insert the object into its respective store
47            pub fn insert(self, objects: &mut Objects) -> Object<BehindHandle> {
48                match self {
49                    $(
50                        Self::$ty((handle, object)) => {
51                            objects.$store.insert(
52                                handle.clone().into(), object
53                            );
54                            handle.0.into()
55                        }
56                    )*
57                }
58            }
59        }
60
61        impl From<Object<WithHandle>> for Object<BehindHandle> {
62            fn from(object: Object<WithHandle>) -> Self {
63                match object {
64                    $(
65                        Object::$ty((handle, _)) => Self::$ty(handle.into()),
66                    )*
67                }
68            }
69        }
70
71        $(
72            impl From<$ty> for Object<Bare> {
73                fn from(object: $ty) -> Self {
74                    Self::$ty(object)
75                }
76            }
77
78            impl From<Handle<$ty>> for Object<BehindHandle> {
79                fn from(object: Handle<$ty>) -> Self {
80                    Self::$ty(object.into())
81                }
82            }
83
84            impl From<(Handle<$ty>, $ty)> for Object<WithHandle> {
85                fn from((handle, object): (Handle<$ty>, $ty)) -> Self {
86                    Self::$ty((handle.into(), object))
87                }
88            }
89        )*
90    };
91}
92
93object!(
94    Cycle, "cycle", cycles;
95    Face, "face", faces;
96    GlobalEdge, "global edge", global_edges;
97    HalfEdge, "half-edge", half_edges;
98    Shell, "shell", shells;
99    Sketch, "sketch", sketches;
100    Solid, "solid", solids;
101    Surface, "surface", surfaces;
102    Vertex, "vertex", vertices;
103);
104
105/// The form that an object can take
106///
107/// An object can be bare ([`Bare`]), behind a [`Handle`] ([`BehindHandle`]), or
108/// can take the form of a handle *and* an object [`WithHandle`].
109pub trait Form {
110    /// The form that the object takes
111    type Form<T>;
112}
113
114/// Implementation of [`Form`] for bare objects
115#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
116pub struct Bare;
117
118impl Form for Bare {
119    type Form<T> = T;
120}
121
122/// Implementation of [`Form`] for objects behind a handle
123#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
124pub struct BehindHandle;
125
126impl Form for BehindHandle {
127    type Form<T> = HandleWrapper<T>;
128}
129
130/// Implementation of [`Form`] for objects that are paired with their handle
131#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
132pub struct WithHandle;
133
134impl Form for WithHandle {
135    type Form<T> = (HandleWrapper<T>, T);
136}