Skip to main content

rapier3d/data/
coarena.rs

1use crate::alloc_prelude::*;
2use crate::data::arena::Index;
3
4#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
5#[derive(Clone, Debug, Default)]
6/// A container for data associated to item existing into another Arena.
7pub struct Coarena<T> {
8    data: Vec<(u32, T)>,
9}
10
11impl<T> Coarena<T> {
12    /// A coarena with no element.
13    pub fn new() -> Self {
14        Self { data: Vec::new() }
15    }
16
17    /// Pre-allocates capacity for `additional` extra elements in this arena.
18    pub fn reserve(&mut self, additional: usize) {
19        self.data.reserve(additional);
20    }
21
22    /// Iterates through all the elements of this coarena.
23    pub fn iter(&self) -> impl Iterator<Item = (Index, &T)> {
24        self.data
25            .iter()
26            .enumerate()
27            .filter(|(_, elt)| elt.0 != u32::MAX)
28            .map(|(i, elt)| (Index::from_raw_parts(i as u32, elt.0), &elt.1))
29    }
30
31    /// Gets a specific element from the coarena without specifying its generation number.
32    ///
33    /// It is strongly encouraged to use `Coarena::get` instead of this method because this method
34    /// can suffer from the ABA problem.
35    pub fn get_unknown_gen(&self, index: u32) -> Option<&T> {
36        self.data.get(index as usize).map(|(_, t)| t)
37    }
38
39    /// Gets a specific mutable element from the coarena without specifying its generation number.
40    ///
41    /// It is strongly encouraged to use `Coarena::get_mut` instead of this method because this method
42    /// can suffer from the ABA problem.
43    pub fn get_mut_unknown_gen(&mut self, index: u32) -> Option<&mut T> {
44        self.data.get_mut(index as usize).map(|(_, t)| t)
45    }
46
47    #[allow(dead_code)]
48    pub(crate) fn get_gen(&self, index: u32) -> Option<u32> {
49        self.data
50            .get(index as usize)
51            .map(|(generation, _)| *generation)
52    }
53
54    /// Deletes an element for the coarena and returns its value.
55    ///
56    /// This method will reset the value to the given `removed_value`.
57    pub fn remove(&mut self, index: Index, removed_value: T) -> Option<T> {
58        let (i, g) = index.into_raw_parts();
59        let data = self.data.get_mut(i as usize)?;
60        if g == data.0 {
61            data.0 = u32::MAX; // invalidate the generation number.
62            Some(core::mem::replace(&mut data.1, removed_value))
63        } else {
64            None
65        }
66    }
67
68    /// Gets a specific element from the coarena, if it exists.
69    pub fn get(&self, index: Index) -> Option<&T> {
70        let (i, g) = index.into_raw_parts();
71        self.data
72            .get(i as usize)
73            .and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
74    }
75
76    /// Gets a mutable reference to a specific element from the coarena, if it exists.
77    pub fn get_mut(&mut self, index: Index) -> Option<&mut T> {
78        let (i, g) = index.into_raw_parts();
79        self.data
80            .get_mut(i as usize)
81            .and_then(|(gg, t)| if g == *gg { Some(t) } else { None })
82    }
83
84    /// Inserts an element into this coarena.
85    pub fn insert(&mut self, a: Index, value: T)
86    where
87        T: Clone + Default,
88    {
89        let (i1, g1) = a.into_raw_parts();
90
91        if self.data.len() <= i1 as usize {
92            self.data.resize(i1 as usize + 1, (u32::MAX, T::default()));
93        }
94
95        self.data[i1 as usize] = (g1, value);
96    }
97
98    /// Ensure that the given element exists in this coarena, and return its mutable reference.
99    pub fn ensure_element_exist(&mut self, a: Index, default: T) -> &mut T
100    where
101        T: Clone,
102    {
103        let (i1, g1) = a.into_raw_parts();
104
105        if self.data.len() <= i1 as usize {
106            self.data
107                .resize(i1 as usize + 1, (u32::MAX, default.clone()));
108        }
109
110        let data = &mut self.data[i1 as usize];
111
112        if data.0 != g1 {
113            *data = (g1, default);
114        }
115
116        &mut data.1
117    }
118
119    /// Ensure that elements at the two given indices exist in this coarena, and return their references.
120    ///
121    /// Missing elements are created automatically and initialized with the `default` value.
122    pub fn ensure_pair_exists(&mut self, a: Index, b: Index, default: T) -> (&mut T, &mut T)
123    where
124        T: Clone,
125    {
126        let (i1, g1) = a.into_raw_parts();
127        let (i2, g2) = b.into_raw_parts();
128
129        assert_ne!(i1, i2, "Cannot index the same object twice.");
130
131        let (elt1, elt2) = if i1 > i2 {
132            if self.data.len() <= i1 as usize {
133                self.data
134                    .resize(i1 as usize + 1, (u32::MAX, default.clone()));
135            }
136
137            let (left, right) = self.data.split_at_mut(i1 as usize);
138            (&mut right[0], &mut left[i2 as usize])
139        } else {
140            // i2 > i1
141            if self.data.len() <= i2 as usize {
142                self.data
143                    .resize(i2 as usize + 1, (u32::MAX, default.clone()));
144            }
145
146            let (left, right) = self.data.split_at_mut(i2 as usize);
147            (&mut left[i1 as usize], &mut right[0])
148        };
149
150        if elt1.0 != g1 {
151            *elt1 = (g1, default.clone());
152        }
153
154        if elt2.0 != g2 {
155            *elt2 = (g2, default);
156        }
157
158        (&mut elt1.1, &mut elt2.1)
159    }
160}