diff options
Diffstat (limited to 'src/data')
| -rw-r--r-- | src/data/coarena.rs | 71 | ||||
| -rw-r--r-- | src/data/mod.rs | 2 |
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; |
