1use std::{
30 fmt,
31 hint::unreachable_unchecked,
32 iter, mem,
33 num::{NonZeroU32, ParseIntError},
34 ops::{Index, IndexMut},
35 ptr,
36 str::FromStr,
37 vec,
38};
39
40use std::ops::Deref;
41use std::slice;
42
43#[cfg(feature = "serde_support")]
44use serde::{Deserialize, Serialize};
45
46mod par;
47pub use par::*;
48
49#[derive(Clone)]
55enum Slot<T> {
56 Vacant(u32),
58
59 Occupied(T),
61}
62
63#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
70#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
71pub struct ObjId(pub NonZeroU32);
72
73impl ObjId {
74 pub fn from_index(index: u32) -> Self {
80 debug_assert!(index < u32::MAX, "index out of range");
81 Self(unsafe { NonZeroU32::new_unchecked(index + 1) })
87 }
88
89 pub const fn into_index(self) -> u32 {
94 self.0.get() - 1
95 }
96}
97
98impl std::fmt::Display for ObjId {
99 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
100 self.0.fmt(f)
101 }
102}
103
104impl FromStr for ObjId {
105 type Err = ParseIntError;
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 Ok(ObjId(s.parse::<NonZeroU32>()?))
109 }
110}
111
112impl Deref for ObjId {
113 type Target = NonZeroU32;
114
115 fn deref(&self) -> &Self::Target {
116 &self.0
117 }
118}
119
120impl From<NonZeroU32> for ObjId {
121 fn from(v: NonZeroU32) -> ObjId {
122 ObjId(v)
123 }
124}
125
126#[derive(Clone, Copy)]
133pub(crate) struct PoolTag {
134 #[cfg(debug_assertions)]
135 offset: u32,
136}
137
138impl PoolTag {
139 pub(crate) const fn empty() -> Self {
141 PoolTag {
142 #[cfg(debug_assertions)]
143 offset: 0,
144 }
145 }
146
147 pub(crate) fn random() -> Self {
149 let mut tag = Self::empty();
150 tag.randomize();
151 tag
152 }
153
154 #[inline]
156 pub(crate) fn randomize(&mut self) {
157 #[cfg(debug_assertions)]
158 if self.offset == 0 {
159 self.offset = random_offset();
160 }
161 }
162
163 #[inline]
165 pub(crate) fn mask_id(self, obj_id: ObjId) -> ObjId {
166 #[cfg(debug_assertions)]
167 return ObjId(rotate_id(obj_id.0, self.offset as u64));
168 #[cfg(not(debug_assertions))]
169 obj_id
170 }
171
172 #[inline]
174 pub(crate) fn unmask_id(self, obj_id: ObjId) -> ObjId {
175 #[cfg(debug_assertions)]
176 return ObjId(rotate_id(obj_id.0, ID_DOMAIN - self.offset as u64));
177 #[cfg(not(debug_assertions))]
178 obj_id
179 }
180}
181
182#[cfg(debug_assertions)]
184const ID_DOMAIN: u64 = u32::MAX as u64;
185
186#[cfg(debug_assertions)]
190fn rotate_id(value: NonZeroU32, offset: u64) -> NonZeroU32 {
191 let rotated = ((value.get() as u64 - 1) + offset) % ID_DOMAIN;
192 NonZeroU32::new(rotated as u32 + 1).expect("rotation preserves non-zero")
193}
194
195#[cfg(debug_assertions)]
198fn random_offset() -> u32 {
199 use std::collections::hash_map::RandomState;
200 use std::hash::{BuildHasher, Hasher};
201 let random = RandomState::new().build_hasher().finish() as u32;
202 1 + random % (u32::MAX - 1)
203}
204
205pub struct ObjPool<T> {
259 slots: Vec<Slot<T>>,
261
262 len: u32,
264
265 head: u32,
267
268 tag: PoolTag,
270}
271
272impl<T> AsRef<ObjPool<T>> for ObjPool<T> {
273 fn as_ref(&self) -> &ObjPool<T> {
274 self
275 }
276}
277
278impl<T> AsMut<ObjPool<T>> for ObjPool<T> {
279 fn as_mut(&mut self) -> &mut ObjPool<T> {
280 self
281 }
282}
283
284impl<T> ObjPool<T> {
285 #[inline]
297 pub const fn new() -> Self {
298 ObjPool {
299 slots: Vec::new(),
300 len: 0,
301 head: u32::MAX,
302 tag: PoolTag::empty(),
304 }
305 }
306
307 #[inline]
312 pub fn obj_id_to_index(&self, obj_id: ObjId) -> u32 {
313 self.tag.unmask_id(obj_id).into_index()
314 }
315
316 #[inline]
322 pub fn index_to_obj_id(&self, index: u32) -> ObjId {
323 self.tag.mask_id(ObjId::from_index(index))
324 }
325
326 #[inline]
352 pub fn with_capacity(cap: usize) -> Self {
353 ObjPool {
354 slots: Vec::with_capacity(cap),
355 len: 0,
356 head: u32::MAX,
357 tag: PoolTag::random(),
358 }
359 }
360
361 #[inline]
372 pub fn capacity(&self) -> usize {
373 self.slots.capacity()
374 }
375
376 #[inline]
392 pub fn len(&self) -> u32 {
393 self.len
394 }
395
396 #[inline]
410 pub fn is_empty(&self) -> bool {
411 self.len == 0
412 }
413
414 #[inline]
432 pub fn next_vacant(&mut self) -> ObjId {
433 self.tag.randomize();
434 self.index_to_obj_id(if self.head == u32::MAX {
435 self.len
436 } else {
437 self.head
438 })
439 }
440
441 pub fn insert(&mut self, object: T) -> ObjId {
456 self.tag.randomize();
457 self.len += 1;
458
459 if self.head == u32::MAX {
460 self.slots.push(Slot::Occupied(object));
461 self.index_to_obj_id(self.len - 1)
462 } else {
463 let index = self.head;
464 match self.slots[index as usize] {
465 Slot::Vacant(next) => {
466 self.head = next;
467 self.slots[index as usize] = Slot::Occupied(object);
468 }
469 Slot::Occupied(_) => unreachable!(),
470 }
471 self.index_to_obj_id(index)
472 }
473 }
474
475 pub fn remove(&mut self, obj_id: ObjId) -> Option<T> {
494 let index = self.obj_id_to_index(obj_id);
495 match self.slots.get_mut(index as usize) {
496 None => None,
497 Some(&mut Slot::Vacant(_)) => None,
498 Some(slot @ &mut Slot::Occupied(_)) => {
499 if let Slot::Occupied(object) = mem::replace(slot, Slot::Vacant(self.head)) {
500 self.head = index;
501 self.len -= 1;
502 Some(object)
503 } else {
504 unreachable!();
505 }
506 }
507 }
508 }
509
510 #[inline]
529 pub fn clear(&mut self) {
530 self.slots.clear();
531 self.slots.shrink_to_fit();
532 self.len = 0;
533 self.head = u32::MAX;
534 }
535
536 pub fn get(&self, obj_id: ObjId) -> Option<&T> {
553 let index = self.obj_id_to_index(obj_id) as usize;
554 match self.slots.get(index) {
555 None => None,
556 Some(&Slot::Vacant(_)) => None,
557 Some(Slot::Occupied(object)) => Some(object),
558 }
559 }
560
561 #[inline]
578 pub fn get_mut(&mut self, obj_id: ObjId) -> Option<&mut T> {
579 let index = self.obj_id_to_index(obj_id) as usize;
580 match self.slots.get_mut(index) {
581 None => None,
582 Some(&mut Slot::Vacant(_)) => None,
583 Some(&mut Slot::Occupied(ref mut object)) => Some(object),
584 }
585 }
586
587 pub unsafe fn get_unchecked(&self, obj_id: ObjId) -> &T {
604 match self.slots.get(self.obj_id_to_index(obj_id) as usize) {
605 None => unsafe { unreachable_unchecked() },
606 Some(Slot::Vacant(_)) => unsafe { unreachable_unchecked() },
607 Some(Slot::Occupied(object)) => object,
608 }
609 }
610
611 pub unsafe fn get_unchecked_mut(&mut self, obj_id: ObjId) -> &mut T {
628 let index = self.obj_id_to_index(obj_id) as usize;
629 match self.slots.get_mut(index) {
630 Some(&mut Slot::Vacant(_)) => unsafe { unreachable_unchecked() },
631 Some(&mut Slot::Occupied(ref mut object)) => object,
632 _ => unsafe { unreachable_unchecked() },
633 }
634 }
635
636 #[inline]
658 pub fn swap(&mut self, a: ObjId, b: ObjId) {
659 unsafe {
660 let fst = self.get_mut(a).unwrap() as *mut _;
661 let snd = self.get_mut(b).unwrap() as *mut _;
662 if a != b {
663 ptr::swap(fst, snd);
664 }
665 }
666 }
667
668 pub fn reserve(&mut self, additional: u32) {
687 let vacant = self.slots.len() as u32 - self.len;
688 if additional > vacant {
689 self.slots.reserve((additional - vacant) as usize);
690 }
691 }
692
693 pub fn reserve_exact(&mut self, additional: u32) {
713 let vacant = self.slots.len() as u32 - self.len;
714 if additional > vacant {
715 self.slots.reserve_exact((additional - vacant) as usize);
716 }
717 }
718
719 #[inline]
737 pub fn iter(&self) -> Iter<'_, T> {
738 Iter {
739 len: self.len as usize,
740 slots: self.slots.iter().enumerate(),
741 tag: self.tag,
742 }
743 }
744
745 #[inline]
771 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
772 IterMut {
773 len: self.len as usize,
774 slots: self.slots.iter_mut().enumerate(),
775 tag: self.tag,
776 }
777 }
778
779 pub fn shrink_to_fit(&mut self) {
798 self.slots.shrink_to_fit();
799 }
800}
801
802impl<T> fmt::Debug for ObjPool<T> {
803 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
804 write!(f, "ObjPool {{ ... }}")
805 }
806}
807
808impl<T> Index<ObjId> for ObjPool<T> {
809 type Output = T;
810
811 #[inline]
812 fn index(&self, obj_id: ObjId) -> &T {
813 self.get(obj_id).expect("object not found")
814 }
815}
816
817impl<T> IndexMut<ObjId> for ObjPool<T> {
818 #[inline]
819 fn index_mut(&mut self, obj_id: ObjId) -> &mut T {
820 self.get_mut(obj_id).expect("object not found")
821 }
822}
823
824impl<T> Default for ObjPool<T> {
825 fn default() -> Self {
826 ObjPool::new()
827 }
828}
829
830impl<T: Clone> Clone for ObjPool<T> {
831 fn clone(&self) -> Self {
832 ObjPool {
833 slots: self.slots.clone(),
834 len: self.len,
835 head: self.head,
836 tag: self.tag,
838 }
839 }
840}
841
842pub struct IntoIter<T> {
844 slots: iter::Enumerate<vec::IntoIter<Slot<T>>>,
845 len: usize,
846 tag: PoolTag,
847}
848
849impl<T> Iterator for IntoIter<T> {
850 type Item = (ObjId, T);
851
852 #[inline]
853 fn next(&mut self) -> Option<Self::Item> {
854 for (index, slot) in self.slots.by_ref() {
855 if let Slot::Occupied(object) = slot {
856 self.len -= 1;
857 return Some((self.tag.mask_id(ObjId::from_index(index as u32)), object));
858 }
859 }
860 None
861 }
862
863 fn size_hint(&self) -> (usize, Option<usize>) {
864 (self.len, Some(self.len))
865 }
866}
867
868impl<T> ExactSizeIterator for IntoIter<T> {
869 fn len(&self) -> usize {
870 self.len
871 }
872}
873
874impl<T> iter::FusedIterator for IntoIter<T> {}
875
876impl<T> IntoIterator for ObjPool<T> {
877 type Item = (ObjId, T);
878 type IntoIter = IntoIter<T>;
879
880 #[inline]
881 fn into_iter(self) -> Self::IntoIter {
882 IntoIter {
883 len: self.len as usize,
884 tag: self.tag,
885 slots: self.slots.into_iter().enumerate(),
886 }
887 }
888}
889
890impl<T> iter::FromIterator<T> for ObjPool<T> {
891 fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> ObjPool<T> {
892 let iter = iter.into_iter();
893 let mut obj_pool = ObjPool::with_capacity(iter.size_hint().0);
894 for i in iter {
895 obj_pool.insert(i);
896 }
897 obj_pool
898 }
899}
900
901impl<T> fmt::Debug for IntoIter<T> {
902 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
903 write!(f, "IntoIter {{ ... }}")
904 }
905}
906
907pub struct Iter<'a, T: 'a> {
909 slots: iter::Enumerate<slice::Iter<'a, Slot<T>>>,
910 len: usize,
911 tag: PoolTag,
912}
913
914impl<'a, T> Iterator for Iter<'a, T> {
915 type Item = (ObjId, &'a T);
916
917 #[inline]
918 fn next(&mut self) -> Option<Self::Item> {
919 for (index, slot) in self.slots.by_ref() {
920 if let Slot::Occupied(ref object) = *slot {
921 self.len -= 1;
922 return Some((self.tag.mask_id(ObjId::from_index(index as u32)), object));
923 }
924 }
925 None
926 }
927
928 fn size_hint(&self) -> (usize, Option<usize>) {
929 (self.len, Some(self.len))
930 }
931}
932
933impl<T> ExactSizeIterator for Iter<'_, T> {
934 fn len(&self) -> usize {
935 self.len
936 }
937}
938
939impl<T> iter::FusedIterator for Iter<'_, T> {}
940
941impl<'a, T> IntoIterator for &'a ObjPool<T> {
942 type Item = (ObjId, &'a T);
943 type IntoIter = Iter<'a, T>;
944
945 #[inline]
946 fn into_iter(self) -> Self::IntoIter {
947 self.iter()
948 }
949}
950
951impl<'a, T> fmt::Debug for Iter<'a, T> {
952 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
953 write!(f, "Iter {{ ... }}")
954 }
955}
956
957pub struct IterMut<'a, T: 'a> {
959 slots: iter::Enumerate<slice::IterMut<'a, Slot<T>>>,
960 len: usize,
961 tag: PoolTag,
962}
963
964impl<'a, T> Iterator for IterMut<'a, T> {
965 type Item = (ObjId, &'a mut T);
966
967 #[inline]
968 fn next(&mut self) -> Option<Self::Item> {
969 for (index, slot) in self.slots.by_ref() {
970 if let Slot::Occupied(ref mut object) = *slot {
971 self.len -= 1;
972 return Some((self.tag.mask_id(ObjId::from_index(index as u32)), object));
973 }
974 }
975 None
976 }
977
978 fn size_hint(&self) -> (usize, Option<usize>) {
979 (self.len, Some(self.len))
980 }
981}
982
983impl<T> ExactSizeIterator for IterMut<'_, T> {
984 fn len(&self) -> usize {
985 self.len
986 }
987}
988
989impl<T> iter::FusedIterator for IterMut<'_, T> {}
990
991impl<'a, T> IntoIterator for &'a mut ObjPool<T> {
992 type Item = (ObjId, &'a mut T);
993 type IntoIter = IterMut<'a, T>;
994
995 #[inline]
996 fn into_iter(self) -> Self::IntoIter {
997 self.iter_mut()
998 }
999}
1000
1001impl<'a, T> fmt::Debug for IterMut<'a, T> {
1002 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1003 write!(f, "IterMut {{ ... }}")
1004 }
1005}
1006
1007#[cfg(test)]
1008mod tests {
1009 use super::*;
1010
1011 #[test]
1012 fn new() {
1013 let obj_pool = ObjPool::<i32>::new();
1014 assert!(obj_pool.is_empty());
1015 assert_eq!(obj_pool.len(), 0);
1016 assert_eq!(obj_pool.capacity(), 0);
1017 }
1018
1019 #[test]
1020 fn insert() {
1021 let mut obj_pool = ObjPool::new();
1022
1023 for i in 0..10 {
1024 let a = obj_pool.insert(i * 10);
1025 assert_eq!(obj_pool[a], i * 10);
1026 }
1027 assert!(!obj_pool.is_empty());
1028 assert_eq!(obj_pool.len(), 10);
1029 }
1030
1031 #[test]
1032 fn with_capacity() {
1033 let mut obj_pool = ObjPool::with_capacity(10);
1034 assert_eq!(obj_pool.capacity(), 10);
1035
1036 for _ in 0..10 {
1037 obj_pool.insert(());
1038 }
1039 assert_eq!(obj_pool.len(), 10);
1040 assert_eq!(obj_pool.capacity(), 10);
1041
1042 obj_pool.insert(());
1043 assert_eq!(obj_pool.len(), 11);
1044 assert!(obj_pool.capacity() > 10);
1045 }
1046
1047 #[test]
1048 fn remove() {
1049 let mut obj_pool = ObjPool::new();
1050
1051 let a = obj_pool.insert(0);
1052 let b = obj_pool.insert(10);
1053 let c = obj_pool.insert(20);
1054 obj_pool.insert(30);
1055 assert_eq!(obj_pool.len(), 4);
1056
1057 assert_eq!(obj_pool.remove(b), Some(10));
1058 assert_eq!(obj_pool.remove(c), Some(20));
1059 assert_eq!(obj_pool.len(), 2);
1060
1061 obj_pool.insert(-1);
1062 obj_pool.insert(-1);
1063 assert_eq!(obj_pool.len(), 4);
1064
1065 assert_eq!(obj_pool.remove(a), Some(0));
1066 obj_pool.insert(-1);
1067 assert_eq!(obj_pool.len(), 4);
1068
1069 obj_pool.insert(400);
1070 assert_eq!(obj_pool.len(), 5);
1071 }
1072
1073 #[test]
1074 fn clear() {
1075 let mut obj_pool = ObjPool::new();
1076 obj_pool.insert(10);
1077 obj_pool.insert(20);
1078
1079 assert!(!obj_pool.is_empty());
1080 assert_eq!(obj_pool.len(), 2);
1081
1082 obj_pool.clear();
1083
1084 assert!(obj_pool.is_empty());
1085 assert_eq!(obj_pool.len(), 0);
1086 assert_eq!(obj_pool.capacity(), 0);
1087 }
1088
1089 #[test]
1090 fn indexing() {
1091 let mut obj_pool = ObjPool::new();
1092
1093 let a = obj_pool.insert(10);
1094 let b = obj_pool.insert(20);
1095 let c = obj_pool.insert(30);
1096
1097 obj_pool[b] += obj_pool[c];
1098 assert_eq!(obj_pool[a], 10);
1099 assert_eq!(obj_pool[b], 50);
1100 assert_eq!(obj_pool[c], 30);
1101 }
1102
1103 #[test]
1104 #[should_panic]
1105 fn indexing_vacant() {
1106 let mut obj_pool = ObjPool::new();
1107
1108 let _ = obj_pool.insert(10);
1109 let b = obj_pool.insert(20);
1110 let _ = obj_pool.insert(30);
1111
1112 obj_pool.remove(b);
1113 obj_pool[b];
1114 }
1115
1116 #[test]
1117 #[should_panic]
1118 fn invalid_indexing() {
1119 let mut obj_pool = ObjPool::new();
1120
1121 obj_pool.insert(10);
1122 obj_pool.insert(20);
1123 let a = obj_pool.insert(30);
1124 obj_pool.remove(a);
1125
1126 obj_pool[a];
1127 }
1128
1129 #[test]
1130 fn get() {
1131 let mut obj_pool = ObjPool::new();
1132
1133 let a = obj_pool.insert(10);
1134 let b = obj_pool.insert(20);
1135 let c = obj_pool.insert(30);
1136
1137 *obj_pool.get_mut(b).unwrap() += *obj_pool.get(c).unwrap();
1138 assert_eq!(obj_pool.get(a), Some(&10));
1139 assert_eq!(obj_pool.get(b), Some(&50));
1140 assert_eq!(obj_pool.get(c), Some(&30));
1141
1142 obj_pool.remove(b);
1143 assert_eq!(obj_pool.get(b), None);
1144 assert_eq!(obj_pool.get_mut(b), None);
1145 }
1146
1147 #[test]
1148 fn reserve() {
1149 let mut obj_pool = ObjPool::new();
1150 obj_pool.insert(1);
1151 obj_pool.insert(2);
1152
1153 obj_pool.reserve(10);
1154 assert!(obj_pool.capacity() >= 11);
1155 }
1156
1157 #[test]
1158 fn reserve_exact() {
1159 let mut obj_pool = ObjPool::new();
1160 obj_pool.insert(1);
1161 obj_pool.insert(2);
1162 obj_pool.reserve(10);
1163 assert!(obj_pool.capacity() >= 11);
1164 }
1165
1166 #[test]
1167 fn iter() {
1168 let mut arena = ObjPool::new();
1169 let a = arena.insert(10);
1170 let b = arena.insert(20);
1171 let c = arena.insert(30);
1172 let d = arena.insert(40);
1173
1174 arena.remove(b);
1175
1176 let mut it = arena.iter();
1177 assert_eq!(it.next(), Some((a, &10)));
1178 assert_eq!(it.next(), Some((c, &30)));
1179 assert_eq!(it.next(), Some((d, &40)));
1180 assert_eq!(it.next(), None);
1181 }
1182
1183 #[test]
1184 fn iter_mut() {
1185 let mut obj_pool = ObjPool::new();
1186 let a = obj_pool.insert(10);
1187 let b = obj_pool.insert(20);
1188 let c = obj_pool.insert(30);
1189 let d = obj_pool.insert(40);
1190
1191 obj_pool.remove(b);
1192
1193 {
1194 let mut it = obj_pool.iter_mut();
1195 assert_eq!(it.next(), Some((a, &mut 10)));
1196 assert_eq!(it.next(), Some((c, &mut 30)));
1197 assert_eq!(it.next(), Some((d, &mut 40)));
1198 assert_eq!(it.next(), None);
1199 }
1200
1201 for (obj_id, value) in &mut obj_pool {
1202 *value += obj_id.get();
1203 }
1204
1205 let mut it = obj_pool.iter_mut();
1206 assert_eq!(*it.next().unwrap().1, 10 + a.get());
1207 assert_eq!(*it.next().unwrap().1, 30 + c.get());
1208 assert_eq!(*it.next().unwrap().1, 40 + d.get());
1209 assert_eq!(it.next(), None);
1210 }
1211
1212 #[test]
1213 fn from_iter() {
1214 let obj_pool: ObjPool<usize> = [10, 20, 30, 40].iter().cloned().collect();
1215
1216 let mut it = obj_pool.iter();
1217 assert_eq!(it.next(), Some((obj_pool.index_to_obj_id(0), &10)));
1218 assert_eq!(it.next(), Some((obj_pool.index_to_obj_id(1), &20)));
1219 assert_eq!(it.next(), Some((obj_pool.index_to_obj_id(2), &30)));
1220 assert_eq!(it.next(), Some((obj_pool.index_to_obj_id(3), &40)));
1221 assert_eq!(it.next(), None);
1222 }
1223
1224 #[test]
1225 fn obj_id_index_round_trip() {
1226 let mut obj_pool = ObjPool::new();
1227 let a = obj_pool.insert(10);
1228 let b = obj_pool.insert(20);
1229
1230 assert_eq!(obj_pool.obj_id_to_index(a), 0);
1231 assert_eq!(obj_pool.obj_id_to_index(b), 1);
1232 assert_eq!(obj_pool.index_to_obj_id(0), a);
1233 assert_eq!(obj_pool.index_to_obj_id(1), b);
1234 }
1235
1236 #[cfg(debug_assertions)]
1237 #[test]
1238 fn foreign_obj_id_is_rejected() {
1239 let mut a = ObjPool::new();
1240 let id = a.insert(10);
1241
1242 let mut b = ObjPool::new();
1243 b.insert(20);
1244 while b.tag.offset == a.tag.offset {
1248 b = ObjPool::new();
1249 b.insert(20);
1250 }
1251
1252 assert_eq!(b.get(id), None);
1253 assert_eq!(b.get_mut(id), None);
1254 assert_eq!(b.remove(id), None);
1255 assert_eq!(b.get(b.index_to_obj_id(0)), Some(&20));
1256 }
1257
1258 #[test]
1259 fn free_list_is_lifo() {
1260 let mut obj_pool = ObjPool::new();
1261 let a = obj_pool.insert(1);
1262 let b = obj_pool.insert(2);
1263 let c = obj_pool.insert(3);
1264
1265 obj_pool.remove(a);
1266 obj_pool.remove(c);
1267
1268 assert_eq!(obj_pool.next_vacant(), c);
1270 assert_eq!(obj_pool.insert(30), c);
1271 assert_eq!(obj_pool.next_vacant(), a);
1272 assert_eq!(obj_pool.insert(10), a);
1273
1274 let next = obj_pool.next_vacant();
1276 assert_eq!(obj_pool.obj_id_to_index(next), 3);
1277 assert_eq!(obj_pool.insert(4), next);
1278 assert_eq!(obj_pool.len(), 4);
1279 assert_eq!(obj_pool.get(b), Some(&2));
1280 }
1281
1282 #[test]
1283 fn unknown_id_is_not_found() {
1284 let mut obj_pool = ObjPool::new();
1285 obj_pool.insert(1);
1286
1287 let unknown = obj_pool.index_to_obj_id(100);
1288 assert_eq!(obj_pool.get(unknown), None);
1289 assert_eq!(obj_pool.get_mut(unknown), None);
1290 assert_eq!(obj_pool.remove(unknown), None);
1291 assert_eq!(obj_pool.len(), 1);
1292 }
1293
1294 #[test]
1295 fn clear_then_insert_reuses_ids() {
1296 let mut obj_pool = ObjPool::new();
1297 let a = obj_pool.insert(1);
1298 obj_pool.insert(2);
1299 obj_pool.clear();
1300
1301 assert_eq!(obj_pool.get(a), None);
1303 assert_eq!(obj_pool.remove(a), None);
1304
1305 let b = obj_pool.insert(3);
1307 assert_eq!(b, a);
1308 assert_eq!(obj_pool.get(b), Some(&3));
1309 assert_eq!(obj_pool.len(), 1);
1310 }
1311
1312 #[test]
1313 fn into_iter_skips_vacant() {
1314 let mut obj_pool = ObjPool::new();
1315 let a = obj_pool.insert(10);
1316 let b = obj_pool.insert(20);
1317 let c = obj_pool.insert(30);
1318 obj_pool.remove(b);
1319
1320 let items: Vec<_> = obj_pool.into_iter().collect();
1321 assert_eq!(items, [(a, 10), (c, 30)]);
1322 }
1323
1324 #[test]
1325 fn iterate_with_vacant_ends() {
1326 let mut obj_pool = ObjPool::new();
1327 let a = obj_pool.insert(10);
1328 let b = obj_pool.insert(20);
1329 let c = obj_pool.insert(30);
1330 obj_pool.remove(a);
1331 obj_pool.remove(c);
1332
1333 let items: Vec<_> = obj_pool.iter().map(|(k, &v)| (k, v)).collect();
1334 assert_eq!(items, [(b, 20)]);
1335 }
1336
1337 #[test]
1338 fn iterate_empty_and_fully_vacant() {
1339 let mut obj_pool: ObjPool<i32> = ObjPool::new();
1340 assert_eq!(obj_pool.iter().next(), None);
1341 assert_eq!(obj_pool.iter().size_hint(), (0, Some(0)));
1342
1343 let keys: Vec<_> = (0..4).map(|v| obj_pool.insert(v)).collect();
1344 for k in keys {
1345 obj_pool.remove(k);
1346 }
1347 assert!(obj_pool.is_empty());
1348 assert_eq!(obj_pool.iter().size_hint(), (0, Some(0)));
1349 assert_eq!(obj_pool.iter().next(), None);
1350 assert_eq!(obj_pool.iter_mut().next(), None);
1351 assert_eq!(obj_pool.into_iter().next(), None);
1352 }
1353
1354 #[test]
1355 fn iterator_len_and_fuse() {
1356 let mut obj_pool = ObjPool::new();
1357 obj_pool.insert(10);
1358 let b = obj_pool.insert(20);
1359 obj_pool.insert(30);
1360 obj_pool.remove(b);
1361
1362 let mut it = obj_pool.iter();
1363 assert_eq!(it.len(), 2);
1364 assert_eq!(it.size_hint(), (2, Some(2)));
1365 it.next();
1366 assert_eq!(it.len(), 1);
1367 it.next();
1368 assert_eq!(it.len(), 0);
1369 assert_eq!(it.next(), None);
1370 assert_eq!(it.next(), None);
1372
1373 let mut it = obj_pool.iter_mut();
1374 assert_eq!(it.len(), 2);
1375 it.next();
1376 assert_eq!(it.size_hint(), (1, Some(1)));
1377
1378 let mut it = obj_pool.into_iter();
1379 assert_eq!(it.len(), 2);
1380 it.next();
1381 assert_eq!(it.len(), 1);
1382 }
1383
1384 #[test]
1385 fn clone_preserves_ids_and_free_list() {
1386 let mut original = ObjPool::new();
1387 let a = original.insert(1);
1388 let b = original.insert(2);
1389 let c = original.insert(3);
1390 original.remove(b);
1391
1392 let mut clone = original.clone();
1393 assert_eq!(clone.get(a), Some(&1));
1395 assert_eq!(clone.get(b), None);
1396 assert_eq!(clone.get(c), Some(&3));
1397 assert_eq!(clone.len(), original.len());
1398
1399 assert_eq!(clone.insert(20), original.insert(20));
1402 assert_eq!(clone.insert(4), original.insert(4));
1403 }
1404
1405 #[test]
1406 fn swap_with_itself() {
1407 let mut obj_pool = ObjPool::new();
1408 let a = obj_pool.insert(7);
1409 obj_pool.swap(a, a);
1410 assert_eq!(obj_pool.get(a), Some(&7));
1411 }
1412
1413 #[test]
1414 #[should_panic]
1415 fn swap_removed_id_panics() {
1416 let mut obj_pool = ObjPool::new();
1417 let a = obj_pool.insert(1);
1418 let b = obj_pool.insert(2);
1419 obj_pool.remove(b);
1420 obj_pool.swap(a, b);
1421 }
1422
1423 #[test]
1424 fn reserve_accounts_for_vacant_slots() {
1425 let mut obj_pool = ObjPool::with_capacity(2);
1426 let a = obj_pool.insert(1);
1427 obj_pool.insert(2);
1428 obj_pool.remove(a);
1429
1430 obj_pool.reserve(1);
1432 assert_eq!(obj_pool.capacity(), 2);
1433 obj_pool.reserve_exact(1);
1434 assert_eq!(obj_pool.capacity(), 2);
1435 }
1436
1437 #[test]
1438 fn obj_id_display_from_str_round_trip() {
1439 let mut obj_pool = ObjPool::new();
1440 let a = obj_pool.insert(7);
1441
1442 let parsed: ObjId = a.to_string().parse().unwrap();
1443 assert_eq!(parsed, a);
1444 assert_eq!(obj_pool.get(parsed), Some(&7));
1445
1446 assert!("0".parse::<ObjId>().is_err());
1447 assert!("".parse::<ObjId>().is_err());
1448 assert!("abc".parse::<ObjId>().is_err());
1449 assert!("4294967296".parse::<ObjId>().is_err()); }
1451
1452 #[test]
1453 fn obj_id_raw_round_trip() {
1454 for index in [0, 1, 42, u32::MAX - 1] {
1455 assert_eq!(ObjId::from_index(index).into_index(), index);
1456 }
1457 }
1458
1459 #[cfg(debug_assertions)]
1460 #[test]
1461 #[should_panic(expected = "index out of range")]
1462 fn from_index_max_panics_in_debug() {
1463 let _ = ObjId::from_index(u32::MAX);
1464 }
1465}