Moved in sparse set tests

This commit is contained in:
Skye Terran 2022-03-11 10:19:57 -08:00
parent f93fb22699
commit a49d3e6888
4 changed files with 107 additions and 16 deletions

17
.gitignore vendored
View File

@ -1,16 +1 @@
# ---> Rust
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
/target

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ecs"
version = "0.1.0"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "ecs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

91
src/main.rs Normal file
View File

@ -0,0 +1,91 @@
use std::fmt;
// Error type
struct SparseSetError;
#[derive(Debug, Copy, Clone)]
struct DenseItem<T> {
index: usize,
value: T
}
// TODO: Use arrays+slices instead of vecs
#[derive(Debug)]
struct SparseSet<T> {
sparse: Vec<Option<usize>>,
dense: Vec<DenseItem<T>>
}
impl<T> SparseSet<T> {
pub fn new() -> SparseSet<T> {
SparseSet {
sparse: vec![],
dense: vec![]
}
}
// Add an item to the dense vector and record its index in the sparse vector
fn insert(&mut self, value: T) {
let item = DenseItem {
index: self.dense.len(),
value: value
};
self.dense.push(item);
let dense_index = self.dense.len() - 1;
self.sparse.push(Some(dense_index));
}
// Remove an item at the supplied target index from the set
// Replaces the selected target with the last item in the dense vector
fn remove(&mut self, target_sparse_index: usize) -> Result<(), SparseSetError> {
// Find the dense index of the target (need to decide what to do from there)
let target_dense_index = self.sparse[target_sparse_index].unwrap();
// If the target points to the last item in the dense set, this'll be easier
if target_dense_index + 1 == self.dense.len() {
// Remove the target from the dense set
self.dense.pop();
// Overwrite the target's sparse index
self.sparse[target_sparse_index] = None;
} else {
// Get the last item in the dense set as a source to switch with
// Change its index to the target sparse index, as it's replacing the target
let source_item = match self.dense.pop() {
Some(item) => { item },
None => { return Err(SparseSetError) }
};
// Redirect the source item's sparse index to replace the target sparse index
self.sparse[source_item.index] = Some(target_sparse_index);
// Assign the source item to the target's place in the dense set
self.dense[target_dense_index] = source_item;
// Overwrite the target's sparse index
self.sparse[target_dense_index] = None;
}
Ok(())
}
}
fn main() {
let mut test_set: SparseSet<f32> = SparseSet::new();
test_set.insert(69.0);
test_set.insert(420.0);
test_set.insert(9001.0);
println!("{:?}", test_set);
test_set.remove(1);
println!("{:?}", test_set);
// Create a mutable array (contiguous memory!)
let mut array: [Option<DenseItem<f32>>; 8] = [None; 8];
// Create a mutable slice of that whole array
let slice: &[Option<DenseItem<f32>>] = &mut array[..];
for item in slice {
println!("{:?}", item);
}
}