diff --git a/Cargo.toml b/Cargo.toml index 03ba166..8211886 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ comet_resources = { path = "./crates/comet_resources", workspace = true } comet_ecs = { path = "./crates/comet_ecs", workspace = true } comet_input = { path = "./crates/comet_input", workspace = true } comet_log = { path = "./crates/comet_log", workspace = true } +comet_structs = { path = "./crates/comet_structs", workspace = true } cfg-if = "1" anyhow = "1.0" @@ -49,7 +50,8 @@ members = [ "./crates/comet_log", "./crates/comet_ui", "./crates/comet_fonts", - "./crates/comet_sound" + "./crates/comet_sound", + "./crates/comet_structs" ] [workspace.dependencies] @@ -61,3 +63,4 @@ comet_resources = { path = "./crates/comet_resources", workspace = true } comet_ecs = { path = "./crates/comet_ecs", workspace = true } comet_input = { path = "./crates/comet_input", workspace = true } comet_log = { path = "./crates/comet_log", workspace = true } +comet_structs = { path = "./crates/comet_structs", workspace = true } \ No newline at end of file diff --git a/build.rs b/build.rs index 71683f3..0cd0571 100644 --- a/build.rs +++ b/build.rs @@ -3,6 +3,7 @@ use fs_extra::copy_items; use fs_extra::dir::CopyOptions; use std::env; + fn main() -> Result<()> { // This tells cargo to rerun this script if something in /resources/ changes. println!("cargo:rerun-if-changed=resources/materials/*"); @@ -26,4 +27,4 @@ fn main() -> Result<()> { copy_items(&paths_to_copy, out_dir, ©_options)?; Ok(()) -} \ No newline at end of file +} diff --git a/comet_structs/Cargo.toml b/comet_structs/Cargo.toml deleted file mode 100644 index 16c508b..0000000 --- a/comet_structs/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "comet_structs" -version = "0.1.0" -edition = "2024" - -[dependencies] diff --git a/comet_structs/src/column.rs b/comet_structs/src/column.rs deleted file mode 100644 index d465491..0000000 --- a/comet_structs/src/column.rs +++ /dev/null @@ -1,304 +0,0 @@ -use crate::{Component}; -use std::{ - alloc::{ - handle_alloc_error, - Layout - }, - any::TypeId, - collections::{ - HashMap, - HashSet - }, - hash::{ - DefaultHasher, - Hash, - Hasher - }, - mem::MaybeUninit, - ptr::NonNull -}; -use std::ptr; - -#[derive(Debug, Clone)] -pub struct BlobVec { - item_layout: Layout, - capacity: usize, - len: usize, - data: NonNull, - swap_scratch: NonNull, - drop: unsafe fn(*mut u8) -} - - -impl BlobVec { - pub fn new(item_layout: Layout, drop: unsafe fn(*mut u8), capacity: usize) -> Self { - if item_layout.size() == 0 { - BlobVec { - swap_scratch: NonNull::dangling(), - data: NonNull::dangling(), - capacity: usize:: MAX, - len: 0, - item_layout, - drop, - } - } - else { - let swap_scratch = NonNull::new(unsafe { std::alloc::alloc(item_layout) }) - .unwrap_or_else(|| handle_alloc_error(item_layout)); - - let mut blob_vec = BlobVec { - swap_scratch, - data: NonNull::dangling(), - capacity: 0, - len: 0, - item_layout, - drop, - }; - blob_vec.reserve_exact(capacity); - blob_vec - } - } - - pub fn reserve_exact(&mut self, additional: usize) { - let available_space = self.capacity - self.len; - if available_space < additional { - self.grow_exact(additional - available_space); - } - } - - fn grow_exact(&mut self, increment: usize) { - debug_assert!(self.item_layout.size() != 0); - - let new_capacity = self.capacity + increment; - let new_layout = - array_layout(&self.item_layout, new_capacity).expect("array layout should be valid"); - unsafe { - let new_data = if self.capacity == 0 { - std::alloc::alloc(new_layout) - } else { - std::alloc::realloc( - self.get_ptr().as_ptr(), - array_layout(&self.item_layout, self.capacity) - .expect("array layout should be valid"), - new_layout.size(), - ) - }; - - self.data = NonNull::new(new_data).unwrap_or_else(|| handle_alloc_error(new_layout)); - } - self.capacity = new_capacity; - } - - - #[inline] - pub fn len(&self) -> usize { - self.len - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.len == 0 - } - - #[inline] - pub fn capacity(&self) -> usize { - self.capacity - } - - - #[inline] - pub unsafe fn get_ptr(&self) -> NonNull { - self.data - } - - #[inline] - pub unsafe fn push_uninit(&mut self) -> usize { - self.reserve_exact(1); - let index = self.len; - self.len += 1; - index - } - - #[inline] - pub unsafe fn get_unchecked(&self, index: usize) -> *mut u8 { - debug_assert!(index < self.len()); - self.get_ptr().as_ptr().add(index * self.item_layout.size()) - } - - #[inline] - pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> *mut u8 { - debug_assert!(index < self.len()); - self.get_ptr().as_ptr().add(index * self.item_layout.size()) - } - - pub unsafe fn push_element(&mut self, element: T) { - let index = self.push_uninit(); - let ptr = self.get_unchecked(index) as *mut T; - ptr::write(ptr,element); - } - - pub fn clear(&mut self) { - let len = self.len; - // We set len to 0 _before_ dropping elements for unwind safety. This ensures we don't - // accidentally drop elements twice in the event of a drop impl panicking. - self.len = 0; - for i in 0..len { - unsafe { - // NOTE: this doesn't use self.get_unchecked(i) because the debug_assert on index - // will panic here due to self.len being set to 0 - let ptr = self.get_ptr().as_ptr().add(i * self.item_layout.size()); - (self.drop)(ptr); - } - } - } - - #[inline] - pub unsafe fn swap_remove_and_forget_unchecked(&mut self, index: usize) -> *mut u8 { - debug_assert!(index < self.len()); - let last = self.len - 1; - let swap_scratch = self.swap_scratch.as_ptr(); - ptr::copy_nonoverlapping( - self.get_unchecked(index), - swap_scratch, - self.item_layout.size(), - ); - ptr::copy( - self.get_unchecked(last), - self.get_unchecked(index), - self.item_layout.size(), - ); - self.len -= 1; - swap_scratch - } - - #[inline] - pub unsafe fn initialize_unchecked(&mut self, index: usize, value: *mut u8) { - debug_assert!(index < self.len()); - let ptr = self.get_unchecked(index); - ptr::copy_nonoverlapping(value, ptr, self.item_layout.size()); - } -} - -impl Drop for BlobVec { - fn drop(&mut self) { - self.clear(); - let array_layout = - array_layout(&self.item_layout, self.capacity).expect("array layout should be valid"); - if array_layout.size() > 0 { - unsafe { - std::alloc::dealloc(self.get_ptr().as_ptr(), array_layout); - std::alloc::dealloc(self.swap_scratch.as_ptr(), self.item_layout); - } - } - } -} - -unsafe impl Send for BlobVec {} -unsafe impl Sync for BlobVec {} - -fn array_layout(layout: &Layout, n: usize) -> Option { - let (array_layout, offset) = repeat_layout(layout, n)?; - debug_assert_eq!(layout.size(), offset); - Some(array_layout) -} - -fn repeat_layout(layout: &Layout, n: usize) -> Option<(Layout, usize)> { - let padded_size = layout.size() + padding_needed_for(layout, layout.align()); - let alloc_size = padded_size.checked_mul(n)?; - - unsafe { - Some(( - Layout::from_size_align_unchecked(alloc_size, layout.align()), - padded_size, - )) - } -} - -const fn padding_needed_for(layout: &Layout, align: usize) -> usize { - let len = layout.size(); - let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); - len_rounded_up.wrapping_sub(len) -} - -#[derive(Debug, Clone)] -pub struct Column { - pub data: BlobVec -} - -impl Column { - pub fn new(capacity: usize) -> Self { - let layout = Layout::new::(); - let drop_fn = |ptr: *mut u8| unsafe { - ptr::drop_in_place(ptr as *mut T); - }; - Self { - data: BlobVec::new(layout, drop_fn, capacity), - } - } - - pub fn data(&self) -> BlobVec { - self.data.clone() - } - - pub fn push(&mut self, item: T) { - assert_eq!(TypeId::of::(), TypeId::of::(), "Type mismatch"); - unsafe { - let index = self.data.push_uninit(); - let ptr = self.data.get_unchecked(index); - ptr::write(ptr as *mut T, item); - } - } - - pub fn get(&self, index: usize) -> Option<&T> { - assert_eq!(TypeId::of::(), TypeId::of::(), "Type mismatch"); - if index >= self.data.len() { - return None; - } - unsafe { - let ptr = self.data.get_unchecked(index); - Some(&*(ptr as *const T)) - } - } - - pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { - assert_eq!(TypeId::of::(), TypeId::of::(), "Type mismatch"); - - if index >= self.data.len() { - return None; - } - - // Access the element at the given index - unsafe { - let ptr = self.data.get_unchecked(index); - // Convert the pointer to a mutable reference and return it - Some(&mut *(ptr as *mut T)) - } - } - - pub fn remove(&mut self, index: usize) -> Option { - assert_eq!(TypeId::of::(), TypeId::of::(), "Type mismatch"); - if index >= self.data.len() { - return None; - } - unsafe { - let ptr = self.data.swap_remove_and_forget_unchecked(index); - Some(ptr::read(ptr as *const T)) - } - } - - fn swap(&mut self, index1: usize, index2: usize) { - assert!(index1 < self.data.len() && index2 < self.data.len(), "Index out of bounds"); - - unsafe { - let ptr1 = self.data.get_unchecked(index1); - let ptr2 = self.data.get_unchecked(index2); - - let mut temp = MaybeUninit::::uninit(); - - // Swap the elements at index1 and index2 - ptr::copy_nonoverlapping(ptr1, temp.as_mut_ptr(), self.data.item_layout.size()); - ptr::copy_nonoverlapping(ptr2, ptr1, self.data.item_layout.size()); - ptr::copy_nonoverlapping(temp.as_ptr(), ptr2, self.data.item_layout.size()); - } - } -} diff --git a/crates/comet_ecs/Cargo.toml b/crates/comet_ecs/Cargo.toml index ca6d2f8..e193af2 100644 --- a/crates/comet_ecs/Cargo.toml +++ b/crates/comet_ecs/Cargo.toml @@ -8,6 +8,7 @@ component_derive = { path = "./component_derive" } comet_math = { path = "../comet_math" } comet_resources = { path = "../comet_resources" } comet_log = { path = "../comet_log" } +comet_structs = { path = "../comet_structs" } chrono = "0.4" bit-set = "0.8.0" \ No newline at end of file diff --git a/crates/comet_structs/Cargo.toml b/crates/comet_structs/Cargo.toml index 583448e..45372ea 100644 --- a/crates/comet_structs/Cargo.toml +++ b/crates/comet_structs/Cargo.toml @@ -4,3 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] +comet_log = { path = "../comet_log" } +chrono = "0.4"