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