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
use crate::{
objects::{
Cycle, Face, GlobalEdge, HalfEdge, Region, Shell, Sketch, Solid,
Surface, Vertex,
},
services::Services,
storage::Handle,
};
use super::{Polygon, TetrahedronShell};
/// Insert an object into its respective store
///
/// This is the only primitive operation that is directly understood by
/// `Service<Objects>`. All other operations are built on top of it.
pub trait Insert: Sized {
/// The type of `Self`, once it has been inserted
///
/// Usually this is just `Handle<Self>`, but there are some more complex
/// cases where this type needs to be customized.
type Inserted;
/// Insert the object into its respective store
fn insert(self, services: &mut Services) -> Self::Inserted;
}
macro_rules! impl_insert {
($($ty:ty, $store:ident;)*) => {
$(
impl Insert for $ty {
type Inserted = Handle<Self>;
fn insert(self, services: &mut Services) -> Self::Inserted {
let handle = services.objects.$store.reserve();
let object = (handle.clone(), self).into();
services.insert_object(object);
handle
}
}
)*
};
}
impl_insert!(
Cycle, cycles;
Face, faces;
GlobalEdge, global_edges;
HalfEdge, half_edges;
Region, regions;
Shell, shells;
Sketch, sketches;
Solid, solids;
Surface, surfaces;
Vertex, vertices;
);
/// Indicate whether an object has been inserted
///
/// Intended to be used as a type parameter bound for structs that need to track
/// whether their contents have been inserted or not.
pub trait IsInserted {
/// The type of the object for which the insertion status is tracked
type T<T>;
}
/// Indicate that an object has been inserted
///
/// See [`IsInserted`].
pub struct IsInsertedYes;
impl IsInserted for IsInsertedYes {
type T<T> = Handle<T>;
}
/// Indicate that an object has not been inserted
///
/// See [`IsInserted`].
pub struct IsInsertedNo;
impl IsInserted for IsInsertedNo {
type T<T> = T;
}
impl<const D: usize> Insert for Polygon<D, IsInsertedNo> {
type Inserted = Polygon<D, IsInsertedYes>;
fn insert(self, services: &mut Services) -> Self::Inserted {
Polygon {
face: self.face.insert(services),
edges: self.edges,
vertices: self.vertices,
}
}
}
impl Insert for TetrahedronShell<IsInsertedNo> {
type Inserted = TetrahedronShell<IsInsertedYes>;
fn insert(self, services: &mut Services) -> Self::Inserted {
TetrahedronShell {
shell: self.shell.insert(services),
abc: self.abc,
bad: self.bad,
dac: self.dac,
cbd: self.cbd,
}
}
}