aboutsummaryrefslogtreecommitdiff
path: root/src/data
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-11-24 16:54:15 +0100
committerGitHub <noreply@github.com>2020-11-24 16:54:15 +0100
commitbdf2e15fdcff4c4757b4875354b2d6e8b9c6939d (patch)
tree097166c76d92921b269b28a1e115b3cef89d820b /src/data
parentc641114f016c47f6b22acc084610847f88ff5a66 (diff)
parentfcafcac66f1792ea155925e3de5055ef50910fb0 (diff)
downloadrapier-bdf2e15fdcff4c4757b4875354b2d6e8b9c6939d.tar.gz
rapier-bdf2e15fdcff4c4757b4875354b2d6e8b9c6939d.tar.bz2
rapier-bdf2e15fdcff4c4757b4875354b2d6e8b9c6939d.zip
Merge pull request #68 from dimforge/read_contacts
Allow access to contact information
Diffstat (limited to 'src/data')
-rw-r--r--src/data/coarena.rs71
-rw-r--r--src/data/mod.rs2
2 files changed, 73 insertions, 0 deletions
diff --git a/src/data/coarena.rs b/src/data/coarena.rs
new file mode 100644
index 0000000..78cbfa7
--- /dev/null
+++ b/src/data/coarena.rs
@@ -0,0 +1,71 @@
+use crate::data::arena::Index;
+
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone, Debug)]
+/// A container for data associated to item existing into another Arena.
+pub struct Coarena<T> {
+ data: Vec<(u64, T)>,
+}
+
+impl<T> Coarena<T> {
+ /// A coarena with no element.
+ pub fn new() -> Self {
+ Self { data: Vec::new() }
+ }
+
+ /// Gets a specific element from the coarena, if it exists.
+ pub fn get(&self, index: Index) -> Option<&T> {
+ let (i, g) = index.into_raw_parts();
+ self.data
+ .get(i)
+ .and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
+ }
+
+ /// Gets a mutable reference to a specific element from the coarena, if it exists.
+ pub fn get_mut(&mut self, index: Index) -> Option<&mut T> {
+ let (i, g) = index.into_raw_parts();
+ self.data
+ .get_mut(i)
+ .and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
+ }
+
+ /// Ensure that elements at the two given indices exist in this coarena, and return their reference.
+ ///
+ /// Missing elements are created automatically and initialized with the `default` value.
+ pub fn ensure_pair_exists(&mut self, a: Index, b: Index, default: T) -> (&mut T, &mut T)
+ where
+ T: Clone,
+ {
+ let (i1, g1) = a.into_raw_parts();
+ let (i2, g2) = b.into_raw_parts();
+
+ assert_ne!(i1, i2, "Cannot index the same object twice.");
+
+ let (elt1, elt2) = if i1 > i2 {
+ if self.data.len() <= i1 {
+ self.data.resize(i1 + 1, (u32::MAX as u64, default.clone()));
+ }
+
+ let (left, right) = self.data.split_at_mut(i1);
+ (&mut right[0], &mut left[i2])
+ } else {
+ // i2 > i1
+ if self.data.len() <= i2 {
+ self.data.resize(i2 + 1, (u32::MAX as u64, default.clone()));
+ }
+
+ let (left, right) = self.data.split_at_mut(i2);
+ (&mut left[i1], &mut right[0])
+ };
+
+ if elt1.0 != g1 {
+ *elt1 = (g1, default.clone());
+ }
+
+ if elt2.0 != g2 {
+ *elt2 = (g2, default);
+ }
+
+ (&mut elt1.1, &mut elt2.1)
+ }
+}
diff --git a/src/data/mod.rs b/src/data/mod.rs
index 0e0459e..672bf94 100644
--- a/src/data/mod.rs
+++ b/src/data/mod.rs
@@ -1,8 +1,10 @@
//! Data structures modified with guaranteed deterministic behavior after deserialization.
+pub use self::coarena::Coarena;
pub use self::maybe_serializable_data::MaybeSerializableData;
pub mod arena;
+mod coarena;
pub(crate) mod graph;
pub(crate) mod hashmap;
mod maybe_serializable_data;