diff --git a/agb/src/agb_alloc/block_allocator.rs b/agb/src/agb_alloc/block_allocator.rs index 929174df..14eb4638 100644 --- a/agb/src/agb_alloc/block_allocator.rs +++ b/agb/src/agb_alloc/block_allocator.rs @@ -10,9 +10,9 @@ use core::convert::TryInto; use core::ptr::NonNull; use crate::interrupt::free; -use bare_metal::{CriticalSection, Mutex}; +use bare_metal::Mutex; -use super::bump_allocator::{BumpAllocator, StartEnd}; +use super::bump_allocator::{BumpAllocatorInner, StartEnd}; use super::SendNonNull; struct Block { @@ -37,170 +37,309 @@ impl Block { .expect("too large allocation") .pad_to_align() } + + pub fn layout() -> Layout { + Layout::new::().align_to(8).unwrap().pad_to_align() + } } struct BlockAllocatorState { first_free_block: Option>, } +struct BlockAllocatorInner { + inner_allocator: BumpAllocatorInner, + state: BlockAllocatorState, +} + pub struct BlockAllocator { - inner_allocator: BumpAllocator, - state: Mutex>, + inner: Mutex>, } impl BlockAllocator { pub(crate) const unsafe fn new(start: StartEnd) -> Self { Self { - inner_allocator: BumpAllocator::new(start), - state: Mutex::new(RefCell::new(BlockAllocatorState { - first_free_block: None, - })), + inner: Mutex::new(RefCell::new(BlockAllocatorInner::new(start))), } } #[doc(hidden)] #[cfg(any(test, feature = "testing"))] pub unsafe fn number_of_blocks(&self) -> u32 { - free(|key| { - let mut state = self.state.borrow(key).borrow_mut(); - - let mut count = 0; - - let mut list_ptr = &mut state.first_free_block; - while let Some(mut current) = list_ptr { - count += 1; - list_ptr = &mut current.as_mut().next; - } - - count - }) - } - - /// Requests a brand new block from the inner bump allocator - fn new_block(&self, layout: Layout, cs: CriticalSection) -> Option> { - let overall_layout = Block::either_layout(layout); - self.inner_allocator.alloc_critical(overall_layout, cs) - } - - /// Merges blocks together to create a normalised list - unsafe fn normalise(&self) { - free(|key| { - let mut state = self.state.borrow(key).borrow_mut(); - - let mut list_ptr = &mut state.first_free_block; - - while let Some(mut current) = list_ptr { - if let Some(next_elem) = current.as_mut().next { - let difference = next_elem - .as_ptr() - .cast::() - .offset_from(current.as_ptr().cast::()); - let usize_difference: usize = difference - .try_into() - .expect("distances in alloc'd blocks must be positive"); - - if usize_difference == current.as_mut().size { - let current = current.as_mut(); - let next = next_elem.as_ref(); - - current.size += next.size; - current.next = next.next; - continue; - } - } - list_ptr = &mut current.as_mut().next; - } - }); + free(|key| self.inner.borrow(key).borrow_mut().number_of_blocks()) } pub unsafe fn alloc(&self, layout: Layout) -> Option> { - // find a block that this current request fits in - let full_layout = Block::either_layout(layout); - - let (block_after_layout, block_after_layout_offset) = full_layout - .extend(Layout::new::().align_to(8).unwrap().pad_to_align()) - .unwrap(); - - free(|key| { - let mut state = self.state.borrow(key).borrow_mut(); - let mut current_block = state.first_free_block; - let mut list_ptr = &mut state.first_free_block; - // This iterates the free list until it either finds a block that - // is the exact size requested or a block that can be split into - // one with the desired size and another block header. - while let Some(mut current) = current_block { - let block_to_examine = current.as_mut(); - if block_to_examine.size == full_layout.size() { - *list_ptr = block_to_examine.next; - return Some(current.cast()); - } else if block_to_examine.size >= block_after_layout.size() { - // can split block - let split_block = Block { - size: block_to_examine.size - block_after_layout_offset, - next: block_to_examine.next, - }; - let split_ptr = current - .as_ptr() - .cast::() - .add(block_after_layout_offset) - .cast(); - *split_ptr = split_block; - *list_ptr = NonNull::new(split_ptr).map(SendNonNull); - - return Some(current.cast()); - } - current_block = block_to_examine.next; - list_ptr = &mut block_to_examine.next; - } - - self.new_block(layout, key) - }) + free(|key| self.inner.borrow(key).borrow_mut().alloc(layout)) } pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + free(|key| self.inner.borrow(key).borrow_mut().dealloc(ptr, layout)); + } + + pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { + free(|key| { + self.inner + .borrow(key) + .borrow_mut() + .dealloc_no_normalise(ptr, layout); + }); + } + + pub unsafe fn grow( + &self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout, + ) -> Option> { + free(|key| { + self.inner + .borrow(key) + .borrow_mut() + .grow(ptr, layout, new_layout) + }) + } +} + +impl BlockAllocatorInner { + pub(crate) const unsafe fn new(start: StartEnd) -> Self { + Self { + inner_allocator: BumpAllocatorInner::new(start), + state: BlockAllocatorState { + first_free_block: None, + }, + } + } + + #[doc(hidden)] + #[cfg(any(test, feature = "testing"))] + pub unsafe fn number_of_blocks(&mut self) -> u32 { + let mut count = 0; + + let mut list_ptr = &mut self.state.first_free_block; + while let Some(mut current) = list_ptr { + count += 1; + list_ptr = &mut current.as_mut().next; + } + + count + } + + /// Requests a brand new block from the inner bump allocator + fn new_block(&mut self, layout: Layout) -> Option> { + let overall_layout = Block::either_layout(layout); + self.inner_allocator.alloc(overall_layout) + } + + /// Merges blocks together to create a normalised list + unsafe fn normalise(&mut self) { + let mut list_ptr = &mut self.state.first_free_block; + + while let Some(mut current) = list_ptr { + if let Some(next_elem) = current.as_mut().next { + let difference = next_elem + .as_ptr() + .cast::() + .offset_from(current.as_ptr().cast::()); + let usize_difference: usize = difference + .try_into() + .expect("distances in alloc'd blocks must be positive"); + + if usize_difference == current.as_mut().size { + let current = current.as_mut(); + let next = next_elem.as_ref(); + + current.size += next.size; + current.next = next.next; + continue; + } + } + list_ptr = &mut current.as_mut().next; + } + } + + pub unsafe fn alloc(&mut self, layout: Layout) -> Option> { + // find a block that this current request fits in + let full_layout = Block::either_layout(layout); + + let mut list_ptr = &mut self.state.first_free_block; + // This iterates the free list until it either finds a block that + // is the exact size requested or a block that can be split into + // one with the desired size and another block header. + loop { + match list_ptr { + Some(mut current_block) => { + if let Some(alloc) = Self::allocate_into_block(list_ptr, full_layout) { + return Some(alloc); + } + list_ptr = &mut current_block.as_mut().next; + } + None => return self.new_block(layout), + } + } + } + + /// splits a block in twain + unsafe fn allocate_into_block( + reference_to_block_pointer: &mut Option>, + wanted_layout: Layout, + ) -> Option> { + let (extended_layout, offset) = wanted_layout.extend(Block::layout()).unwrap(); + + let mut examination_block_ptr = reference_to_block_pointer.unwrap().0; + let examination_block = examination_block_ptr.as_mut(); + + if examination_block.size == wanted_layout.size() { + *reference_to_block_pointer = examination_block.next; + Some(examination_block_ptr.cast()) + } else if examination_block.size >= extended_layout.size() { + let split_block = Block { + size: examination_block.size - offset, + next: examination_block.next, + }; + + let split_block_ptr = examination_block_ptr + .as_ptr() + .cast::() + .add(offset) + .cast(); + *split_block_ptr = split_block; + *reference_to_block_pointer = NonNull::new(split_block_ptr).map(SendNonNull); + + Some(examination_block_ptr.cast()) + } else { + None + } + } + + pub unsafe fn grow( + &mut self, + ptr: *mut u8, + initial_layout: Layout, + desired_layout: Layout, + ) -> Option> { + let either_layout_initial = Block::either_layout(initial_layout); + let either_layout_desired = Block::either_layout(desired_layout); + + let difference = Layout::from_size_align( + either_layout_desired.size() - either_layout_initial.size(), + either_layout_initial.align(), + ) + .expect("should be able to construct difference layout"); + + if self.is_block_at_end(ptr, either_layout_initial) { + let _additional_space = self.inner_allocator.alloc(difference); + return NonNull::new(ptr); + } + + // cases + // * Our block has no free block after it. + // * Our block has a free block after that we fit in. + // * Our block has a free block after that is too small. + // * UNIMPLEMENTED Out block has a free block after that is too small but that is at the end so we can bump allocate some more space. + + let next_block = self.find_first_block_after(ptr); + + if let Some(list_to_block) = next_block { + let is_block_directly_after = { + if let Some(block) = list_to_block { + block.0.as_ptr() == ptr.add(either_layout_initial.size()).cast() + } else { + false + } + }; + + if is_block_directly_after { + if let Some(_split) = Self::allocate_into_block(list_to_block, difference) { + return NonNull::new(ptr); + } + } + } + + self.grow_copy(ptr, either_layout_initial, either_layout_desired) + } + + unsafe fn grow_copy( + &mut self, + ptr: *mut u8, + initial_layout: Layout, + desired_layout: Layout, + ) -> Option> { + let new_ptr = self.alloc(desired_layout)?; + + core::ptr::copy_nonoverlapping(ptr, new_ptr.as_ptr(), initial_layout.size()); + self.dealloc(ptr, initial_layout); + + Some(new_ptr) + } + + unsafe fn is_block_at_end(&self, ptr: *mut u8, total_layout: Layout) -> bool { + self.inner_allocator.tip() == NonNull::new(ptr.add(total_layout.size())) + } + + pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { self.dealloc_no_normalise(ptr, layout); self.normalise(); } - pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { - let new_layout = Block::either_layout(layout).pad_to_align(); - free(|key| { - let mut state = self.state.borrow(key).borrow_mut(); + /// Returns a reference to the pointer to the next block + /// Useful because you can modify what points to the block and access the block + unsafe fn find_first_block_after( + &mut self, + ptr: *mut u8, + ) -> Option<&mut Option>> { + let mut list_ptr = &mut self.state.first_free_block; - // note that this is a reference to a pointer - let mut list_ptr = &mut state.first_free_block; - - // This searches the free list until it finds a block further along - // than the block that is being freed. The newly freed block is then - // inserted before this block. If the end of the list is reached - // then the block is placed at the end with no new block after it. - loop { - match list_ptr { - Some(mut current_block) => { - if current_block.as_ptr().cast() > ptr { - let new_block_content = Block { - size: new_layout.size(), - next: Some(current_block), - }; - *ptr.cast() = new_block_content; - *list_ptr = NonNull::new(ptr.cast()).map(SendNonNull); - break; - } - list_ptr = &mut current_block.as_mut().next; + loop { + match list_ptr { + Some(mut current_block) => { + if current_block.as_ptr().cast() > ptr { + return Some(list_ptr); } - None => { - // reached the end of the list without finding a place to insert the value + + list_ptr = &mut current_block.as_mut().next; + } + None => return None, + } + } + } + + pub unsafe fn dealloc_no_normalise(&mut self, ptr: *mut u8, layout: Layout) { + let new_layout = Block::either_layout(layout).pad_to_align(); + + // note that this is a reference to a pointer + let mut list_ptr = &mut self.state.first_free_block; + + // This searches the free list until it finds a block further along + // than the block that is being freed. The newly freed block is then + // inserted before this block. If the end of the list is reached + // then the block is placed at the end with no new block after it. + loop { + match list_ptr { + Some(mut current_block) => { + if current_block.as_ptr().cast() > ptr { let new_block_content = Block { size: new_layout.size(), - next: None, + next: Some(current_block), }; *ptr.cast() = new_block_content; *list_ptr = NonNull::new(ptr.cast()).map(SendNonNull); break; } + list_ptr = &mut current_block.as_mut().next; + } + None => { + // reached the end of the list without finding a place to insert the value + let new_block_content = Block { + size: new_layout.size(), + next: None, + }; + *ptr.cast() = new_block_content; + *list_ptr = NonNull::new(ptr.cast()).map(SendNonNull); + break; } } - }); + } } } @@ -215,6 +354,24 @@ unsafe impl GlobalAlloc for BlockAllocator { unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { self.dealloc(ptr, layout); } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + + if new_size > layout.size() { + return match self.grow(ptr, layout, new_layout) { + Some(p) => p.as_ptr(), + None => core::ptr::null_mut(), + }; + } + + let new_ptr = GlobalAlloc::alloc(self, new_layout); + if !new_ptr.is_null() { + core::ptr::copy_nonoverlapping(ptr, new_ptr, core::cmp::min(layout.size(), new_size)); + self.dealloc(ptr, layout); + } + new_ptr + } } unsafe impl Allocator for BlockAllocator { @@ -230,6 +387,42 @@ unsafe impl Allocator for BlockAllocator { } } + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, core::alloc::AllocError> { + match self.grow(ptr.as_ptr(), old_layout, new_layout) { + Some(p) => Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( + p.as_ptr(), + new_layout.size(), + ))), + None => Err(core::alloc::AllocError), + } + } + + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, core::alloc::AllocError> { + let new_ptr = self + .grow(ptr.as_ptr(), old_layout, new_layout) + .ok_or(core::alloc::AllocError)?; + + new_ptr + .as_ptr() + .add(old_layout.size()) + .write_bytes(0, new_layout.size() - old_layout.size()); + + Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( + new_ptr.as_ptr(), + new_layout.size(), + ))) + } + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { self.dealloc(ptr.as_ptr(), layout); } diff --git a/agb/src/agb_alloc/bump_allocator.rs b/agb/src/agb_alloc/bump_allocator.rs index 0ea27d2d..2c154d48 100644 --- a/agb/src/agb_alloc/bump_allocator.rs +++ b/agb/src/agb_alloc/bump_allocator.rs @@ -4,35 +4,41 @@ use core::ptr::NonNull; use super::SendNonNull; use crate::interrupt::free; -use bare_metal::{CriticalSection, Mutex}; +use bare_metal::Mutex; pub(crate) struct StartEnd { pub start: fn() -> usize, pub end: fn() -> usize, } -pub(crate) struct BumpAllocator { - current_ptr: Mutex>>>, - start_end: Mutex, +pub(crate) struct BumpAllocatorInner { + current_ptr: Option>, + start_end: StartEnd, } -impl BumpAllocator { +pub(crate) struct BumpAllocator { + inner: Mutex>, +} + +impl BumpAllocatorInner { pub const fn new(start_end: StartEnd) -> Self { Self { - current_ptr: Mutex::new(RefCell::new(None)), - start_end: Mutex::new(start_end), + current_ptr: None, + start_end, } } -} -impl BumpAllocator { - pub fn alloc_critical(&self, layout: Layout, cs: CriticalSection) -> Option> { - let mut current_ptr = self.current_ptr.borrow(cs).borrow_mut(); + pub fn tip(&self) -> Option> { + self.current_ptr.map(|x| x.0) + } + + pub fn alloc(&mut self, layout: Layout) -> Option> { + let current_ptr = &mut self.current_ptr; let ptr = if let Some(c) = *current_ptr { c.as_ptr() as usize } else { - (self.start_end.borrow(cs).start)() + (self.start_end.start)() }; let alignment_bitmask = layout.align() - 1; @@ -43,7 +49,7 @@ impl BumpAllocator { let resulting_ptr = ptr + amount_to_add; let new_current_ptr = resulting_ptr + layout.size(); - if new_current_ptr >= (self.start_end.borrow(cs).end)() { + if new_current_ptr >= (self.start_end.end)() { return None; } @@ -51,8 +57,11 @@ impl BumpAllocator { NonNull::new(resulting_ptr as *mut _) } - pub fn alloc_safe(&self, layout: Layout) -> Option> { - free(|key| self.alloc_critical(layout, key)) +} + +impl BumpAllocator { + fn alloc_safe(&self, layout: Layout) -> Option> { + free(|key| self.inner.borrow(key).borrow_mut().alloc(layout)) } } diff --git a/agb/src/agb_alloc/mod.rs b/agb/src/agb_alloc/mod.rs index 53e429b0..5cff31e5 100644 --- a/agb/src/agb_alloc/mod.rs +++ b/agb/src/agb_alloc/mod.rs @@ -292,4 +292,18 @@ mod test { } } } + + #[test_case] + fn growth_works(_gba: &mut crate::Gba) { + let mut growing_vector = Vec::with_capacity(1); + + for i in 0..1000 { + growing_vector.push(i); + growing_vector.reserve_exact(i + 2); + + for (idx, elem) in growing_vector.iter().enumerate() { + assert_eq!(idx, *elem); + } + } + } } diff --git a/examples/hyperspace-roll/Cargo.lock b/examples/hyperspace-roll/Cargo.lock index cb6ec5e9..da95b861 100644 --- a/examples/hyperspace-roll/Cargo.lock +++ b/examples/hyperspace-roll/Cargo.lock @@ -176,7 +176,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", "ttf-parser", ] @@ -200,6 +200,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hound" version = "3.5.0" @@ -211,7 +217,6 @@ name = "hyperspace-roll" version = "0.1.0" dependencies = [ "agb", - "bare-metal", ] [[package]] @@ -229,6 +234,16 @@ dependencies = [ "png", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "libc" version = "0.2.140" @@ -244,6 +259,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -392,6 +413,15 @@ dependencies = [ "syn 2.0.8", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -422,11 +452,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -452,3 +507,12 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] diff --git a/examples/the-hat-chooses-the-wizard/Cargo.lock b/examples/the-hat-chooses-the-wizard/Cargo.lock index eb0098c0..44a85826 100644 --- a/examples/the-hat-chooses-the-wizard/Cargo.lock +++ b/examples/the-hat-chooses-the-wizard/Cargo.lock @@ -176,7 +176,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", "ttf-parser", ] @@ -200,6 +200,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hound" version = "3.5.0" @@ -221,6 +227,16 @@ dependencies = [ "png", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "itoa" version = "1.0.6" @@ -242,6 +258,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -407,6 +429,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -446,11 +477,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -476,3 +532,12 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] diff --git a/examples/the-purple-night/Cargo.lock b/examples/the-purple-night/Cargo.lock index dc5b0e60..47cd52a5 100644 --- a/examples/the-purple-night/Cargo.lock +++ b/examples/the-purple-night/Cargo.lock @@ -191,7 +191,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", "ttf-parser", ] @@ -224,6 +224,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hound" version = "3.5.0" @@ -245,6 +251,16 @@ dependencies = [ "png", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "libc" version = "0.2.140" @@ -272,6 +288,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -426,6 +448,15 @@ dependencies = [ "syn 2.0.8", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -483,11 +514,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -514,6 +570,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] + [[package]] name = "xml-rs" version = "0.8.4"