From 5c471ffd75df734c04a7a27343a63879872afbce Mon Sep 17 00:00:00 2001 From: Charlotte Pabst Date: Fri, 23 Feb 2024 03:04:36 +0100 Subject: --- src/main.rs | 428 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 243 insertions(+), 185 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index ae1d891..8384fc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,4 @@ -#![allow(unused)] #![allow(private_bounds)] -// the ptr! macro will expand to complex types but makes things easier to read for humans -// unlike type definitions, a macro can capture the 'brand and 'arena lifetimes from the scope -#![allow(clippy::type_complexity)] use core::ops::Deref; pub use ghost_cell::{GhostBorrow, GhostCell, GhostToken}; @@ -37,42 +33,55 @@ impl fmt::Result> Debug for DebugFn { } } +#[macro_export] macro_rules! ptr_t { ($T:ty) => { Ptr<'brand, 'arena, $T> } } +#[macro_export] macro_rules! ptr { ($T:ident) => { Ptr<'brand, 'arena, $T<'brand, 'arena, V>> }; } +#[macro_export] macro_rules! own_t { ($T:ty) => { Own<'brand, 'arena, $T> } } +#[macro_export] macro_rules! own { ($T:ident) => { Own<'brand, 'arena, $T<'brand, 'arena, V>> }; } +#[macro_export] macro_rules! lens_t { ($T:ty) => { Lens<'tok, 'brand, 'arena, $T> } } +#[macro_export] macro_rules! lens { ($T:ident) => { Lens<'tok, 'brand, 'arena, $T<'brand, 'arena, V>> }; } +#[macro_export] +macro_rules! mklens { + ($token: expr, $($name:ident),*) => { + $( let $name = $name.lens($token); )* + }; +} + fn _short_debug(ty: &'static str, id: usize, f: &mut Formatter) -> fmt::Result { f.debug_tuple(ty).field(&id).finish() } @@ -132,6 +141,7 @@ impl<'brand, 'arena, T> ptr_t!(T) { } } +#[allow(unused)] impl<'brand, 'arena, T: Entity<'brand, 'arena>> ptr_t!(T) { fn clear(self, token: &mut impl ReflAsMut>) { self.borrow_mut(token).clear() @@ -220,6 +230,12 @@ impl<'tok, 'brand, 'arena, T> ReflAsRef> for lens_t!(T) { } } +impl<'tok, 'brand, 'arena, T> From for ptr_t!(T) { + fn from(x: lens_t!(T)) -> Self { + x.item + } +} + impl<'tok, 'brand, 'arena, T> lens_t!(T) { pub fn new(item: ptr_t!(T), token: &'tok impl ReflAsRef>) -> Self { Self { @@ -229,6 +245,7 @@ impl<'tok, 'brand, 'arena, T> lens_t!(T) { } } +#[allow(unused)] impl<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>> lens_t!(T) { pub fn id(self) -> usize { self.item.id(&self) @@ -270,7 +287,7 @@ impl<'tok, 'brand, 'arena, T> Clone for EntityIterator<'tok, 'brand, 'arena, T> impl<'tok, 'brand, 'arena, T> Copy for EntityIterator<'tok, 'brand, 'arena, T> {} impl<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>> EntityIterator<'tok, 'brand, 'arena, T> { - fn new(token: &'tok impl ReflAsRef>, start: Option) -> Self { + fn new(start: Option, token: &'tok impl ReflAsRef>) -> Self { Self(start.map(|s| { let l = Lens::new(s, token); (l, l.prev()) @@ -284,7 +301,7 @@ impl<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>> Iterator type Item = lens_t!(T); fn next(&mut self) -> Option { - let mut range = self.0.as_mut()?; + let range = self.0.as_mut()?; let ret = range.0; if range.0 == range.1 { @@ -301,7 +318,7 @@ impl<'tok, 'brand, 'arena, T: Entity<'brand, 'arena>> DoubleEndedIterator for EntityIterator<'tok, 'brand, 'arena, T> { fn next_back(&mut self) -> Option { - let mut range = self.0.as_mut()?; + let range = self.0.as_mut()?; let ret = range.1; if range.0 == range.1 { @@ -386,12 +403,6 @@ trait Entity<'brand, 'arena>: Eq + Sized { } } -macro_rules! mklens { - ($token: expr, $($name:ident),*) => { - $( let $name = $name.lens($token); )* - }; -} - macro_rules! entity { ($name:ident : $T:ident, $arg_name:ident: $arg_ty:ty @@ -401,166 +412,165 @@ macro_rules! entity { $([ $list_singular:ident : $list_name:ident $($list_back:ident)? ])? : $field_ty:ident ),* )? - ) => { - paste! { - pub struct $T<'brand, 'arena, V> { - id: Option, - next: Option, - prev: Option, - $($($init_field: $init_ty,)*)? - $($($field: Option,)*)? - } + ) => { paste! { + pub struct $T<'brand, 'arena, V> { + id: Option, + next: Option, + prev: Option, + $($($init_field: $init_ty,)*)? + $($($field: Option,)*)? + } - impl<'brand, 'arena, V> Entity<'brand, 'arena> for $T<'brand, 'arena, V> { - type Init = $arg_ty; + impl<'brand, 'arena, V> Entity<'brand, 'arena> for $T<'brand, 'arena, V> { + type Init = $arg_ty; - fn new(id: usize, $arg_name: $arg_ty) -> Self { - Self { - id: Some(id), - prev: None, - next: None, - $($($init_field: $init_expr,)*)? - $($($field: None,)*)? - } + fn new(id: usize, $arg_name: $arg_ty) -> Self { + Self { + id: Some(id), + prev: None, + next: None, + $($($init_field: $init_expr,)*)? + $($($field: None,)*)? } + } - fn clear(&mut self) { - self.id = None; - #[cfg(debug_assertions)] - { - self.prev = None; - self.next = None; - $($(self.$field = None;)*)? - } + fn clear(&mut self) { + self.id = None; + #[cfg(debug_assertions)] + { + self.prev = None; + self.next = None; + $($(self.$field = None;)*)? } + } - fn type_name() -> &'static str { - stringify!($T) - } + fn type_name() -> &'static str { + stringify!($T) + } - fn maybe_id(&self) -> Option { - self.id - } + fn maybe_id(&self) -> Option { + self.id + } - fn maybe_next(&self) -> Option { - self.next - } + fn maybe_next(&self) -> Option { + self.next + } - fn set_next_opt(&mut self, x: Option) { - self.next = x; - } + fn set_next_opt(&mut self, x: Option) { + self.next = x; + } - fn maybe_prev(&self) -> Option { - self.prev - } + fn maybe_prev(&self) -> Option { + self.prev + } - fn set_prev_opt(&mut self, x: Option) { - self.prev = x; - } + fn set_prev_opt(&mut self, x: Option) { + self.prev = x; } + } - impl<'brand, 'arena, V> ptr!($T) { - $($( - $field_vis fn $field(self, token: &impl ReflAsRef>) -> ptr!($field_ty) { - self.[](token).unwrap() - } + #[allow(unused)] + impl<'brand, 'arena, V> ptr!($T) { + $($( + $field_vis fn $field(self, token: &impl ReflAsRef>) -> ptr!($field_ty) { + self.[](token).unwrap() + } + fn [](self, token: &impl ReflAsRef>) -> Option { + self.borrow(token).$field + } - fn [](self, token: &impl ReflAsRef>) -> Option { - self.borrow(token).$field - } + fn [](self, token: &mut impl ReflAsMut>, x: ptr!($field_ty)) { + self.[](token, Some(x)); + } + fn [](self, token: &mut impl ReflAsMut>, x: Option) { + self.borrow_mut(token).$field = x; + } - fn [](self, token: &mut impl ReflAsMut>, x: ptr!($field_ty)) { - self.[](token, Some(x)); + $( + pub fn []<'tok>( + self, + token: &'tok impl ReflAsRef>, + ) -> EntityIterator<'tok, 'brand, 'arena, $field_ty<'brand, 'arena, V>> + { + EntityIterator::new(self.[](token), token) } - fn [](self, token: &mut impl ReflAsMut>, x: Option) { - self.borrow_mut(token).$field = x; + fn []( + self, + token: &mut impl ReflAsMut>, + x: ptr!($field_ty), + ) { + let list = Entity::list_add(x, self.[](token), token); + self.[](token, list); + + $( + let [<_ $list_back>] = (); + x.[](token, self); + )? } - $( - pub fn []<'tok>( - self, - token: &'tok impl ReflAsRef>, - ) -> EntityIterator<'tok, 'brand, 'arena, $field_ty<'brand, 'arena, V>> - { - EntityIterator::new(token, self.[](token)) - } - - fn []( - self, - token: &mut impl ReflAsMut>, - x: ptr!($field_ty), - ) { - let list = Entity::list_add(x, self.[](token), token); - self.[](token, list); - - $( - let [<_ $list_back>] = (); - x.[](token, self); - )? - } - - fn []( - self, - dcel: &mut Dcel<'brand, 'arena, V>, - init: <$field_ty<'brand, 'arena, V> as Entity<'brand, 'arena>>::Init, - ) -> own!($field_ty) { - let x = dcel.$list_name.alloc(&mut dcel.token, init); - self.[](dcel, *x); - x - } - )? - )*)? - } + fn []( + self, + dcel: &mut Dcel<'brand, 'arena, V>, + init: <$field_ty<'brand, 'arena, V> as Entity<'brand, 'arena>>::Init, + ) -> own!($field_ty) { + let x = dcel.$list_name.alloc(&mut dcel.token, init); + self.[](dcel, *x); + x + } + )? + )*)? + } - impl<'tok, 'brand, 'arena, V: Debug> Debug for lens!($T) { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.debug_struct(stringify!($T)) - .field("id", &self.id()) - .field("prev", &short_debug_fn(self.prev())) - .field("next", &short_debug_fn(self.next())) - $($( - .field(stringify!($field), &DebugFn(|f| self.[](f))) - )*)? - $($( - .field(stringify!($init_field), &DebugFn(|f| self.[](f))) - )*)? - .finish() + #[allow(unused)] + impl<'tok, 'brand, 'arena, V> lens!($T) { + $($( + $field_vis fn $field(self) -> lens!($field_ty) { + self.item.$field(&self).lens(self.token) } - } - impl<'tok, 'brand, 'arena, V> lens!($T) { - $($( - $field_vis fn $field(self) -> lens!($field_ty) { - self.item.$field(&self).lens(self.token) - } + fn [](self) -> Option { + self.item.[](&self).map(|x| x.lens(self.token)) + } - fn [](self) -> Option { - self.item.[](&self).map(|x| x.lens(self.token)) + $( + pub fn [](self) -> EntityIterator<'tok, 'brand, 'arena, $field_ty<'brand, 'arena, V>> { + let [<_ $list_singular>] = (); + self.item.[](self.token) } + )? - $( - pub fn [](self) -> EntityIterator<'tok, 'brand, 'arena, $field_ty<'brand, 'arena, V>> { - let [<_ $list_singular>] = (); - self.item.[](self.token) + fn [](self, f: &mut Formatter) -> fmt::Result { + $({ + let [<_ $list_singular>] = (); + if true { + return short_debug_list(self.[](), f); } - )? - - fn [](self, f: &mut Formatter) -> fmt::Result { - $({ - let [<_ $list_singular>] = (); - if true { - return short_debug_list(self.[](), f); - } - })? - short_debug(self.$field(), f) - } - )*)? + })? + short_debug(self.$field(), f) + } + )*)? + } + + impl<'tok, 'brand, 'arena, V: Debug> Debug for lens!($T) { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.debug_struct(stringify!($T)) + .field("id", &self.id()) + .field("prev", &short_debug_fn(self.prev())) + .field("next", &short_debug_fn(self.next())) + $($( + .field(stringify!($field), &DebugFn(|f| self.[](f))) + )*)? + $($( + .field(stringify!($init_field), &DebugFn(|f| self.[](f))) + )*)? + .finish() } } + #[allow(unused)] impl<'brand, 'arena, V> Own<'brand, 'arena, $T<'brand, 'arena, V>> { fn free(self, dcel: &mut Dcel<'brand, 'arena, V>) { dcel.$name.free(&mut dcel.token, self) @@ -573,56 +583,51 @@ macro_rules! entity { } } impl<'brand, 'arena, V> Eq for $T<'brand, 'arena, V> {} - }; + }}; } -struct Allocator<'brand, 'arena, T: Entity<'brand, 'arena>> { - next_id: usize, - arena: &'arena Arena, - freelist: Vec, +entity!(vertex: Vertex, + init: V, + data: V = init; + outgoing: HalfEdge +); + +pub struct OutgoingIterator<'tok, 'brand, 'arena, V>(Option<(lens!(HalfEdge), lens!(HalfEdge))>); + +impl<'tok, 'brand, 'arena, V> Clone for OutgoingIterator<'tok, 'brand, 'arena, V> { + fn clone(&self) -> Self { + Self(self.0) + } } -impl<'brand, 'arena, T: Entity<'brand, 'arena>> Allocator<'brand, 'arena, T> { - fn new(arena: &'arena Arena) -> Self { - Self { - next_id: 0, - arena, - freelist: Vec::new(), - } +impl<'tok, 'brand, 'arena, V> Copy for OutgoingIterator<'tok, 'brand, 'arena, V> {} + +impl<'tok, 'brand, 'arena, V> OutgoingIterator<'tok, 'brand, 'arena, V> { + fn new(start: Option, token: &'tok impl ReflAsRef>) -> Self { + Self(start.map(|s| { + let l = Lens::new(s, token); + (l, l) + })) } +} - fn alloc( - &mut self, - token: &mut impl ReflAsMut>, - init: T::Init, - ) -> own_t!(T) { - let id = self.next_id; - self.next_id += 1; +impl<'tok, 'brand, 'arena, V> Iterator for OutgoingIterator<'tok, 'brand, 'arena, V> { + type Item = lens!(HalfEdge); - let t = Entity::new(id, init); + fn next(&mut self) -> Option { + let range = self.0.as_mut()?; + let ret = range.0; - if let Some(ptr) = self.freelist.pop() { - *ptr.borrow_mut(token) = t; - ptr - } else { - Own::unsafe_make_owned(Ptr(GhostCell::from_mut(self.arena.alloc(t)))) + range.0 = range.0.twin().next(); + if range.0 == range.1 { + self.0 = None; } - } - fn free(&mut self, token: &mut impl ReflAsMut>, ptr: own_t!(T)) { - debug_assert!(ptr.alive(token), "double free"); - ptr.clear(token); - self.freelist.push(ptr); + Some(ret) } } -entity!(vertex: Vertex, - init: V, - data: V = init; - outgoing: HalfEdge -); - -impl<'brand, 'arena, V: Debug> ptr!(Vertex) { +impl<'brand, 'arena, V> ptr!(Vertex) { pub fn data<'tok, 'out>(self, token: &'tok impl ReflAsRef>) -> &'out V where 'arena: 'out, @@ -641,6 +646,15 @@ impl<'brand, 'arena, V: Debug> ptr!(Vertex) { { &mut self.borrow_mut(token).data } + + pub fn iter_outgoing<'tok>( + self, + token: &'tok impl ReflAsRef>, + ) -> OutgoingIterator<'tok, 'brand, 'arena, V> { + // FIXME: maybe enforce at least one item by using .outgoing() + // there should be no "standalone" vertices (?) + OutgoingIterator::new(self.maybe_outgoing(token), token) + } } impl<'tok, 'brand, 'arena, V: Debug> lens!(Vertex) { @@ -648,6 +662,10 @@ impl<'tok, 'brand, 'arena, V: Debug> lens!(Vertex) { self.item.data(self) } + pub fn iter_outgoing(self) -> OutgoingIterator<'tok, 'brand, 'arena, V> { + self.item.iter_outgoing(self.token) + } + fn debug_data(self, f: &mut Formatter) -> fmt::Result { self.data().fmt(f) } @@ -655,7 +673,7 @@ impl<'tok, 'brand, 'arena, V: Debug> lens!(Vertex) { // TODO: target entity!(half_edge: HalfEdge, - init: (); + _init: (); pub origin: Vertex, pub twin: HalfEdge, pub loop_: Loop, @@ -675,13 +693,13 @@ impl<'tok, 'brand, 'arena, V> lens!(HalfEdge) { } entity!(loop_: Loop, - init: (); + _init: (); half_edges[half_edge: half_edge back]: HalfEdge, pub face: Face ); entity!(edge: Edge, - init: (), + _init: (), half_edges: Option<[own!(HalfEdge); 2]> = None ); @@ -711,14 +729,14 @@ impl<'tok, 'brand, 'arena, V> lens!(Edge) { } entity!(face: Face, - init: (); + _init: (); outer_loops[outer_loop: loop_ back]: Loop, inner_loops[inner_loop: loop_ back]: Loop, pub shell: Shell ); entity!(shell: Shell, - init: (); + _init: (); faces[face: face back]: Face, edges[edge: edge]: Edge, vertices[vertex: vertex]: Vertex, @@ -726,10 +744,50 @@ entity!(shell: Shell, ); entity!(body: Body, - init: (); + _init: (); shells[shell: shell back]: Shell ); +struct Allocator<'brand, 'arena, T: Entity<'brand, 'arena>> { + next_id: usize, + arena: &'arena Arena, + freelist: Vec, +} + +impl<'brand, 'arena, T: Entity<'brand, 'arena>> Allocator<'brand, 'arena, T> { + fn new(arena: &'arena Arena) -> Self { + Self { + next_id: 0, + arena, + freelist: Vec::new(), + } + } + + fn alloc( + &mut self, + token: &mut impl ReflAsMut>, + init: T::Init, + ) -> own_t!(T) { + let id = self.next_id; + self.next_id += 1; + + let t = Entity::new(id, init); + + if let Some(ptr) = self.freelist.pop() { + *ptr.borrow_mut(token) = t; + ptr + } else { + Own::unsafe_make_owned(Ptr(GhostCell::from_mut(self.arena.alloc(t)))) + } + } + + fn free(&mut self, token: &mut impl ReflAsMut>, ptr: own_t!(T)) { + debug_assert!(ptr.alive(token), "double free"); + ptr.clear(token); + self.freelist.push(ptr); + } +} + pub struct Mevvlfs<'brand, 'arena, V> { pub edge: own!(Edge), pub vertices: [own!(Vertex); 2], -- cgit v1.2.3