fj_core/objects/
any_object.rs

1use crate::{
2    geometry::Geometry,
3    objects::{
4        Curve, Cycle, Face, HalfEdge, Objects, Region, Shell, Sketch, Solid,
5        Surface, Vertex,
6    },
7    storage::{Handle, HandleWrapper, ObjectId},
8    validate::Validate,
9    validation::{ValidationConfig, ValidationError},
10};
11
12macro_rules! any_object {
13    ($($ty:ident, $name:expr, $store:ident;)*) => {
14        /// An enum that can hold any object
15        ///
16        /// This enum is generic over the form that the object takes. An
17        /// `AnyObject<Bare>` contains a bare objects, for example `Curve`. An
18        /// `AnyObject<Stored>` contains a handle referencing a stored object,
19        /// for example `Handle<Curve>`.
20        #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
21        pub enum AnyObject<F: Form> {
22            $(
23                #[doc = concat!("A ", $name)]
24                $ty(F::Form<$ty>),
25            )*
26        }
27
28        impl AnyObject<Stored> {
29            /// Access the ID of the object
30            pub fn id(&self) -> ObjectId {
31                match self {
32                    $(
33                        Self::$ty(handle) => handle.id(),
34                    )*
35                }
36            }
37
38            /// Validate the object with a pre-defined validation configuration
39            pub fn validate(&self,
40                config: &ValidationConfig,
41                errors: &mut Vec<ValidationError>,
42                geometry: &Geometry,
43            ) {
44                match self {
45                    $(
46                        Self::$ty(object) => object.validate(
47                            config,
48                            errors,
49                            geometry,
50                        ),
51                    )*
52                }
53            }
54        }
55
56        impl AnyObject<AboutToBeStored> {
57            /// Insert the object into its respective store
58            pub fn insert(self, objects: &mut Objects) -> AnyObject<Stored> {
59                match self {
60                    $(
61                        Self::$ty((handle, object)) => {
62                            objects.$store.insert(
63                                handle.clone().into(), object
64                            );
65                            handle.0.into()
66                        }
67                    )*
68                }
69            }
70        }
71
72        impl From<AnyObject<AboutToBeStored>> for AnyObject<Stored> {
73            fn from(object: AnyObject<AboutToBeStored>) -> Self {
74                match object {
75                    $(
76                        AnyObject::$ty((handle, _)) => Self::$ty(handle.into()),
77                    )*
78                }
79            }
80        }
81
82        $(
83            impl From<$ty> for AnyObject<Bare> {
84                fn from(object: $ty) -> Self {
85                    Self::$ty(object)
86                }
87            }
88
89            impl From<Handle<$ty>> for AnyObject<Stored> {
90                fn from(object: Handle<$ty>) -> Self {
91                    Self::$ty(object.into())
92                }
93            }
94
95            impl From<(Handle<$ty>, $ty)> for AnyObject<AboutToBeStored> {
96                fn from((handle, object): (Handle<$ty>, $ty)) -> Self {
97                    Self::$ty((handle.into(), object))
98                }
99            }
100        )*
101    };
102}
103
104any_object!(
105    Curve, "curve", curves;
106    Cycle, "cycle", cycles;
107    Face, "face", faces;
108    HalfEdge, "half-edge", half_edges;
109    Region, "region", regions;
110    Shell, "shell", shells;
111    Sketch, "sketch", sketches;
112    Solid, "solid", solids;
113    Surface, "surface", surfaces;
114    Vertex, "vertex", vertices;
115);
116
117/// The form that an object can take
118///
119/// This is used together with [`AnyObject`].
120///
121/// An object can be bare ([`Bare`]), stored ([`Stored`]), or it can be about to
122/// be - but not yet - stored ([`AboutToBeStored`]).
123pub trait Form {
124    /// The form that the object takes
125    type Form<T>;
126}
127
128/// Implementation of [`Form`] for bare objects
129#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
130pub struct Bare;
131
132impl Form for Bare {
133    type Form<T> = T;
134}
135
136/// Implementation of [`Form`] for stored objects
137#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
138pub struct Stored;
139
140impl Form for Stored {
141    type Form<T> = HandleWrapper<T>;
142}
143
144/// Implementation of [`Form`] for objects that are about to be stored
145///
146/// When storing an object, a [`Handle`] instance is generated first. Then both
147/// that [`Handle`] instance and the bare object are sent to the object service,
148/// for storage.
149///
150/// This is the one use case where this form is required.
151#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
152pub struct AboutToBeStored;
153
154impl Form for AboutToBeStored {
155    type Form<T> = (HandleWrapper<T>, T);
156}