grit_data_prison/single_threaded.rs
1use crate::{
2 extract_true_start_end, internal, major_malfunction, mem_replace, unreachable_unchecked,
3 AccessError, Borrow, BorrowMut, CellKey, Debug, Deref, DerefMut, MaybeUninit, RangeBounds,
4 UnsafeCell,
5};
6
7#[cfg(test)]
8 mod tests;
9
10//====== Misc Types ======
11//STRUCT Refs
12struct Refs {}
13impl Refs {
14 const MUT: usize = usize::MAX;
15 const MAX_IMMUT: usize = Self::MUT - 1;
16}
17
18//STRUCT IdxD
19#[allow(non_camel_case_types)]
20struct IdxD {}
21#[allow(dead_code)]
22impl IdxD {
23 const MAX_CAP: usize = usize::MAX >> 1;
24 const MAX_GEN: usize = Self::MAX_CAP;
25 const MAX_IDX: usize = Self::MAX_CAP - 1;
26 const INVALID: usize = Self::MAX_CAP;
27 const DISCRIMINANT_MASK: usize = Self::MAX_CAP + 1;
28 const DISCRIMINANT_SHIFT: u32 = usize::BITS - 1;
29 const VALUE_MASK: usize = Self::MAX_CAP;
30
31 const fn val(val: usize) -> usize {
32 val & Self::VALUE_MASK
33 }
34
35 const fn is_type_a(val: usize) -> bool {
36 val & Self::DISCRIMINANT_MASK == 0
37 }
38
39 const fn is_type_b(val: usize) -> bool {
40 val & Self::DISCRIMINANT_MASK == Self::DISCRIMINANT_MASK
41 }
42
43 const fn new_type_a(val: usize) -> usize {
44 val & Self::VALUE_MASK
45 }
46
47 const fn new_type_b(val: usize) -> usize {
48 (val & Self::VALUE_MASK) | Self::DISCRIMINANT_MASK
49 }
50}
51
52//====== Prison ======
53//------ Prison Public ------
54//STRUCT Prison
55/// The single-threaded implementation of [Prison]
56///
57/// This struct uses an underlying [Vec<T>] to store data, but provides full interior mutability
58/// for each of its elements. It primarily acts like a Generational Arena using [CellKey]'s to index
59/// into the vector, but allows accessing elements with only a plain [usize] as well.
60///
61/// It does this by using [UnsafeCell] to wrap its internals, a ref-counting [usize] on each element,
62/// and a master [usize] access-counter that are used to determine what cells (indexes) are currently
63/// being accessed to prevent violating Rust's memory management rules.
64/// Each element also has a [usize] generation counter to determine if the value being requested
65/// was created in the same context it is being requested in.
66///
67/// Removing elements does not shift all elements that come after it like a normal [Vec]. Instead,
68/// it marks the element as "free", meaning the value was deleted or removed. Subsequent inserts into
69/// the [Prison] will insert values into free spaces before they consider extending the [Vec],
70/// minimizing reallocations when possible.
71///
72/// See the crate-level documentation or individual methods for more info
73#[derive(Debug)] //COV_IGNORE
74pub struct Prison<T> {
75 internal: UnsafeCell<PrisonInternal<T>>,
76}
77
78impl<T> Prison<T> {
79 //FN Prison::new()
80 /// Create a new [Prison] with the default allocation strategy ([Vec::new()])
81 ///
82 /// Because [Prison] accepts values that may or may not be implement [Copy], [Clone],
83 /// or [Default] and because indexes are simply marked as "free" when their values are removed
84 /// from the [Prison], a closure must be provided upon creation of a new prison
85 /// that supplies it default values to replace the removed ones with safely ([mem::replace()](mem_replace))
86 /// without running into double-frees or use-after-frees or resorting to things like
87 /// [ManuallyDrop](std::mem::ManuallyDrop) or [MaybeUninit](std::mem::MaybeUninit)
88 ///
89 /// Because re-allocating the internal [Vec] comes with many restrictions when
90 /// accessing references to its elements, it is recommended to use [Prison::with_capacity()]
91 /// with a suitable best-guess starting value rather than [Prison::new()]
92 /// ### Example
93 /// ```rust
94 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
95 /// # fn main() {
96 /// let my_prison: Prison<u32> = Prison::new();
97 /// assert!(my_prison.vec_cap() < 100)
98 /// # }
99 /// ```
100 #[inline(always)]
101 pub fn new() -> Self {
102 return Self {
103 internal: UnsafeCell::new(PrisonInternal {
104 access_count: 0,
105 free_count: 0,
106 generation: 0,
107 next_free: IdxD::INVALID,
108 vec: Vec::new(),
109 }),
110 };
111 }
112
113 //FN Prison::with_capacity()
114 /// Create a new [Prison<T>] with a specific starting capacity ([Vec::with_capacity()])
115 ///
116 /// Because [Prison<T>] accepts values that may or may not be implement [Copy], [Clone],
117 /// or [Default] and because indexes are simply marked as "free" when their values are removed
118 /// from the [Prison], a closure must be provided upon creation of a new prison
119 /// that supplies it default values to replace the removed ones with safely ([mem::replace()](mem_replace))
120 /// without running into double-frees or use-after-frees or resorting to things like
121 /// [ManuallyDrop](std::mem::ManuallyDrop) or [MaybeUninit](std::mem::MaybeUninit)
122 ///
123 /// Because re-allocating the internal [Vec] comes with many restrictions when
124 /// accessing references to its elements, it is recommended to use [Prison::with_capacity()]
125 /// with a suitable best-guess starting value rather than [Prison::new()]
126 /// ### Example
127 /// ```rust
128 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
129 /// # fn main() {
130 /// let my_prison: Prison<u32> = Prison::with_capacity(1000);
131 /// assert!(my_prison.vec_cap() == 1000)
132 /// # }
133 /// ```
134 #[inline(always)]
135 pub fn with_capacity(size: usize) -> Self {
136 return Self {
137 internal: UnsafeCell::new(PrisonInternal {
138 access_count: 0,
139 free_count: 0,
140 generation: 0,
141 next_free: IdxD::INVALID,
142 vec: Vec::with_capacity(size),
143 }),
144 };
145 }
146
147 //FN Prison::vec_len()
148 /// Return the length of the underlying [Vec]
149 ///
150 /// Because a [Prison] may have values that are free/deleted that are still counted
151 /// within the length of the [Vec], this value should not be used to determine how many
152 /// *valid* elements exist in the [Prison]
153 #[inline(always)]
154 pub fn vec_len(&self) -> usize {
155 return internal!(self).vec.len();
156 }
157
158 //FN Prison::vec_cap()
159 /// Return the capacity of the underlying [Vec]
160 ///
161 /// Capacity refers to the number of total spaces in memory reserved for the [Vec]
162 ///
163 /// Because a [Prison] may have values that are free/deleted that are *not* counted
164 /// withing the capacity of the [Vec], this value should not be used to determine how many
165 /// *empty* spots exist to add elements into the [Prison]
166 #[inline(always)]
167 pub fn vec_cap(&self) -> usize {
168 return internal!(self).vec.capacity();
169 }
170
171 //FN Prison::num_free()
172 /// Return the number of spaces available for elements to be added to the [Prison]
173 /// without reallocating more memory.
174 #[inline(always)]
175 pub fn num_free(&self) -> usize {
176 let internal = internal!(self);
177 return internal.free_count + internal.vec.capacity() - internal.vec.len();
178 }
179
180 //FN Prison::num_used()
181 /// Return the number of spaces currently occupied by valid elements in the [Prison]
182 #[inline(always)]
183 pub fn num_used(&self) -> usize {
184 let internal = internal!(self);
185 return internal.vec.len() - internal.free_count;
186 }
187
188 //FN Prison::density()
189 /// Return the ratio of used space to total space in the [Prison]
190 ///
191 /// 0.0 = 0% used, 1.0 = 100% used
192 pub fn density(&self) -> f32 {
193 let internal = internal!(self);
194 let used = internal.vec.len() - internal.free_count;
195 let cap = internal.vec.capacity();
196 return (used as f32) / (cap as f32);
197 }
198
199 //FN Prison::insert()
200 /// Insert a value into the [Prison] and recieve a [CellKey] that can be used to
201 /// reference it in the future
202 ///
203 /// As long as there are sufficient free cells or vector capacity to do so,
204 /// you may `insert()` to the [Prison] while any of its elements have active references
205 /// ### Example
206 /// ```rust
207 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
208 /// # fn main() -> Result<(), AccessError> {
209 /// let string_prison: Prison<String> = Prison::with_capacity(10);
210 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
211 /// string_prison.visit_ref(key_0, |first_string| {
212 /// let key_1 = string_prison.insert(String::from("World!"))?;
213 /// string_prison.visit_ref(key_1, |second_string| {
214 /// let hello_world = format!("{}{}", first_string, second_string);
215 /// assert_eq!(hello_world, "Hello, World!");
216 /// Ok(())
217 /// });
218 /// Ok(())
219 /// });
220 /// # Ok(())
221 /// # }
222 /// ```
223 /// However, if the [Prison] is at maxumum capacity, attempting to `insert()`
224 /// during while there are active references to any element will cause the operation to fail and a
225 /// [AccessError::InsertAtMaxCapacityWhileAValueIsReferenced] to be returned
226 /// ### Example
227 /// ```rust
228 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
229 /// # fn main() -> Result<(), AccessError> {
230 /// let string_prison: Prison<String> = Prison::with_capacity(1);
231 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
232 /// string_prison.visit_ref(key_0, |first_string| {
233 /// assert!(string_prison.insert(String::from("World!")).is_err());
234 /// Ok(())
235 /// })?;
236 /// # Ok(())
237 /// # }
238 /// ```
239 #[inline(always)]
240 pub fn insert(&self, value: T) -> Result<CellKey, AccessError> {
241 let internal = internal!(self);
242 if internal.next_free == IdxD::INVALID {
243 if internal.vec.capacity() <= internal.vec.len() {
244 if internal.access_count > 0 {
245 return Err(AccessError::InsertAtMaxCapacityWhileAValueIsReferenced);
246 }
247 if internal.vec.capacity() == IdxD::MAX_CAP {
248 return Err(AccessError::MaximumCapacityReached);
249 }
250 }
251 internal
252 .vec
253 .push(PrisonCell::new_cell(value, internal.generation));
254 return Ok(CellKey {
255 idx: internal.vec.len() - 1,
256 gen: internal.generation,
257 });
258 }
259 let new_idx = internal.next_free;
260 match &mut internal.vec[new_idx] {
261 free if free.is_free() => {
262 internal.free_count -= 1;
263 internal.next_free = free.refs_or_next;
264 free.make_cell_unchecked(value, internal.generation);
265 Ok(CellKey {
266 idx: new_idx,
267 gen: internal.generation,
268 })
269 }
270 _ => major_malfunction!( //COV_IGNORE
271 "`Prison` had a recorded `next_free` index ({}) that WAS NOT FREE", //COV_IGNORE
272 new_idx //COV_IGNORE
273 ), //COV_IGNORE
274 }
275 }
276
277 //FN Prison::insert_at()
278 /// #### This operation has O(N) time complexity
279 ///
280 /// Insert a value into the [Prison] at the specified index and recieve a
281 /// [CellKey] that can be used to reference it in the future
282 ///
283 /// The index *must* be within range of the underlying [Vec] *AND* must reference
284 /// a space tagged as free/deleted.
285 /// ### Example
286 /// ```rust
287 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
288 /// # fn main() -> Result<(), AccessError> {
289 /// let string_prison: Prison<String> = Prison::with_capacity(10);
290 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
291 /// let key_1 = string_prison.insert(String::from("World!"))?;
292 /// string_prison.remove(key_1)?;
293 /// let key_1 = string_prison.insert_at(1, String::from("Rust!!"))?;
294 /// string_prison.visit_many_ref(&[key_0, key_1], |vals| {
295 /// let hello_world = format!("{}{}", vals[0], vals[1]);
296 /// assert_eq!(hello_world, "Hello, Rust!!");
297 /// Ok(())
298 /// })?;
299 /// # Ok(())
300 /// # }
301 /// ```
302 /// If the index is out of range the function will return an [AccessError::IndexOutOfRange(idx)],
303 /// and if the index is not free/deleted, it will return an [AccessError::IndexIsNotFree(idx)]
304 /// ### Example
305 /// ```rust
306 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
307 /// # fn main() -> Result<(), AccessError> {
308 /// let string_prison: Prison<String> = Prison::with_capacity(10);
309 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
310 /// let key_1 = string_prison.insert(String::from("World!"))?;
311 /// assert!(string_prison.insert_at(1, String::from("Rust!!")).is_err());
312 /// assert!(string_prison.insert_at(10, String::from("Oops...")).is_err());
313 /// # Ok(())
314 /// # }
315 /// ```
316 #[inline(always)]
317 pub fn insert_at(&self, idx: usize, value: T) -> Result<CellKey, AccessError> {
318 let internal: &mut PrisonInternal<T> = internal!(self);
319 if idx >= internal.vec.len() {
320 return Err(AccessError::IndexOutOfRange(idx));
321 }
322 match &mut internal.vec[idx] {
323 free if free.is_free() => {
324 let prev = IdxD::val(free.d_gen_or_prev);
325 if prev != IdxD::INVALID {
326 match &mut internal!(self).vec[prev] {
327 prev_free if prev_free.is_free() => prev_free.refs_or_next = free.refs_or_next,
328 _ => major_malfunction!("a `Free` index ({}) had a `prev_free` that pointed to an index ({}) that WAS NOT FREE", idx, prev) //COV_IGNORE
329 }
330 } else if internal.next_free == idx {
331 internal.next_free = free.refs_or_next;
332 } else {
333 major_malfunction!("a `Free` index ({}) had a `prev_free` value that indicated `INVALID`, meaning it should have been the top of the `free` stack, but `Prison.next_free` ({}) did not match its index", prev, internal.next_free) //COV_IGNORE
334 }
335 if free.refs_or_next != IdxD::INVALID {
336 match &mut internal!(self).vec[free.refs_or_next] {
337 next_free if next_free.is_free() => next_free.d_gen_or_prev = IdxD::new_type_b(prev),
338 _ => major_malfunction!("a `Free` index ({}) had a `next_free` that pointed to an index ({}) that WAS NOT FREE", idx, free.refs_or_next) //COV_IGNORE
339 }
340 }
341 internal.free_count -= 1;
342 free.make_cell_unchecked(value, internal.generation);
343 return Ok(CellKey {
344 idx,
345 gen: internal.generation,
346 });
347 }
348 _ => return Err(AccessError::IndexIsNotFree(idx)),
349 }
350 }
351
352 //FN Prison::overwrite()
353 /// Insert or overwrite a value in the [Prison] at the specified index and recieve a
354 /// [CellKey] that can be used to reference it in the future
355 ///
356 /// Similar to [Prison::insert_at()] but does not require the space be marked as free.
357 ///
358 /// Note: Overwriting a value that isn't marked as free will invalidate any [CellKey]
359 /// that could have been used to reference it and cause a lookup using the old
360 /// key(s) to return an [AccessError::ValueDeleted(idx, gen)]
361 /// ### Example
362 /// ```rust
363 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
364 /// # fn main() -> Result<(), AccessError> {
365 /// let string_prison: Prison<String> = Prison::with_capacity(10);
366 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
367 /// let key_1_a = string_prison.insert(String::from("World!"))?;
368 /// // string_prison.remove(key_1)?; // removal not needed
369 /// let key_1_b = string_prison.overwrite(1, String::from("Rust!!"))?;
370 /// string_prison.visit_many_ref(&[key_0, key_1_b], |vals| {
371 /// let hello_world = format!("{}{}", vals[0], vals[1]);
372 /// assert_eq!(hello_world, "Hello, Rust!!");
373 /// Ok(())
374 /// });
375 /// assert!(string_prison.visit_ref(key_1_a, |deleted_val| Ok(())).is_err());
376 /// assert!(string_prison.overwrite(10, String::from("Oops...")).is_err());
377 /// # Ok(())
378 /// # }
379 #[inline(always)]
380 pub fn overwrite(&self, idx: usize, value: T) -> Result<CellKey, AccessError> {
381 let internal: &mut PrisonInternal<T> = internal!(self);
382 if idx >= internal.vec.len() {
383 return Err(AccessError::IndexOutOfRange(idx));
384 }
385 match &mut internal.vec[idx] {
386 cell if cell.is_cell() => {
387 if cell.refs_or_next > 0 {
388 return Err(AccessError::OverwriteWhileValueReferenced(idx));
389 }
390 let cell_gen = IdxD::val(cell.d_gen_or_prev);
391 if cell_gen >= internal.generation {
392 if cell_gen == IdxD::MAX_GEN {
393 return Err(AccessError::MaxValueForGenerationReached);
394 }
395 internal.generation = cell_gen + 1;
396 }
397 cell.overwrite_cell_unchecked(value, internal.generation);
398 return Ok(CellKey {
399 idx,
400 gen: internal.generation,
401 });
402 }
403 free => {
404 let prev = IdxD::val(free.d_gen_or_prev);
405 if prev != IdxD::INVALID {
406 match &mut internal!(self).vec[prev] {
407 prev_free if prev_free.is_free() => prev_free.refs_or_next = free.refs_or_next,
408 _ => major_malfunction!("a `Free` index ({}) had a `prev_free` that pointed to an index ({}) that WAS NOT FREE", idx, prev) //COV_IGNORE
409 }
410 } else if internal.next_free == idx {
411 internal.next_free = free.refs_or_next;
412 } else {
413 major_malfunction!("a `free` index ({}) had a `prev_free` value that indicated `INVALID`, meaning it should have been the top of the `free` stack, but `Prison.next_free` ({}) did not match its index", prev, internal.next_free) //COV_IGNORE
414 }
415 if free.refs_or_next != IdxD::INVALID {
416 match &mut internal!(self).vec[free.refs_or_next] {
417 next_free if next_free.is_free() => next_free.d_gen_or_prev = IdxD::new_type_b(prev),
418 _ => major_malfunction!("a `Free` index ({}) had a `next_free` that pointed to an index ({}) that WAS NOT FREE", idx, free.refs_or_next) //COV_IGNORE
419 }
420 }
421 internal.free_count -= 1;
422 free.make_cell_unchecked(value, internal.generation);
423 return Ok(CellKey {
424 idx,
425 gen: internal.generation,
426 });
427 }
428 }
429 }
430
431 //FN Prison::remove()
432 /// Remove and return the element indexed by the provided [CellKey]
433 ///
434 /// As long as the element doesn't have an active reference you can `.remove()` it
435 /// ### Example
436 /// ```rust
437 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
438 /// # fn main() -> Result<(), AccessError> {
439 /// let string_prison: Prison<String> = Prison::with_capacity(15);
440 /// let key_0 = string_prison.insert(String::from("Hello, "))?;
441 /// let key_1 = string_prison.insert(String::from("World!"))?;
442 /// let mut take_world = String::new();
443 /// string_prison.visit_ref(key_0, |hello| {
444 /// take_world = string_prison.remove(key_1)?;
445 /// Ok(())
446 /// })?;
447 /// assert_eq!(take_world, "World!");
448 /// # Ok(())
449 /// # }
450 /// ```
451 /// However, if the element *does* have an active reference, either from `visit()` or `guard()`,
452 /// `remove()` will return an [AccessError::RemoveWhileValueReferenced(idx)] with the index in question
453 /// ### Example
454 /// ```rust
455 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
456 /// # fn main() -> Result<(), AccessError> {
457 /// let string_prison: Prison<String> = Prison::with_capacity(15);
458 /// let key_0 = string_prison.insert(String::from("Everything"))?;
459 /// string_prison.visit_ref(key_0, |everything| {
460 /// assert!(string_prison.remove(key_0).is_err());
461 /// Ok(())
462 /// })?;
463 /// # Ok(())
464 /// # }
465 /// ```
466 #[inline(always)]
467 pub fn remove(&self, key: CellKey) -> Result<T, AccessError> {
468 let internal = internal!(self);
469 if key.idx >= internal.vec.len() {
470 return Err(AccessError::IndexOutOfRange(key.idx));
471 }
472 let removed_val = match &mut internal.vec[key.idx] {
473 cell if cell.is_cell_and_gen_match(key.gen) => {
474 if cell.refs_or_next > 0 {
475 return Err(AccessError::RemoveWhileValueReferenced(key.idx));
476 }
477 let cell_gen = IdxD::val(cell.d_gen_or_prev);
478 if cell_gen >= internal.generation {
479 if cell_gen == IdxD::MAX_GEN {
480 return Err(AccessError::MaxValueForGenerationReached);
481 }
482 internal.generation = cell_gen + 1;
483 }
484 cell.make_free_unchecked(internal.next_free, IdxD::INVALID)
485 }
486 _ => return Err(AccessError::ValueDeleted(key.idx, key.gen)),
487 };
488 if internal.next_free != IdxD::INVALID {
489 match &mut internal.vec[internal.next_free] {
490 free if free.is_free() => {
491 free.d_gen_or_prev = IdxD::new_type_b(key.idx);
492 }
493 _ => major_malfunction!( //COV_IGNORE
494 "the `prison.next_free` index ({}) pointed to an element that WAS NOT FREE", //COV_IGNORE
495 internal.next_free //COV_IGNORE
496 ), //COV_IGNORE
497 }
498 }
499 internal.next_free = key.idx;
500 internal.free_count += 1;
501 return Ok(removed_val);
502 }
503
504 //FN Prison::remove_idx()
505 /// Remove and return the element at the specified index
506 ///
507 /// Like `remove()` but disregards the generation counter
508 ///
509 /// As long as the element doesnt have an active reference you can `.remove_idx()` it
510 /// ### Example
511 /// ```rust
512 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
513 /// # fn main() -> Result<(), AccessError> {
514 /// let string_prison: Prison<String> = Prison::with_capacity(15);
515 /// string_prison.insert(String::from("Hello, "))?;
516 /// string_prison.insert(String::from("World!"))?;
517 /// let mut take_world = String::new();
518 /// string_prison.visit_ref_idx(0, |hello| {
519 /// take_world = string_prison.remove_idx(1)?;
520 /// Ok(())
521 /// })?;
522 /// assert_eq!(take_world, "World!");
523 /// # Ok(())
524 /// # }
525 /// ```
526 /// However, if the element *does* have an active reference, either from `visit()` or `guard()`,
527 /// `.remove_idx()` will return an [AccessError::RemoveWhileValueReferenced(idx)] with the index in question
528 /// ### Example
529 /// ```rust
530 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
531 /// # fn main() -> Result<(), AccessError> {
532 /// let string_prison: Prison<String> = Prison::with_capacity(15);
533 /// string_prison.insert(String::from("Everything"))?;
534 /// string_prison.visit_ref_idx(0, |everything| {
535 /// assert!(string_prison.remove_idx(0).is_err());
536 /// Ok(())
537 /// })?;
538 /// # Ok(())
539 /// # }
540 /// ```
541 #[inline(always)]
542 pub fn remove_idx(&self, idx: usize) -> Result<T, AccessError> {
543 let internal = internal!(self);
544 if idx >= internal.vec.len() {
545 return Err(AccessError::IndexOutOfRange(idx));
546 }
547 let removed_val = match &mut internal.vec[idx] {
548 cell if cell.is_cell() => {
549 if cell.refs_or_next > 0 {
550 return Err(AccessError::RemoveWhileValueReferenced(idx));
551 }
552 let cell_gen = IdxD::val(cell.d_gen_or_prev);
553 if cell_gen >= internal.generation {
554 if cell_gen == IdxD::MAX_GEN {
555 return Err(AccessError::MaxValueForGenerationReached);
556 }
557 internal.generation = cell_gen + 1;
558 }
559 cell.make_free_unchecked(internal.next_free, IdxD::INVALID)
560 }
561 _ => return Err(AccessError::ValueDeleted(idx, 0)),
562 };
563 if internal.next_free != IdxD::INVALID {
564 match &mut internal.vec[internal.next_free] {
565 free if free.is_free() => {
566 free.d_gen_or_prev = IdxD::new_type_b(idx);
567 }
568 _ => major_malfunction!( //COV_IGNORE
569 "the `prison.next_free` index ({}) pointed to an element that WAS NOT FREE", //COV_IGNORE
570 internal.next_free //COV_IGNORE
571 ),
572 }
573 }
574 internal.next_free = idx;
575 internal.free_count += 1;
576 return Ok(removed_val);
577 }
578
579 //FN Prison::visit_mut()
580 /// Visit a single value in the [Prison], obtaining a mutable reference to the
581 /// value that is passed into a closure you provide.
582 ///
583 /// You can only obtain a single mutable reference to an element at any given time, and cannot move the mutable
584 /// reference out of the closure, meaning there is only one mutable reference to it at
585 /// any time (and zero immutable references).
586 /// ### Example
587 /// ```rust
588 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
589 /// # fn main() -> Result<(), AccessError> {
590 /// let u32_prison: Prison<u32> = Prison::new();
591 /// let key_0 = u32_prison.insert(42)?;
592 /// u32_prison.visit_mut(key_0, |mut_ref_42| {
593 /// *mut_ref_42 = 69; // nice
594 /// Ok(())
595 /// });
596 /// # Ok(())
597 /// # }
598 /// ```
599 /// ## Errors
600 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
601 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if element has any number of immutable references
602 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
603 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted *OR* the [CellKey] generation doe not match
604 /// ### Example
605 /// ```rust
606 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
607 /// # fn main() -> Result<(), AccessError> {
608 /// let u32_prison: Prison<u32> = Prison::new();
609 /// let key_0 = u32_prison.insert(42)?;
610 /// let key_1 = u32_prison.insert(69)?;
611 /// u32_prison.remove(key_1)?;
612 /// u32_prison.visit_mut(key_0, |mut_ref_42| {
613 /// assert!(u32_prison.visit_mut(key_0, |mut_ref_42_again| Ok(())).is_err());
614 /// assert!(u32_prison.visit_ref(key_0, |mut_ref_42_again| Ok(())).is_err());
615 /// assert!(u32_prison.visit_mut(CellKey::from_raw_parts(5, 5), |doesnt_exist| Ok(())).is_err());
616 /// assert!(u32_prison.visit_mut(key_1, |deleted| Ok(())).is_err());
617 /// Ok(())
618 /// })?;
619 /// # Ok(())
620 /// # }
621 /// ```
622 /// ### Example
623 /// ```compile_fail
624 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
625 /// # fn main() -> Result<(), AccessError> {
626 /// let u32_prison: Prison<u32> = Prison::new();
627 /// let key_0 = u32_prison.insert(42)?;
628 /// let mut try_to_take_the_ref: &mut u32 = &mut 0;
629 /// u32_prison.visit_mut(key_0, |mut_ref_42| {
630 /// // will not compile: (error[E0521]: borrowed data escapes outside of closure)
631 /// try_to_take_the_ref = mut_ref_42;
632 /// Ok(())
633 /// })?;
634 /// # Ok(())
635 /// # }
636 /// ```
637 #[inline(always)]
638 pub fn visit_mut<F>(&self, key: CellKey, mut operation: F) -> Result<(), AccessError>
639 where
640 F: FnMut(&mut T) -> Result<(), AccessError>,
641 {
642 let (cell, accesses) = self._add_mut_ref(key.idx, key.gen, true)?;
643 let res = operation(unsafe { cell.val.assume_init_mut() });
644 _remove_mut_ref(&mut cell.refs_or_next, accesses);
645 return res;
646 }
647
648 //FN Prison::visit_ref()
649 /// Visit a single value in the [Prison], obtaining an immutable reference to the
650 /// value that is passed into a closure you provide.
651 ///
652 /// You obtain any number of simultaneous immutable references to an element,
653 /// cannot obtain a mutable reference while any immutable references are active,
654 /// and cannot move the immutable references out of the closure,
655 /// ### Example
656 /// ```rust
657 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
658 /// # fn main() -> Result<(), AccessError> {
659 /// let u32_prison: Prison<u32> = Prison::new();
660 /// let key_0 = u32_prison.insert(42)?;
661 /// u32_prison.visit_ref(key_0, |ref_42_a| {
662 /// u32_prison.visit_ref(key_0, |ref_42_b| {
663 /// assert_eq!(*ref_42_a, *ref_42_b);
664 /// Ok(())
665 /// });
666 /// Ok(())
667 /// });
668 /// # Ok(())
669 /// # }
670 /// ```
671 /// ## Errors
672 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
673 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references already
674 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
675 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted *OR* the [CellKey] generation doe not match
676 /// ### Example
677 /// ```rust
678 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
679 /// # fn main() -> Result<(), AccessError> {
680 /// let u32_prison: Prison<u32> = Prison::new();
681 /// let key_0 = u32_prison.insert(42)?;
682 /// let key_1 = u32_prison.insert(69)?;
683 /// u32_prison.remove(key_1)?;
684 /// u32_prison.visit_ref(key_0, |ref_42| {
685 /// assert!(u32_prison.visit_mut(key_0, |mut_ref_42| Ok(())).is_err());
686 /// assert!(u32_prison.visit_ref(CellKey::from_raw_parts(5, 5), |doesnt_exist| Ok(())).is_err());
687 /// assert!(u32_prison.visit_ref(key_1, |deleted| Ok(())).is_err());
688 /// Ok(())
689 /// })?;
690 /// # Ok(())
691 /// # }
692 /// ```
693 /// ### Example
694 /// ```compile_fail
695 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
696 /// # fn main() -> Result<(), AccessError> {
697 /// let u32_prison: Prison<u32> = Prison::new();
698 /// let key_0 = u32_prison.insert(42)?;
699 /// let mut try_to_take_the_ref: & u32 = & 0;
700 /// u32_prison.visit_ref(key_0, |ref_42| {
701 /// // will not compile: (error[E0521]: borrowed data escapes outside of closure)
702 /// try_to_take_the_ref = ref_42;
703 /// Ok(())
704 /// })?;
705 /// # Ok(())
706 /// # }
707 /// ```
708 #[inline(always)]
709 pub fn visit_ref<F>(&self, key: CellKey, mut operation: F) -> Result<(), AccessError>
710 where
711 F: FnMut(&T) -> Result<(), AccessError>,
712 {
713 let (cell, accesses) = self._add_imm_ref(key.idx, key.gen, true)?;
714 let res = operation(unsafe { cell.val.assume_init_ref() });
715 _remove_imm_ref(&mut cell.refs_or_next, accesses);
716 return res;
717 }
718
719 //FN Prison::visit_mut_idx()
720 /// Visit a single value in the [Prison], obtaining a mutable reference to the
721 /// value that is passed into a closure you provide.
722 ///
723 /// Similar to `visit_mut()` but ignores the generation counter
724 ///
725 /// You can only obtain a single mutable reference to an element at any given time, and cannot move the mutable
726 /// reference out of the closure, meaning there is only one mutable reference to it at
727 /// any time (and zero immutable references).
728 /// ### Example
729 /// ```rust
730 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
731 /// # fn main() -> Result<(), AccessError> {
732 /// let u32_prison: Prison<u32> = Prison::new();
733 /// u32_prison.insert(42)?;
734 /// u32_prison.visit_mut_idx(0, |mut_ref_42| {
735 /// *mut_ref_42 = 69; // nice
736 /// Ok(())
737 /// });
738 /// # Ok(())
739 /// # }
740 /// ```
741 /// ## Errors
742 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
743 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if element has any number of immutable references
744 /// - [AccessError::IndexOutOfRange(idx)] if the index is out of range
745 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted
746 /// ### Example
747 /// ```rust
748 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
749 /// # fn main() -> Result<(), AccessError> {
750 /// let u32_prison: Prison<u32> = Prison::new();
751 /// u32_prison.insert(42)?;
752 /// u32_prison.insert(69)?;
753 /// u32_prison.remove_idx(1)?;
754 /// u32_prison.visit_mut_idx(0, |mut_ref_42| {
755 /// assert!(u32_prison.visit_mut_idx(0, |mut_ref_42_again| Ok(())).is_err());
756 /// assert!(u32_prison.visit_ref_idx(0, |mut_ref_42_again| Ok(())).is_err());
757 /// assert!(u32_prison.visit_mut_idx(5, |doesnt_exist| Ok(())).is_err());
758 /// assert!(u32_prison.visit_mut_idx(1, |deleted| Ok(())).is_err());
759 /// Ok(())
760 /// })?;
761 /// # Ok(())
762 /// # }
763 /// ```
764 /// ### Example
765 /// ```compile_fail
766 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
767 /// # fn main() -> Result<(), AccessError> {
768 /// let u32_prison: Prison<u32> = Prison::new();
769 /// u32_prison.insert(42)?;
770 /// let mut try_to_take_the_ref: &mut u32 = &mut 0;
771 /// u32_prison.visit_mut_idx(0, |mut_ref_42| {
772 /// // will not compile: (error[E0521]: borrowed data escapes outside of closure)
773 /// try_to_take_the_ref = mut_ref_42;
774 /// Ok(())
775 /// })?;
776 /// # Ok(())
777 /// # }
778 /// ```
779 #[inline(always)]
780 pub fn visit_mut_idx<F>(&self, idx: usize, mut operation: F) -> Result<(), AccessError>
781 where
782 F: FnMut(&mut T) -> Result<(), AccessError>,
783 {
784 let (cell, accesses) = self._add_mut_ref(idx, 0, false)?;
785 let res = operation(unsafe { cell.val.assume_init_mut() });
786 _remove_mut_ref(&mut cell.refs_or_next, accesses);
787 return res;
788 }
789
790 //FN Prison::visit_ref_idx()
791 /// Visit a single value in the [Prison], obtaining an immutable reference to the
792 /// value that is passed into a closure you provide.
793 ///
794 /// Similar to `visit_ref()` but ignores the generation counter
795 ///
796 /// You obtain any number of simultaneous immutable references to an element,
797 /// cannot obtain a mutable reference while any immutable references are active,
798 /// and cannot move the immutable references out of the closure,
799 /// ### Example
800 /// ```rust
801 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
802 /// # fn main() -> Result<(), AccessError> {
803 /// let u32_prison: Prison<u32> = Prison::new();
804 /// u32_prison.insert(42)?;
805 /// u32_prison.visit_ref_idx(0, |ref_42_a| {
806 /// u32_prison.visit_ref_idx(0, |ref_42_b| {
807 /// assert_eq!(*ref_42_a, *ref_42_b);
808 /// Ok(())
809 /// });
810 /// Ok(())
811 /// });
812 /// # Ok(())
813 /// # }
814 /// ```
815 /// ## Errors
816 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
817 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references already
818 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
819 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted
820 /// ### Example
821 /// ```rust
822 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
823 /// # fn main() -> Result<(), AccessError> {
824 /// let u32_prison: Prison<u32> = Prison::new();
825 /// u32_prison.insert(42)?;
826 /// u32_prison.insert(69)?;
827 /// u32_prison.remove_idx(1)?;
828 /// u32_prison.visit_ref_idx(0, |ref_42| {
829 /// assert!(u32_prison.visit_mut_idx(0, |mut_ref_42| Ok(())).is_err());
830 /// assert!(u32_prison.visit_ref_idx(5, |doesnt_exist| Ok(())).is_err());
831 /// assert!(u32_prison.visit_ref_idx(1, |deleted| Ok(())).is_err());
832 /// Ok(())
833 /// })?;
834 /// # Ok(())
835 /// # }
836 /// ```
837 /// ### Example
838 /// ```compile_fail
839 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
840 /// # fn main() -> Result<(), AccessError> {
841 /// let u32_prison: Prison<u32> = Prison::new();
842 /// u32_prison.insert(42)?;
843 /// let mut try_to_take_the_ref: & u32 = & 0;
844 /// u32_prison.visit_ref_idx(0, |ref_42| {
845 /// // will not compile: (error[E0521]: borrowed data escapes outside of closure)
846 /// try_to_take_the_ref = ref_42;
847 /// Ok(())
848 /// })?;
849 /// # Ok(())
850 /// # }
851 /// ```
852 #[inline(always)]
853 pub fn visit_ref_idx<F>(&self, idx: usize, mut operation: F) -> Result<(), AccessError>
854 where
855 F: FnMut(&T) -> Result<(), AccessError>,
856 {
857 let (cell, accesses) = self._add_imm_ref(idx, 0, false)?;
858 let res = operation(unsafe { cell.val.assume_init_ref() });
859 _remove_imm_ref(&mut cell.refs_or_next, accesses);
860 return res;
861 }
862
863 //FN Prison::visit_many_mut()
864 /// Visit many values in the [Prison] at the same time, obtaining a mutable reference
865 /// to all of them in the same closure and in the same order they were requested.
866 ///
867 /// While you can obtain multiple unrelated mutable references simultaneously,
868 /// you can only obtain a single mutable reference to the same element at any given time, and cannot move the mutable
869 /// reference out of the closure, meaning there is only one mutable reference to it at
870 /// any time (and zero immutable references).
871 /// ### Example
872 /// ```rust
873 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
874 /// # fn main() -> Result<(), AccessError> {
875 /// let u32_prison: Prison<u32> = Prison::new();
876 /// let key_0 = u32_prison.insert(42)?;
877 /// let key_1 = u32_prison.insert(43)?;
878 /// let key_2 = u32_prison.insert(44)?;
879 /// let key_3 = u32_prison.insert(45)?;
880 /// u32_prison.visit_many_mut(&[key_3, key_2, key_1, key_0], |first_four_reversed| {
881 /// assert_eq!(*first_four_reversed[0], 45);
882 /// assert_eq!(*first_four_reversed[1], 44);
883 /// assert_eq!(*first_four_reversed[2], 43);
884 /// assert_eq!(*first_four_reversed[3], 42);
885 /// Ok(())
886 /// })?;
887 /// # Ok(())
888 /// # }
889 /// ```
890 /// Just like `.visit_mut()`, any particular element can only have one mutable reference,
891 /// but as long as the elements requested don't overlap you may make nested
892 /// `visit()` or `guard()` calls
893 /// ### Example
894 /// ```rust
895 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
896 /// # fn main() -> Result<(), AccessError> {
897 /// let u32_prison: Prison<u32> = Prison::new();
898 /// let key_0 = u32_prison.insert(42)?;
899 /// let key_1 = u32_prison.insert(43)?;
900 /// let key_2 = u32_prison.insert(44)?;
901 /// let key_3 = u32_prison.insert(45)?;
902 /// u32_prison.visit_many_mut(&[key_0, key_2], |evens| {
903 /// u32_prison.visit_many_mut(&[key_1, key_3], |odds| {
904 /// assert_eq!(*evens[1], 44);
905 /// assert_eq!(*odds[1], 45);
906 /// Ok(())
907 /// });
908 /// Ok(())
909 /// });
910 /// # Ok(())
911 /// # }
912 /// ```
913 /// ## Errors
914 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
915 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if any element has any number of immutable references
916 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
917 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted *OR* the [CellKey] generation doesnt match
918 /// ### Example
919 /// ```rust
920 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
921 /// # fn main() -> Result<(), AccessError> {
922 /// let u32_prison: Prison<u32> = Prison::new();
923 /// let key_0 = u32_prison.insert(42)?;
924 /// let key_1 = u32_prison.insert(43)?;
925 /// let key_2 = u32_prison.insert(44)?;
926 /// let key_3 = u32_prison.insert(45)?;
927 /// u32_prison.remove(key_1)?;
928 /// let key_4 = CellKey::from_raw_parts(4, 1);
929 /// assert!(u32_prison.visit_many_mut(&[key_0, key_0], |double_key_zero| Ok(())).is_err());
930 /// assert!(u32_prison.visit_many_mut(&[key_1, key_2, key_3], |key_1_removed| Ok(())).is_err());
931 /// assert!(u32_prison.visit_many_mut(&[key_2, key_3, key_4], |key_4_invalid| Ok(())).is_err());
932 /// # Ok(())
933 /// # }
934 /// ```
935 pub fn visit_many_mut<F>(&self, keys: &[CellKey], mut operation: F) -> Result<(), AccessError>
936 where
937 F: FnMut(&mut [&mut T]) -> Result<(), AccessError>,
938 {
939 let (mut vals, mut refs, accesses) = self._add_many_mut_refs(keys)?;
940 let result = operation(&mut vals);
941 _remove_many_mut_refs(&mut refs, accesses);
942 return result;
943 }
944
945 //FN Prison::visit_many_ref()
946 /// Visit many values in the [Prison] at the same time, obtaining an immutable reference
947 /// to all of them in the same closure and in the same order they were requested.
948 ///
949 /// As long as the element does not have any mutable references, you can obtain multiple
950 /// immutable references to the same element
951 /// ### Example
952 /// ```rust
953 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
954 /// # fn main() -> Result<(), AccessError> {
955 /// let u32_prison: Prison<u32> = Prison::new();
956 /// let key_0 = u32_prison.insert(42)?;
957 /// let key_1 = u32_prison.insert(43)?;
958 /// let key_2 = u32_prison.insert(44)?;
959 /// let key_3 = u32_prison.insert(45)?;
960 /// u32_prison.visit_many_ref(&[key_3, key_2, key_1, key_0], |first_four_reversed| {
961 /// assert_eq!(*first_four_reversed[0], 45);
962 /// assert_eq!(*first_four_reversed[1], 44);
963 /// assert_eq!(*first_four_reversed[2], 43);
964 /// assert_eq!(*first_four_reversed[3], 42);
965 /// u32_prison.visit_many_ref(&[key_0, key_1, key_2, key_3], |first_four_original| {
966 /// assert_eq!(*first_four_original[0], 42);
967 /// assert_eq!(*first_four_original[1], 43);
968 /// assert_eq!(*first_four_original[2], 44);
969 /// assert_eq!(*first_four_original[3], 45);
970 /// Ok(())
971 /// })?;
972 /// Ok(())
973 /// })?;
974 /// # Ok(())
975 /// # }
976 /// ```
977 /// Just like `.visit_ref()`, any particular element can have multile immutable references to
978 /// it as long as it has no mutable, meaning you can make nested
979 /// `visit()` or `guard()` calls to the same element if desired
980 /// ### Example
981 /// ```rust
982 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
983 /// # fn main() -> Result<(), AccessError> {
984 /// let u32_prison: Prison<u32> = Prison::new();
985 /// let key_0 = u32_prison.insert(42)?;
986 /// let key_1 = u32_prison.insert(43)?;
987 /// let key_2 = u32_prison.insert(44)?;
988 /// let key_3 = u32_prison.insert(45)?;
989 /// u32_prison.visit_many_ref(&[key_0, key_2], |evens| {
990 /// u32_prison.visit_many_ref(&[key_1, key_3], |odds| {
991 /// assert_eq!(*evens[1], 44);
992 /// assert_eq!(*odds[1], 45);
993 /// assert!(u32_prison.visit_many_ref(&[key_0, key_1, key_2, key_3], |all| Ok(())).is_ok());
994 /// Ok(())
995 /// });
996 /// Ok(())
997 /// });
998 /// # Ok(())
999 /// # }
1000 /// ```
1001 /// ## Errors
1002 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1003 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references to any element
1004 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1005 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted *OR* if the [CellKey] generation doesn't match
1006 /// ### Example
1007 /// ```rust
1008 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1009 /// # fn main() -> Result<(), AccessError> {
1010 /// let u32_prison: Prison<u32> = Prison::new();
1011 /// let key_0 = u32_prison.insert(42)?;
1012 /// let key_1 = u32_prison.insert(43)?;
1013 /// let key_2 = u32_prison.insert(44)?;
1014 /// let key_3 = u32_prison.insert(45)?;
1015 /// u32_prison.remove(key_1)?;
1016 /// let key_4 = CellKey::from_raw_parts(4, 1);
1017 /// u32_prison.visit_mut(key_0, |mut_0| {
1018 /// assert!(u32_prison.visit_many_ref(&[key_0], |zero_already_mut| Ok(())).is_err());
1019 /// assert!(u32_prison.visit_many_ref(&[key_1, key_2, key_3], |key_1_removed| Ok(())).is_err());
1020 /// assert!(u32_prison.visit_many_ref(&[key_2, key_3, key_4], |key_4_invalid| Ok(())).is_err());
1021 /// Ok(())
1022 /// })?;
1023 /// # Ok(())
1024 /// # }
1025 /// ```
1026 pub fn visit_many_ref<F>(&self, keys: &[CellKey], mut operation: F) -> Result<(), AccessError>
1027 where
1028 F: FnMut(&[&T]) -> Result<(), AccessError>,
1029 {
1030 let (vals, mut refs, accesses) = self._add_many_imm_refs(keys)?;
1031 let result = operation(&vals);
1032 _remove_many_imm_refs(&mut refs, accesses);
1033 return result;
1034 }
1035
1036 //FN Prison::visit_many_mut_idx()
1037 /// Visit many values in the [Prison] at the same time, obtaining a mutable reference
1038 /// to all of them in the same closure and in the same order they were requested.
1039 ///
1040 /// Similar to `visit_many_mut()` but ignores the generation counter
1041 ///
1042 /// While you can obtain multiple unrelated mutable references simultaneously,
1043 /// you can only obtain a single mutable reference to the same element at any given time, and cannot move the mutable
1044 /// reference out of the closure, meaning there is only one mutable reference to it at
1045 /// any time (and zero immutable references).
1046 /// ### Example
1047 /// ```rust
1048 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1049 /// # fn main() -> Result<(), AccessError> {
1050 /// let u32_prison: Prison<u32> = Prison::new();
1051 /// u32_prison.insert(42)?;
1052 /// u32_prison.insert(43)?;
1053 /// u32_prison.insert(44)?;
1054 /// u32_prison.insert(45)?;
1055 /// u32_prison.visit_many_mut_idx(&[3, 2, 1, 0], |first_four_reversed| {
1056 /// assert_eq!(*first_four_reversed[0], 45);
1057 /// assert_eq!(*first_four_reversed[1], 44);
1058 /// assert_eq!(*first_four_reversed[2], 43);
1059 /// assert_eq!(*first_four_reversed[3], 42);
1060 /// Ok(())
1061 /// })?;
1062 /// # Ok(())
1063 /// # }
1064 /// ```
1065 /// Just like `.visit_mut_idx()`, any particular element can only have one mutable reference,
1066 /// but as long as the elements requested don't overlap you may make nested
1067 /// `visit()` or `guard()` calls
1068 /// ### Example
1069 /// ```rust
1070 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1071 /// # fn main() -> Result<(), AccessError> {
1072 /// let u32_prison: Prison<u32> = Prison::new();
1073 /// u32_prison.insert(42)?;
1074 /// u32_prison.insert(43)?;
1075 /// u32_prison.insert(44)?;
1076 /// u32_prison.insert(45)?;
1077 /// u32_prison.visit_many_mut_idx(&[0, 2], |evens| {
1078 /// u32_prison.visit_many_mut_idx(&[1, 3], |odds| {
1079 /// assert_eq!(*evens[1], 44);
1080 /// assert_eq!(*odds[1], 45);
1081 /// Ok(())
1082 /// });
1083 /// Ok(())
1084 /// });
1085 /// # Ok(())
1086 /// # }
1087 /// ```
1088 /// ## Errors
1089 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1090 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if any element has any number of immutable references
1091 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1092 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted
1093 /// ### Example
1094 /// ```rust
1095 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1096 /// # fn main() -> Result<(), AccessError> {
1097 /// let u32_prison: Prison<u32> = Prison::new();
1098 /// u32_prison.insert(42)?;
1099 /// u32_prison.insert(43)?;
1100 /// u32_prison.insert(44)?;
1101 /// u32_prison.insert(45)?;
1102 /// u32_prison.remove_idx(1)?;
1103 /// assert!(u32_prison.visit_many_mut_idx(&[0, 0], |double_idx_zero| Ok(())).is_err());
1104 /// assert!(u32_prison.visit_many_mut_idx(&[1, 2, 3], |idx_1_removed| Ok(())).is_err());
1105 /// assert!(u32_prison.visit_many_mut_idx(&[2, 3, 4], |idx_4_invalid| Ok(())).is_err());
1106 /// # Ok(())
1107 /// # }
1108 /// ```
1109 pub fn visit_many_mut_idx<F>(
1110 &self,
1111 indexes: &[usize],
1112 mut operation: F,
1113 ) -> Result<(), AccessError>
1114 where
1115 F: FnMut(&mut [&mut T]) -> Result<(), AccessError>,
1116 {
1117 let (mut vals, mut refs, accesses) = self._add_many_mut_refs_idx(indexes)?;
1118 let result = operation(&mut vals);
1119 _remove_many_mut_refs(&mut refs, accesses);
1120 return result;
1121 }
1122
1123 //FN Prison::visit_many_ref_idx()
1124 /// Visit many values in the [Prison] at the same time, obtaining an immutable reference
1125 /// to all of them in the same closure and in the same order they were requested.
1126 ///
1127 /// Similar to `visit_many_ref()` but ignores the generation counter
1128 ///
1129 /// As long as the element does not have any mutable references, you can obtain multiple
1130 /// immutable references to the same element
1131 /// ### Example
1132 /// ```rust
1133 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1134 /// # fn main() -> Result<(), AccessError> {
1135 /// let u32_prison: Prison<u32> = Prison::new();
1136 /// u32_prison.insert(42)?;
1137 /// u32_prison.insert(43)?;
1138 /// u32_prison.insert(44)?;
1139 /// u32_prison.insert(45)?;
1140 /// u32_prison.visit_many_ref_idx(&[3, 2, 1, 0], |first_four_reversed| {
1141 /// assert_eq!(*first_four_reversed[0], 45);
1142 /// assert_eq!(*first_four_reversed[1], 44);
1143 /// assert_eq!(*first_four_reversed[2], 43);
1144 /// assert_eq!(*first_four_reversed[3], 42);
1145 /// u32_prison.visit_many_ref_idx(&[0, 1, 2, 3], |first_four_original| {
1146 /// assert_eq!(*first_four_original[0], 42);
1147 /// assert_eq!(*first_four_original[1], 43);
1148 /// assert_eq!(*first_four_original[2], 44);
1149 /// assert_eq!(*first_four_original[3], 45);
1150 /// Ok(())
1151 /// })?;
1152 /// Ok(())
1153 /// })?;
1154 /// # Ok(())
1155 /// # }
1156 /// ```
1157 /// Just like `.visit_ref_idx()`, any particular element can have multiple immutable references to
1158 /// it as long as it has no mutable references, meaning you can make nested
1159 /// `visit()` or `guard()` calls to the same element if desired
1160 /// ### Example
1161 /// ```rust
1162 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1163 /// # fn main() -> Result<(), AccessError> {
1164 /// let u32_prison: Prison<u32> = Prison::new();
1165 /// u32_prison.insert(42)?;
1166 /// u32_prison.insert(43)?;
1167 /// u32_prison.insert(44)?;
1168 /// u32_prison.insert(45)?;
1169 /// u32_prison.visit_many_ref_idx(&[0, 2], |evens| {
1170 /// u32_prison.visit_many_ref_idx(&[1, 3], |odds| {
1171 /// assert_eq!(*evens[1], 44);
1172 /// assert_eq!(*odds[1], 45);
1173 /// assert!(u32_prison.visit_many_ref_idx(&[0, 1, 2, 3], |all| Ok(())).is_ok());
1174 /// Ok(())
1175 /// });
1176 /// Ok(())
1177 /// });
1178 /// # Ok(())
1179 /// # }
1180 /// ```
1181 /// ## Errors
1182 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1183 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references to any element
1184 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1185 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted
1186 /// ### Example
1187 /// ```rust
1188 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1189 /// # fn main() -> Result<(), AccessError> {
1190 /// let u32_prison: Prison<u32> = Prison::new();
1191 /// u32_prison.insert(42)?;
1192 /// u32_prison.insert(43)?;
1193 /// u32_prison.insert(44)?;
1194 /// u32_prison.insert(45)?;
1195 /// u32_prison.remove_idx(1)?;
1196 /// u32_prison.visit_mut_idx(0, |mut_0| {
1197 /// assert!(u32_prison.visit_many_ref_idx(&[0], |zero_already_mut| Ok(())).is_err());
1198 /// assert!(u32_prison.visit_many_ref_idx(&[1, 2, 3], |idx_1_removed| Ok(())).is_err());
1199 /// assert!(u32_prison.visit_many_ref_idx(&[2, 3, 4], |idx_4_invalid| Ok(())).is_err());
1200 /// Ok(())
1201 /// })?;
1202 /// # Ok(())
1203 /// # }
1204 /// ```
1205 pub fn visit_many_ref_idx<F>(
1206 &self,
1207 indexes: &[usize],
1208 mut operation: F,
1209 ) -> Result<(), AccessError>
1210 where
1211 F: FnMut(&[&T]) -> Result<(), AccessError>,
1212 {
1213 let (vals, mut refs, accesses) = self._add_many_imm_refs_idx(indexes)?;
1214 let result = operation(&vals);
1215 _remove_many_imm_refs(&mut refs, accesses);
1216 return result;
1217 }
1218
1219 //FN Prison::visit_slice_mut()
1220 /// Visit a slice of values in the [Prison] at the same time, obtaining a mutable reference
1221 /// to all of them in the same closure.
1222 ///
1223 /// Internally this is strictly identical to passing [Prison::visit_many_mut_idx()] a list of all
1224 /// indexes in the slice range, and is subject to all the same restrictions and errors
1225 /// ### Example
1226 /// ```rust
1227 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1228 /// # fn main() -> Result<(), AccessError> {
1229 /// let u32_prison: Prison<u32> = Prison::new();
1230 /// u32_prison.insert(42)?;
1231 /// u32_prison.insert(43)?;
1232 /// u32_prison.insert(44)?;
1233 /// u32_prison.insert(45)?;
1234 /// u32_prison.insert(46)?;
1235 /// u32_prison.visit_slice_mut(2..5, |last_three| {
1236 /// assert_eq!(*last_three[0], 44);
1237 /// assert_eq!(*last_three[1], 45);
1238 /// assert_eq!(*last_three[2], 46);
1239 /// Ok(())
1240 /// });
1241 /// # Ok(())
1242 /// # }
1243 /// ```
1244 /// Any standard [Range<usize>](std::ops::Range) notation is allowed as the first paramater,
1245 /// but care must be taken because it is not guaranteed every index within range is a valid
1246 /// value or does not have any other references to it that would violate Rust's memory safety.
1247 /// ### Example
1248 /// ```rust
1249 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1250 /// # fn main() -> Result<(), AccessError> {
1251 /// let u32_prison: Prison<u32> = Prison::new();
1252 /// u32_prison.insert(42)?;
1253 /// u32_prison.insert(43)?;
1254 /// u32_prison.insert(44)?;
1255 /// u32_prison.insert(45)?;
1256 /// u32_prison.insert(46)?;
1257 /// assert!(u32_prison.visit_slice_mut(2..5, |last_three| Ok(())).is_ok());
1258 /// assert!(u32_prison.visit_slice_mut(2..=4, |also_last_three| Ok(())).is_ok());
1259 /// assert!(u32_prison.visit_slice_mut(2.., |again_last_three| Ok(())).is_ok());
1260 /// assert!(u32_prison.visit_slice_mut(..3, |first_three| Ok(())).is_ok());
1261 /// assert!(u32_prison.visit_slice_mut(..=3, |first_four| Ok(())).is_ok());
1262 /// assert!(u32_prison.visit_slice_mut(.., |all| Ok(())).is_ok());
1263 /// u32_prison.remove_idx(2)?;
1264 /// assert!(u32_prison.visit_slice_mut(.., |all| Ok(())).is_err());
1265 /// # Ok(())
1266 /// # }
1267 /// ```
1268 /// See [Prison::visit_many_mut_idx()] for more info
1269 pub fn visit_slice_mut<R, F>(&self, range: R, operation: F) -> Result<(), AccessError>
1270 where
1271 R: RangeBounds<usize>,
1272 F: FnMut(&mut [&mut T]) -> Result<(), AccessError>,
1273 {
1274 let (start, end) = extract_true_start_end(range, self.vec_len());
1275 let idxs: Vec<usize> = (start..end).collect();
1276 self.visit_many_mut_idx(&idxs, operation)
1277 }
1278
1279 //FN Prison::visit_slice_ref()
1280 /// Visit a slice of values in the [Prison] at the same time, obtaining an immutable reference
1281 /// to all of them in the same closure.
1282 ///
1283 /// Internally this is strictly identical to passing [Prison::visit_many_ref_idx()] a list of all
1284 /// indexes in the slice range, and is subject to all the same restrictions and errors
1285 /// ### Example
1286 /// ```rust
1287 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1288 /// # fn main() -> Result<(), AccessError> {
1289 /// let u32_prison: Prison<u32> = Prison::new();
1290 /// u32_prison.insert(42)?;
1291 /// u32_prison.insert(43)?;
1292 /// u32_prison.insert(44)?;
1293 /// u32_prison.insert(45)?;
1294 /// u32_prison.insert(46)?;
1295 /// u32_prison.visit_slice_ref(2..5, |last_three| {
1296 /// assert_eq!(*last_three[0], 44);
1297 /// assert_eq!(*last_three[1], 45);
1298 /// assert_eq!(*last_three[2], 46);
1299 /// u32_prison.visit_slice_ref(0..3, |first_three| {
1300 /// assert_eq!(*first_three[0], 42);
1301 /// assert_eq!(*first_three[1], 43);
1302 /// assert_eq!(*first_three[2], 44);
1303 /// Ok(())
1304 /// });
1305 /// Ok(())
1306 /// });
1307 /// # Ok(())
1308 /// # }
1309 /// ```
1310 /// Any standard [Range<usize>](std::ops::Range) notation is allowed as the first paramater,
1311 /// but care must be taken because it is not guaranteed every index within range is a valid
1312 /// value or does not have any other references to it that would violate Rust's memory safety.
1313 /// ### Example
1314 /// ```rust
1315 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1316 /// # fn main() -> Result<(), AccessError> {
1317 /// let u32_prison: Prison<u32> = Prison::new();
1318 /// u32_prison.insert(42)?;
1319 /// u32_prison.insert(43)?;
1320 /// u32_prison.insert(44)?;
1321 /// u32_prison.insert(45)?;
1322 /// u32_prison.insert(46)?;
1323 /// assert!(u32_prison.visit_slice_ref(2..5, |last_three| Ok(())).is_ok());
1324 /// assert!(u32_prison.visit_slice_ref(2..=4, |also_last_three| Ok(())).is_ok());
1325 /// assert!(u32_prison.visit_slice_ref(2.., |again_last_three| Ok(())).is_ok());
1326 /// assert!(u32_prison.visit_slice_ref(..3, |first_three| Ok(())).is_ok());
1327 /// assert!(u32_prison.visit_slice_ref(..=3, |first_four| Ok(())).is_ok());
1328 /// assert!(u32_prison.visit_slice_ref(.., |all| Ok(())).is_ok());
1329 /// u32_prison.remove_idx(2)?;
1330 /// assert!(u32_prison.visit_slice_ref(.., |all| Ok(())).is_err());
1331 /// # Ok(())
1332 /// # }
1333 /// ```
1334 /// See [Prison::visit_many_ref_idx()] for more info
1335 pub fn visit_slice_ref<R, F>(&self, range: R, operation: F) -> Result<(), AccessError>
1336 where
1337 R: RangeBounds<usize>,
1338 F: FnMut(&[&T]) -> Result<(), AccessError>,
1339 {
1340 let (start, end) = extract_true_start_end(range, self.vec_len());
1341 let idxs: Vec<usize> = (start..end).collect();
1342 self.visit_many_ref_idx(&idxs, operation)
1343 }
1344
1345 //FN Prison::guard_mut()
1346 /// Return a [PrisonValueMut] that contains a mutable reference to the element and wraps it in
1347 /// guarding data that automatically frees its reference count it when it goes out of scope.
1348 ///
1349 /// [PrisonValueMut<T>] implements [Deref<Target = T>], [DerefMut<Target = T>], [AsRef<T>], [AsMut<T>],
1350 /// [Borrow<T>], and [BorrowMut<T>] to allow transparent access to its underlying value
1351 ///
1352 /// As long as the [PrisonValueMut] remains in scope, the element where it's value resides in the
1353 /// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
1354 /// You can manually drop the [PrisonValueMut] out of scope by passing it as the first parameter
1355 /// to the function [PrisonValueMut::unguard(p_val_mut)]
1356 /// ### Example
1357 /// ```rust
1358 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1359 /// # fn main() -> Result<(), AccessError> {
1360 /// let prison: Prison<u32> = Prison::new();
1361 /// let key_0 = prison.insert(10)?;
1362 /// let mut grd_0 = prison.guard_mut(key_0)?;
1363 /// assert_eq!(*grd_0, 10);
1364 /// *grd_0 = 20;
1365 /// PrisonValueMut::unguard(grd_0);
1366 /// prison.visit_ref(key_0, |val_0| {
1367 /// assert_eq!(*val_0, 20);
1368 /// Ok(())
1369 /// });
1370 /// # Ok(())
1371 /// # }
1372 /// ```
1373 /// ## Errors
1374 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
1375 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if element has any number of immutable references
1376 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
1377 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted *OR* the [CellKey] generation does not match
1378 /// ### Example
1379 /// ```rust
1380 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1381 /// # fn main() -> Result<(), AccessError> {
1382 /// let prison: Prison<u32> = Prison::with_capacity(2);
1383 /// let key_0 = prison.insert(10)?;
1384 /// let key_1_a = prison.insert(20)?;
1385 /// let key_out_of_bounds = CellKey::from_raw_parts(10, 0);
1386 /// prison.remove(key_1_a)?;
1387 /// let key_1_b = prison.insert(30)?;
1388 /// let mut grd_0 = prison.guard_mut(key_0)?;
1389 /// assert!(prison.guard_mut(key_0).is_err());
1390 /// assert!(prison.guard_mut(key_out_of_bounds).is_err());
1391 /// assert!(prison.guard_mut(key_1_a).is_err());
1392 /// # Ok(())
1393 /// # }
1394 /// ```
1395 #[must_use = "guarded reference will immediately fall out of scope"]
1396 pub fn guard_mut<'a>(&'a self, key: CellKey) -> Result<PrisonValueMut<'a, T>, AccessError> {
1397 let (cell, visits) = self._add_mut_ref(key.idx, key.gen, true)?;
1398 return Ok(PrisonValueMut {
1399 cell,
1400 prison_accesses: visits,
1401 });
1402 }
1403
1404 //FN Prison::guard_ref()
1405 /// Return a [PrisonValueRef] that contains an immutable reference to the element and wraps it in
1406 /// guarding data that automatically decrements its reference count it when it goes out of scope.
1407 ///
1408 /// [PrisonValueRef<T>] implements [Deref<Target = T>], [AsRef<T>], and
1409 /// [Borrow<T>] to allow transparent access to its underlying value
1410 ///
1411 /// As long as the [PrisonValueRef] remains in scope, the element where it's value resides in the
1412 /// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
1413 /// You can manually drop the [PrisonValueRef] out of scope by passing it as the first parameter
1414 /// to the function [PrisonValueRef::unguard(p_val_ref)]
1415 /// ### Example
1416 /// ```rust
1417 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
1418 /// # fn main() -> Result<(), AccessError> {
1419 /// let prison: Prison<u32> = Prison::new();
1420 /// let key_0 = prison.insert(10)?;
1421 /// let grd_0 = prison.guard_ref(key_0)?;
1422 /// assert_eq!(*grd_0, 10);
1423 /// prison.visit_ref(key_0, |val_0| {
1424 /// assert_eq!(*val_0, 10);
1425 /// Ok(())
1426 /// });
1427 /// assert_eq!(*grd_0, 10);
1428 /// PrisonValueRef::unguard(grd_0);
1429 /// # Ok(())
1430 /// # }
1431 /// ```
1432 /// ## Errors
1433 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
1434 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references already
1435 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
1436 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted *OR* the [CellKey] generation doe not match
1437 /// ### Example
1438 /// ```rust
1439 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
1440 /// # fn main() -> Result<(), AccessError> {
1441 /// let prison: Prison<u32> = Prison::with_capacity(2);
1442 /// let key_0 = prison.insert(10)?;
1443 /// let key_1_a = prison.insert(20)?;
1444 /// let key_out_of_bounds = CellKey::from_raw_parts(10, 0);
1445 /// prison.remove(key_1_a)?;
1446 /// let key_1_b = prison.insert(30)?;
1447 /// let grd_0 = prison.guard_ref(key_0)?;
1448 /// assert!(prison.guard_mut(key_0).is_err());
1449 /// assert!(prison.guard_ref(key_out_of_bounds).is_err());
1450 /// assert!(prison.guard_ref(key_1_a).is_err());
1451 /// # Ok(())
1452 /// # }
1453 /// ```
1454 #[must_use = "guarded reference will immediately fall out of scope"]
1455 pub fn guard_ref<'a>(&'a self, key: CellKey) -> Result<PrisonValueRef<'a, T>, AccessError> {
1456 let (cell, visits) = self._add_imm_ref(key.idx, key.gen, true)?;
1457 return Ok(PrisonValueRef {
1458 cell,
1459 prison_accesses: visits,
1460 });
1461 }
1462
1463 //FN Prison::guard_mut_idx()
1464 /// Return a [PrisonValueMut] that contains a mutable reference to the element and wraps it in
1465 /// guarding data that automatically frees its reference count it when it goes out of scope.
1466 ///
1467 /// Smilar to `guard_mut()` but ignores the generation counter
1468 ///
1469 /// [PrisonValueMut<T>] implements [Deref<Target = T>], [DerefMut<Target = T>], [AsRef<T>], [AsMut<T>],
1470 /// [Borrow<T>], and [BorrowMut<T>] to allow transparent access to its underlying value
1471 ///
1472 /// As long as the [PrisonValueMut] remains in scope, the element where it's value resides in the
1473 /// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
1474 /// You can manually drop the [PrisonValueMut] out of scope by passing it as the first parameter
1475 /// to the function [PrisonValueMut::unguard(p_val_mut)]
1476 /// ### Example
1477 /// ```rust
1478 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1479 /// # fn main() -> Result<(), AccessError> {
1480 /// let prison: Prison<u32> = Prison::new();
1481 /// prison.insert(10)?;
1482 /// let mut grd_0 = prison.guard_mut_idx(0)?;
1483 /// assert_eq!(*grd_0, 10);
1484 /// *grd_0 = 20;
1485 /// PrisonValueMut::unguard(grd_0);
1486 /// prison.visit_ref_idx(0, |val_0| {
1487 /// assert_eq!(*val_0, 20);
1488 /// Ok(())
1489 /// });
1490 /// # Ok(())
1491 /// # }
1492 /// ```
1493 /// ## Errors
1494 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
1495 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if element has any number of immutable references
1496 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
1497 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted
1498 /// ### Example
1499 /// ```rust
1500 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1501 /// # fn main() -> Result<(), AccessError> {
1502 /// let prison: Prison<u32> = Prison::with_capacity(2);
1503 /// prison.insert(10)?;
1504 /// prison.insert(20)?;
1505 /// prison.remove_idx(1)?;
1506 /// let mut grd_0 = prison.guard_mut_idx(0)?;
1507 /// assert!(prison.guard_mut_idx(0).is_err());
1508 /// assert!(prison.guard_mut_idx(5).is_err());
1509 /// assert!(prison.guard_mut_idx(1).is_err());
1510 /// # Ok(())
1511 /// # }
1512 /// ```
1513 #[must_use = "guarded reference will immediately fall out of scope"]
1514 pub fn guard_mut_idx<'a>(&'a self, idx: usize) -> Result<PrisonValueMut<'a, T>, AccessError> {
1515 let (cell, visits) = self._add_mut_ref(idx, 0, false)?;
1516 return Ok(PrisonValueMut {
1517 cell,
1518 prison_accesses: visits,
1519 });
1520 }
1521
1522 //FN Prison::guard_ref_idx()
1523 /// Return a [PrisonValueRef] that contains an immutable reference to the element and wraps it in
1524 /// guarding data that automatically decrements its reference count it when it goes out of scope.
1525 ///
1526 /// Similar to `guard_ref()` but ignores the generation counter
1527 ///
1528 /// [PrisonValueRef<T>] implements [Deref<Target = T>], [AsRef<T>], and
1529 /// [Borrow<T>] to allow transparent access to its underlying value
1530 ///
1531 /// As long as the [PrisonValueRef] remains in scope, the element where it's value resides in the
1532 /// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
1533 /// You can manually drop the [PrisonValueRef] out of scope by passing it as the first parameter
1534 /// to the function [PrisonValueRef::unguard(p_val_ref)]
1535 /// ### Example
1536 /// ```rust
1537 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
1538 /// # fn main() -> Result<(), AccessError> {
1539 /// let prison: Prison<u32> = Prison::new();
1540 /// prison.insert(10)?;
1541 /// let grd_0 = prison.guard_ref_idx(0)?;
1542 /// assert_eq!(*grd_0, 10);
1543 /// prison.visit_ref_idx(0, |val_0| {
1544 /// assert_eq!(*val_0, 10);
1545 /// Ok(())
1546 /// });
1547 /// assert_eq!(*grd_0, 10);
1548 /// PrisonValueRef::unguard(grd_0);
1549 /// # Ok(())
1550 /// # }
1551 /// ```
1552 /// ## Errors
1553 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if element is already mutably referenced
1554 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references already
1555 /// - [AccessError::IndexOutOfRange(idx)] if the [CellKey] index is out of range
1556 /// - [AccessError::ValueDeleted(idx, gen)] if the cell is marked as free/deleted *OR* the [CellKey] generation doe not match
1557 /// ### Example
1558 /// ```rust
1559 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
1560 /// # fn main() -> Result<(), AccessError> {
1561 /// let prison: Prison<u32> = Prison::with_capacity(2);
1562 /// prison.insert(10)?;
1563 /// prison.insert(20)?;
1564 /// prison.remove_idx(1)?;
1565 /// let grd_0 = prison.guard_ref_idx(0)?;
1566 /// assert!(prison.guard_mut_idx(0).is_err());
1567 /// assert!(prison.guard_ref_idx(5).is_err());
1568 /// assert!(prison.guard_ref_idx(1).is_err());
1569 /// # Ok(())
1570 /// # }
1571 /// ```
1572 #[must_use = "guarded reference will immediately fall out of scope"]
1573 pub fn guard_ref_idx<'a>(&'a self, idx: usize) -> Result<PrisonValueRef<'a, T>, AccessError> {
1574 let (cell, visits) = self._add_imm_ref(idx, 0, false)?;
1575 return Ok(PrisonValueRef {
1576 cell,
1577 prison_accesses: visits,
1578 });
1579 }
1580
1581 //FN Prison::guard_many_mut()
1582 /// Return a [PrisonSliceMut] that marks all the elements as mutably referenced and wraps
1583 /// them in guarding data that automatically frees their mutable reference counts when it goes out of range.
1584 ///
1585 /// [PrisonSliceMut<T>] implements [Deref<Target = \[&mut T\]>](Deref), [DerefMut<Target = \[&mut T\]>](DerefMut), [AsRef<\[&mut T\]>](AsRef), [AsMut<\[&mut T\]>](AsMut),
1586 /// [Borrow<\[&mut T\]>](Borrow), and [BorrowMut<\[&mut T\]>](BorrowMut) to allow transparent access to its underlying slice of values
1587 ///
1588 /// As long as the [PrisonSliceMut] remains in scope, the elements where it's values reside in the
1589 /// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
1590 /// You can manually drop the [PrisonSliceMut] out of scope by passing it as the first parameter
1591 /// to the function [PrisonSliceMut::unguard(p_sli_mut)]
1592 /// ### Example
1593 /// ```rust
1594 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
1595 /// # fn main() -> Result<(), AccessError> {
1596 /// let prison: Prison<u32> = Prison::new();
1597 /// let key_0 = prison.insert(10)?;
1598 /// let key_1 = prison.insert(20)?;
1599 /// let key_2 = prison.insert(30)?;
1600 /// let mut grd_0_1_2 = prison.guard_many_mut(&[key_0, key_1, key_2])?;
1601 /// assert_eq!(*grd_0_1_2[0], 10);
1602 /// *grd_0_1_2[0] = 20;
1603 /// PrisonSliceMut::unguard(grd_0_1_2);
1604 /// prison.visit_many_ref(&[key_0, key_1, key_2], |vals_0_1_2| {
1605 /// assert_eq!(*vals_0_1_2[0], 20);
1606 /// Ok(())
1607 /// });
1608 /// # Ok(())
1609 /// # }
1610 /// ```
1611 /// ## Errors
1612 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1613 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if any element has any number of immutable references
1614 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1615 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted *OR* the [CellKey] generation doesnt match
1616 /// ### Example
1617 /// ```rust
1618 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
1619 /// # fn main() -> Result<(), AccessError> {
1620 /// let prison: Prison<u32> = Prison::new();
1621 /// let key_0 = prison.insert(10)?;
1622 /// let key_1 = prison.insert(20)?;
1623 /// let key_2 = prison.insert(30)?;
1624 /// let key_4_a = prison.insert(40)?;
1625 /// prison.remove(key_4_a)?;
1626 /// let key_4_b = prison.insert(44)?;
1627 /// let key_out_of_bounds = CellKey::from_raw_parts(10, 1);
1628 /// let mut grd_0_1_2 = prison.guard_many_mut(&[key_0, key_1, key_2])?;
1629 /// assert!(prison.guard_many_mut(&[key_0, key_1, key_2, key_4_b]).is_err());
1630 /// assert!(prison.guard_many_mut(&[key_out_of_bounds]).is_err());
1631 /// assert!(prison.guard_many_mut(&[key_4_a]).is_err());
1632 /// # Ok(())
1633 /// # }
1634 /// ```
1635 #[must_use = "guarded reference will immediately fall out of scope"]
1636 pub fn guard_many_mut<'a>(
1637 &'a self,
1638 keys: &[CellKey],
1639 ) -> Result<PrisonSliceMut<'a, T>, AccessError> {
1640 let (vals, refs, prison_accesses) = self._add_many_mut_refs(keys)?;
1641 return Ok(PrisonSliceMut {
1642 vals,
1643 refs,
1644 prison_accesses,
1645 });
1646 }
1647
1648 //FN Prison::guard_many_ref()
1649 /// Return a [PrisonSliceRef] that marks all the elements as immutably referenced and wraps
1650 /// them in guarding data that automatically decreases their immutable reference counts when it goes out of range.
1651 ///
1652 /// [PrisonSliceRef<T>] implements [Deref<Target = \[&T\]>](Deref), [AsRef<\[&T\]>](AsRef),
1653 /// and [Borrow<\[&T\]>](Borrow), to allow transparent access to its underlying slice of values
1654 ///
1655 /// As long as the [PrisonSliceRef] remains in scope, the elements where it's values reside in the
1656 /// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
1657 /// You can manually drop the [PrisonSliceRef] out of scope by passing it as the first parameter
1658 /// to the function [PrisonSliceRef::unguard(p_sli_ref)]
1659 /// ### Example
1660 /// ```rust
1661 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
1662 /// # fn main() -> Result<(), AccessError> {
1663 /// let prison: Prison<u32> = Prison::new();
1664 /// let key_0 = prison.insert(10)?;
1665 /// let key_1 = prison.insert(20)?;
1666 /// let key_2 = prison.insert(30)?;
1667 /// let mut grd_0_1_2 = prison.guard_many_ref(&[key_0, key_1, key_2])?;
1668 /// assert_eq!(*grd_0_1_2[0], 10);
1669 /// prison.visit_many_ref(&[key_0, key_1, key_2], |vals_0_1_2| {
1670 /// assert_eq!(*vals_0_1_2[0], 10);
1671 /// Ok(())
1672 /// });
1673 /// PrisonSliceRef::unguard(grd_0_1_2);
1674 /// # Ok(())
1675 /// # }
1676 /// ```
1677 /// ## Errors
1678 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1679 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references to any element
1680 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1681 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted *OR* if the [CellKey] generation doesn't match
1682 /// ### Example
1683 /// ```rust
1684 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1685 /// # fn main() -> Result<(), AccessError> {
1686 /// let prison: Prison<u32> = Prison::new();
1687 /// let key_0 = prison.insert(10)?;
1688 /// let key_1 = prison.insert(20)?;
1689 /// let key_2 = prison.insert(30)?;
1690 /// let key_4_a = prison.insert(40)?;
1691 /// prison.remove(key_4_a)?;
1692 /// let key_4_b = prison.insert(44)?;
1693 /// let key_out_of_bounds = CellKey::from_raw_parts(10, 1);
1694 /// let grd_0_1_2 = prison.guard_many_ref(&[key_0, key_1, key_2])?;
1695 /// assert!(prison.guard_many_mut(&[key_0]).is_err());
1696 /// assert!(prison.guard_many_ref(&[key_out_of_bounds]).is_err());
1697 /// assert!(prison.guard_many_ref(&[key_4_a]).is_err());
1698 /// # Ok(())
1699 /// # }
1700 /// ```
1701 #[must_use = "guarded reference will immediately fall out of scope"]
1702 pub fn guard_many_ref<'a>(
1703 &'a self,
1704 keys: &[CellKey],
1705 ) -> Result<PrisonSliceRef<'a, T>, AccessError> {
1706 let (vals, refs, prison_accesses) = self._add_many_imm_refs(keys)?;
1707 return Ok(PrisonSliceRef {
1708 vals,
1709 refs,
1710 prison_accesses,
1711 });
1712 }
1713
1714 //FN Prison::guard_many_mut_idx()
1715 /// Return a [PrisonSliceMut] that marks all the elements as mutably referenced and wraps
1716 /// them in guarding data that automatically frees their mutable reference counts when it goes out of range.
1717 ///
1718 /// Similar to `guard_many_mut()` but ignores the generation counter
1719 ///
1720 /// [PrisonSliceMut<T>] implements [Deref<Target = \[&mut T\]>](Deref), [DerefMut<Target = \[&mut T\]>](DerefMut), [AsRef<\[&mut T\]>](AsRef), [AsMut<\[&mut T\]>](AsMut),
1721 /// [Borrow<\[&mut T\]>](Borrow), and [BorrowMut<\[&mut T\]>](BorrowMut) to allow transparent access to its underlying slice of values
1722 ///
1723 /// As long as the [PrisonSliceMut] remains in scope, the elements where it's values reside in the
1724 /// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
1725 /// You can manually drop the [PrisonSliceMut] out of scope by passing it as the first parameter
1726 /// to the function [PrisonSliceMut::unguard(p_sli_mut)]
1727 /// ### Example
1728 /// ```rust
1729 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
1730 /// # fn main() -> Result<(), AccessError> {
1731 /// let prison: Prison<u32> = Prison::new();
1732 /// prison.insert(10)?;
1733 /// prison.insert(20)?;
1734 /// prison.insert(30)?;
1735 /// let mut grd_0_1_2 = prison.guard_many_mut_idx(&[0, 1, 2])?;
1736 /// assert_eq!(*grd_0_1_2[0], 10);
1737 /// *grd_0_1_2[0] = 20;
1738 /// PrisonSliceMut::unguard(grd_0_1_2);
1739 /// prison.visit_many_ref_idx(&[0, 1, 2], |vals_0_1_2| {
1740 /// assert_eq!(*vals_0_1_2[0], 20);
1741 /// Ok(())
1742 /// });
1743 /// # Ok(())
1744 /// # }
1745 /// ```
1746 /// ## Errors
1747 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1748 /// - [AccessError::ValueStillImmutablyReferenced(idx)] if any element has any number of immutable references
1749 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1750 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted
1751 /// ### Example
1752 /// ```rust
1753 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
1754 /// # fn main() -> Result<(), AccessError> {
1755 /// let prison: Prison<u32> = Prison::new();
1756 /// prison.insert(10)?;
1757 /// prison.insert(20)?;
1758 /// prison.insert(30)?;
1759 /// prison.insert(40)?;
1760 /// prison.remove_idx(3)?;
1761 /// let mut grd_0_1_2 = prison.guard_many_mut_idx(&[0, 1, 2])?;
1762 /// assert!(prison.guard_many_mut_idx(&[0, 1, 2]).is_err());
1763 /// assert!(prison.guard_many_mut_idx(&[5]).is_err());
1764 /// assert!(prison.guard_many_mut_idx(&[3]).is_err());
1765 /// # Ok(())
1766 /// # }
1767 /// ```
1768 #[must_use = "guarded reference will immediately fall out of scope"]
1769 pub fn guard_many_mut_idx<'a>(
1770 &'a self,
1771 indexes: &[usize],
1772 ) -> Result<PrisonSliceMut<'a, T>, AccessError> {
1773 let (vals, refs, prison_accesses) = self._add_many_mut_refs_idx(indexes)?;
1774 return Ok(PrisonSliceMut {
1775 vals,
1776 refs,
1777 prison_accesses,
1778 });
1779 }
1780
1781 //FN Prison::guard_many_ref_idx()
1782 /// Return a [PrisonSliceRef] that marks all the elements as immutably referenced and wraps
1783 /// them in guarding data that automatically decreases their immutable reference counts when it goes out of range.
1784 ///
1785 /// Similar to `guard_many_ref()` but ignores the generation counter
1786 ///
1787 /// [PrisonSliceRef<T>] implements [Deref<Target = \[&T\]>](Deref), [AsRef<\[&T\]>](AsRef),
1788 /// and [Borrow<\[&T\]>](Borrow), to allow transparent access to its underlying slice of values
1789 ///
1790 /// As long as the [PrisonSliceRef] remains in scope, the elements where it's values reside in the
1791 /// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
1792 /// You can manually drop the [PrisonSliceRef] out of scope by passing it as the first parameter
1793 /// to the function [PrisonSliceRef::unguard(p_sli_ref)]
1794 /// ### Example
1795 /// ```rust
1796 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
1797 /// # fn main() -> Result<(), AccessError> {
1798 /// let prison: Prison<u32> = Prison::new();
1799 /// prison.insert(10)?;
1800 /// prison.insert(20)?;
1801 /// prison.insert(30)?;
1802 /// let mut grd_0_1_2 = prison.guard_many_ref_idx(&[0, 1, 2])?;
1803 /// assert_eq!(*grd_0_1_2[0], 10);
1804 /// prison.visit_many_ref_idx(&[0, 1, 2], |vals_0_1_2| {
1805 /// assert_eq!(*vals_0_1_2[0], 10);
1806 /// Ok(())
1807 /// });
1808 /// PrisonSliceRef::unguard(grd_0_1_2);
1809 /// # Ok(())
1810 /// # }
1811 /// ```
1812 /// ## Errors
1813 /// - [AccessError::ValueAlreadyMutablyReferenced(idx)] if any element is already mutably referenced
1814 /// - [AccessError::MaximumImmutableReferencesReached(idx)] if you created [usize::MAX] - 2 immutable references to any element
1815 /// - [AccessError::IndexOutOfRange(idx)] if any index is out of range
1816 /// - [AccessError::ValueDeleted(idx, gen)] if any cell is marked as free/deleted
1817 /// ### Example
1818 /// ```rust
1819 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1820 /// # fn main() -> Result<(), AccessError> {
1821 /// let prison: Prison<u32> = Prison::new();
1822 /// prison.insert(10)?;
1823 /// prison.insert(20)?;
1824 /// prison.insert(30)?;
1825 /// prison.insert(40)?;
1826 /// prison.remove_idx(3)?;
1827 /// let grd_0_1_2 = prison.guard_many_ref_idx(&[0, 1, 2])?;
1828 /// assert!(prison.guard_many_mut_idx(&[0]).is_err());
1829 /// assert!(prison.guard_many_ref_idx(&[5]).is_err());
1830 /// assert!(prison.guard_many_ref_idx(&[3]).is_err());
1831 /// # Ok(())
1832 /// # }
1833 /// ```
1834 #[must_use = "guarded reference will immediately fall out of scope"]
1835 pub fn guard_many_ref_idx<'a>(
1836 &'a self,
1837 indexes: &[usize],
1838 ) -> Result<PrisonSliceRef<'a, T>, AccessError> {
1839 let (vals, refs, prison_accesses) = self._add_many_imm_refs_idx(indexes)?;
1840 return Ok(PrisonSliceRef {
1841 vals,
1842 refs,
1843 prison_accesses,
1844 });
1845 }
1846
1847 //FN Prison::guard_slice_mut()
1848 /// Return a [PrisonSliceMut] that marks all the elements as mutably referenced and wraps
1849 /// them in guarding data that automatically frees their mutable reference counts when it goes out of range.
1850 ///
1851 /// Internally this is strictly identical to passing [Prison::guard_many_mut_idx()] a list of all
1852 /// indexes in the slice range, and is subject to all the same restrictions and errors
1853 /// ### Example
1854 /// ```rust
1855 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
1856 /// # fn main() -> Result<(), AccessError> {
1857 /// let u32_prison: Prison<u32> = Prison::new();
1858 /// u32_prison.insert(42)?;
1859 /// u32_prison.insert(43)?;
1860 /// u32_prison.insert(44)?;
1861 /// u32_prison.insert(45)?;
1862 /// u32_prison.insert(46)?;
1863 /// let grd_last_three = u32_prison.guard_slice_mut(2..5)?;
1864 /// assert_eq!(*grd_last_three[0], 44);
1865 /// assert_eq!(*grd_last_three[1], 45);
1866 /// assert_eq!(*grd_last_three[2], 46);
1867 /// # Ok(())
1868 /// # }
1869 /// ```
1870 /// Any standard [Range<usize>](std::ops::Range) notation is allowed as the first paramater,
1871 /// but care must be taken because it is not guaranteed every index within range is a valid
1872 /// value or does not have any other references to it that would violate Rust's memory safety.
1873 /// ### Example
1874 /// ```rust
1875 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::Prison};
1876 /// # fn main() -> Result<(), AccessError> {
1877 /// let u32_prison: Prison<u32> = Prison::new();
1878 /// u32_prison.insert(42)?;
1879 /// u32_prison.insert(43)?;
1880 /// u32_prison.insert(44)?;
1881 /// u32_prison.insert(45)?;
1882 /// u32_prison.insert(46)?;
1883 /// assert!(u32_prison.guard_slice_mut(2..5).is_ok());
1884 /// assert!(u32_prison.guard_slice_mut(2..=4).is_ok());
1885 /// assert!(u32_prison.guard_slice_mut(2..).is_ok());
1886 /// assert!(u32_prison.guard_slice_mut(..3).is_ok());
1887 /// assert!(u32_prison.guard_slice_mut(..=3).is_ok());
1888 /// assert!(u32_prison.guard_slice_mut(..).is_ok());
1889 /// u32_prison.remove_idx(2)?;
1890 /// assert!(u32_prison.guard_slice_mut(..).is_err());
1891 /// # Ok(())
1892 /// # }
1893 /// ```
1894 /// See [Prison::guard_many_mut_idx()] for more info
1895 #[must_use = "guarded reference will immediately fall out of scope"]
1896 pub fn guard_slice_mut<'a, R>(&'a self, range: R) -> Result<PrisonSliceMut<'a, T>, AccessError>
1897 where
1898 R: RangeBounds<usize>,
1899 {
1900 let (start, end) = extract_true_start_end(range, self.vec_len());
1901 let idxs: Vec<usize> = (start..end).into_iter().collect();
1902 return self.guard_many_mut_idx(&idxs);
1903 }
1904
1905 //FN Prison::guard_slice_ref()
1906 /// Return a [PrisonSliceRef] that marks all the elements as immutably referenced and wraps
1907 /// them in guarding data that automatically decreases their immutable reference counts when it goes out of range.
1908 ///
1909 /// Internally this is strictly identical to passing [Prison::guard_many_ref_idx()] a list of all
1910 /// indexes in the slice range, and is subject to all the same restrictions and errors
1911 /// ### Example
1912 /// ```rust
1913 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
1914 /// # fn main() -> Result<(), AccessError> {
1915 /// let u32_prison: Prison<u32> = Prison::new();
1916 /// u32_prison.insert(42)?;
1917 /// u32_prison.insert(43)?;
1918 /// u32_prison.insert(44)?;
1919 /// u32_prison.insert(45)?;
1920 /// u32_prison.insert(46)?;
1921 /// let grd_last_three = u32_prison.guard_slice_ref(2..5)?;
1922 /// let grd_all = u32_prison.guard_slice_ref(..)?;
1923 /// assert_eq!(*grd_all[0], 42);
1924 /// assert_eq!(*grd_all[1], 43);
1925 /// assert_eq!(*grd_last_three[0], 44);
1926 /// assert_eq!(*grd_last_three[1], 45);
1927 /// assert_eq!(*grd_last_three[2], 46);
1928 /// # Ok(())
1929 /// # }
1930 /// ```
1931 /// Any standard [Range<usize>](std::ops::Range) notation is allowed as the first paramater,
1932 /// but care must be taken because it is not guaranteed every index within range is a valid
1933 /// value or does not have any other references to it that would violate Rust's memory safety.
1934 /// ### Example
1935 /// ```rust
1936 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
1937 /// # fn main() -> Result<(), AccessError> {
1938 /// let u32_prison: Prison<u32> = Prison::new();
1939 /// u32_prison.insert(42)?;
1940 /// u32_prison.insert(43)?;
1941 /// u32_prison.insert(44)?;
1942 /// u32_prison.insert(45)?;
1943 /// u32_prison.insert(46)?;
1944 /// assert!(u32_prison.guard_slice_ref(2..5).is_ok());
1945 /// assert!(u32_prison.guard_slice_ref(2..=4).is_ok());
1946 /// assert!(u32_prison.guard_slice_ref(2..).is_ok());
1947 /// assert!(u32_prison.guard_slice_ref(..3).is_ok());
1948 /// assert!(u32_prison.guard_slice_ref(..=3).is_ok());
1949 /// assert!(u32_prison.guard_slice_ref(..).is_ok());
1950 /// u32_prison.remove_idx(2)?;
1951 /// assert!(u32_prison.guard_slice_ref(..).is_err());
1952 /// # Ok(())
1953 /// # }
1954 /// ```
1955 /// See [Prison::guard_many_ref_idx()] for more info
1956 #[must_use = "guarded reference will immediately fall out of scope"]
1957 pub fn guard_slice_ref<'a, R>(&'a self, range: R) -> Result<PrisonSliceRef<'a, T>, AccessError>
1958 where
1959 R: RangeBounds<usize>,
1960 {
1961 let (start, end) = extract_true_start_end(range, self.vec_len());
1962 let idxs: Vec<usize> = (start..end).into_iter().collect();
1963 return self.guard_many_ref_idx(&idxs);
1964 }
1965
1966 //FN Prison::clone_val()
1967 /// Clones the requested value out of the [Prison] into a new variable
1968 ///
1969 /// Only available when elements of type T implement [Clone] (it is assumed that the implementation of `T::clone()` is memory safe).
1970 ///
1971 /// Because cloning does not alter the original, and because the new variable to hold the clone does not have any presumtions about the value, it
1972 /// is safe (in a single-threaded context) to clone out the value even if it is being visited or guarded.
1973 ///
1974 /// This method *will* still return an error if the index or generation of the [CellKey] are invalid
1975 /// ### Example
1976 /// ```rust
1977 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
1978 /// # fn main() -> Result<(), AccessError> {
1979 /// let prison: Prison<String> = Prison::new();
1980 /// let key_0 = prison.insert(String::from("Foo"))?;
1981 /// let key_1 = prison.insert(String::from("Bar"))?;
1982 /// let mut take_foo = String::new();
1983 /// let mut take_bar = String::new();
1984 /// prison.visit_mut(key_0, |val_0| {
1985 /// take_foo = prison.clone_val(key_0)?;
1986 /// Ok(())
1987 /// });
1988 /// let grd_1 = prison.guard_mut(key_1)?;
1989 /// take_bar = prison.clone_val(key_1)?;
1990 /// PrisonValueMut::unguard(grd_1);
1991 /// assert_eq!(take_foo, String::from("Foo"));
1992 /// assert_eq!(take_bar, String::from("Bar"));
1993 /// prison.remove(key_1)?;
1994 /// assert!(prison.clone_val(CellKey::from_raw_parts(10, 10)).is_err());
1995 /// assert!(prison.clone_val(key_1).is_err());
1996 /// # Ok(())
1997 /// # }
1998 /// ```
1999 pub fn clone_val(&self, key: CellKey) -> Result<T, AccessError>
2000 where
2001 T: Clone,
2002 {
2003 let internal = internal!(self);
2004 if key.idx >= internal.vec.len() {
2005 return Err(AccessError::IndexOutOfRange(key.idx));
2006 }
2007 match &internal.vec[key.idx] {
2008 cell if cell.is_cell_and_gen_match(key.gen) => {
2009 return Ok(unsafe { cell.val.assume_init_ref().clone() });
2010 }
2011 _ => return Err(AccessError::ValueDeleted(key.idx, key.gen)),
2012 }
2013 }
2014
2015 //FN Prison::clone_val_idx()
2016 /// Clones the requested value out of the [Prison] into a new variable
2017 ///
2018 /// Same as `clone_val()` but ignores the generation counter
2019 ///
2020 /// Only available when elements of type T implement [Clone] (it is assumed that the implementation of `T::clone()` is memory safe).
2021 ///
2022 /// Because cloning does not alter the original, and because the new variable to hold the clone does not have any presumtions about the value, it
2023 /// is safe (in a single-threaded context) to clone out the value even if it is being visited or guarded.
2024 ///
2025 /// This method *will* still return an error if the index is invalid or the value is free/deleted
2026 /// ### Example
2027 /// ```rust
2028 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
2029 /// # fn main() -> Result<(), AccessError> {
2030 /// let prison: Prison<String> = Prison::new();
2031 /// prison.insert(String::from("Foo"))?;
2032 /// prison.insert(String::from("Bar"))?;
2033 /// let mut take_foo = String::new();
2034 /// let mut take_bar = String::new();
2035 /// prison.visit_mut_idx(0, |val_0| {
2036 /// take_foo = prison.clone_val_idx(0)?;
2037 /// Ok(())
2038 /// });
2039 /// let grd_1 = prison.guard_mut_idx(1)?;
2040 /// take_bar = prison.clone_val_idx(1)?;
2041 /// PrisonValueMut::unguard(grd_1);
2042 /// assert_eq!(take_foo, String::from("Foo"));
2043 /// assert_eq!(take_bar, String::from("Bar"));
2044 /// prison.remove_idx(1)?;
2045 /// assert!(prison.clone_val_idx(10).is_err());
2046 /// assert!(prison.clone_val_idx(1).is_err());
2047 /// # Ok(())
2048 /// # }
2049 /// ```
2050 pub fn clone_val_idx(&self, idx: usize) -> Result<T, AccessError>
2051 where
2052 T: Clone,
2053 {
2054 let internal = internal!(self);
2055 if idx >= internal.vec.len() {
2056 return Err(AccessError::IndexOutOfRange(idx));
2057 }
2058 match &internal.vec[idx] {
2059 cell if cell.is_cell() => {
2060 return Ok(unsafe { cell.val.assume_init_ref().clone() });
2061 }
2062 _ => return Err(AccessError::ValueDeleted(idx, 0)),
2063 }
2064 }
2065
2066 //FN Prison::clone_many_vals()
2067 /// Clones the requested values out of the [Prison] into a new [Vec<T>]
2068 ///
2069 /// Only available when elements of type T implement [Clone] (it is assumed that the implementation of `T::clone()` is memory safe).
2070 ///
2071 /// Because cloning does not alter the originals, and because the new variables to hold the clones do not have any presumtions about the values, it
2072 /// is safe (in a single-threaded context) to clone out the values even if they are being visited or guarded.
2073 ///
2074 /// This method *will* still return an error if any index or generation of the [CellKey]s are invalid
2075 /// ### Example
2076 /// ```rust
2077 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
2078 /// # fn main() -> Result<(), AccessError> {
2079 /// let prison: Prison<String> = Prison::new();
2080 /// let key_0 = prison.insert(String::from("Foo"))?;
2081 /// let key_1 = prison.insert(String::from("Bar"))?;
2082 /// let mut take_foobar: Vec<String> = Vec::new();
2083 /// prison.visit_mut(key_0, |val_0| {
2084 /// let grd_1 = prison.guard_mut(key_1)?;
2085 /// take_foobar = prison.clone_many_vals(&[key_0, key_1])?;
2086 /// PrisonValueMut::unguard(grd_1);
2087 /// Ok(())
2088 /// });
2089 /// assert_eq!(take_foobar[0], String::from("Foo"));
2090 /// assert_eq!(take_foobar[1], String::from("Bar"));
2091 /// prison.remove(key_1)?;
2092 /// assert!(prison.clone_many_vals(&[CellKey::from_raw_parts(10, 10)]).is_err());
2093 /// assert!(prison.clone_many_vals(&[key_1]).is_err());
2094 /// # Ok(())
2095 /// # }
2096 /// ```
2097 pub fn clone_many_vals(&self, keys: &[CellKey]) -> Result<Vec<T>, AccessError>
2098 where
2099 T: Clone,
2100 {
2101 let mut vals = Vec::with_capacity(keys.len());
2102 for key in keys {
2103 vals.push(self.clone_val(*key)?);
2104 }
2105 return Ok(vals);
2106 }
2107
2108 //FN Prison::clone_many_vals_idx()
2109 /// Clones the requested values out of the [Prison] into a new [Vec<T>]
2110 ///
2111 /// Same as `clone_many_vals()` but ignores the generation counter
2112 ///
2113 /// Only available when elements of type T implement [Clone] (it is assumed that the implementation of `T::clone()` is memory safe).
2114 ///
2115 /// Because cloning does not alter the originals, and because the new variables to hold the clones do not have any presumtions about the values, it
2116 /// is safe (in a single-threaded context) to clone out the values even if they are being visited or guarded.
2117 ///
2118 /// This method *will* still return an error if any index is out-of-range or free/deleted
2119 /// ### Example
2120 /// ```rust
2121 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
2122 /// # fn main() -> Result<(), AccessError> {
2123 /// let prison: Prison<String> = Prison::new();
2124 /// prison.insert(String::from("Foo"))?;
2125 /// prison.insert(String::from("Bar"))?;
2126 /// let mut take_foobar: Vec<String> = Vec::new();
2127 /// prison.visit_mut_idx(0, |val_0| {
2128 /// let grd_1 = prison.guard_mut_idx(1)?;
2129 /// take_foobar = prison.clone_many_vals_idx(&[0, 1])?;
2130 /// PrisonValueMut::unguard(grd_1);
2131 /// Ok(())
2132 /// });
2133 /// assert_eq!(take_foobar[0], String::from("Foo"));
2134 /// assert_eq!(take_foobar[1], String::from("Bar"));
2135 /// prison.remove_idx(1)?;
2136 /// assert!(prison.clone_many_vals_idx(&[10]).is_err());
2137 /// assert!(prison.clone_many_vals_idx(&[1]).is_err());
2138 /// # Ok(())
2139 /// # }
2140 /// ```
2141 pub fn clone_many_vals_idx(&self, indexes: &[usize]) -> Result<Vec<T>, AccessError>
2142 where
2143 T: Clone,
2144 {
2145 let mut vals = Vec::with_capacity(indexes.len());
2146 for idx in indexes {
2147 vals.push(self.clone_val_idx(*idx)?);
2148 }
2149 return Ok(vals);
2150 }
2151
2152 //FN: Prison::peek_ref()
2153 /// Get a reference to a value from it's associated [CellKey], ***ignoring reference counting and most other safety measures***
2154 ///
2155 /// Returns [`Ok(&T)`] if the value exists and the generation matches, [Err(AccessError::ValueDeleted(idx, gen))] otherwise
2156 ///
2157 /// This method is provided as a way for libraries depending on this code to perform niche
2158 /// optimized reads of contained values without the overhead of the normal safety checks,
2159 /// or when a mutable reference is active but you can statically confirm that the value will
2160 /// not be mutated from the begining of the returned `&T`'s lifetime to the end of it's lifetime.
2161 ///
2162 /// The returned references are intended to be short-lived and safely contained in a scope where no
2163 /// mutation of the [Prison] as a whole or ANY of its values takes place
2164 /// # Safety
2165 /// When you call this method and as long as the `&T` it returns remains in-scope/alive,
2166 /// you MUST ensure the following:
2167 /// - The value MUST NOT be mutated by ANY source, including active safe reference-counted mutable references
2168 /// - NO operation can be performed that could *potentially* cause the underlying memory address of the [Prison]'s data to relocate
2169 pub unsafe fn peek_ref<'a>(&'a self, key: CellKey) -> Result<&'a T, AccessError> {
2170 match &internal!(self).vec[key.idx] {
2171 cell if cell.is_cell_and_gen_match(key.gen) => {
2172 Ok(unsafe { &cell.val.assume_init_ref() })
2173 }
2174 _ => Err(AccessError::ValueDeleted(key.idx, key.gen)),
2175 }
2176 }
2177
2178 //FN: Prison::peek_ref_idx()
2179 /// Get a reference to a value from it's associated index, ***ignoring reference counting and most other safety measures***
2180 ///
2181 /// Returns [`Ok(&T)`] if the value exists, [Err(AccessError::ValueDeleted(idx, 0))] otherwise
2182 ///
2183 /// This method is provided as a way for libraries depending on this code to perform niche
2184 /// optimized reads of contained values without the overhead of the normal safety checks,
2185 /// or when a mutable reference is active but you can statically confirm that the value will
2186 /// not be mutated from the begining of the returned `&T`s lifetime to the end of it's lifetime.
2187 ///
2188 /// The returned references are intended to be short-lived and safely contained in a scope where no
2189 /// mutation of the [Prison] as a whole or ANY of its values takes place
2190 /// # Safety
2191 /// When you call this method and as long as the `&T` it returns remains in-scope/alive,
2192 /// you MUST ensure the following:
2193 /// - The value MUST NOT be mutated by ANY source, including active safe reference-counted mutable references
2194 /// - NO operation can be performed that could *potentially* cause the underlying memory address of the [Prison]'s data to relocate
2195 pub unsafe fn peek_ref_idx<'a>(&'a self, idx: usize) -> Result<&'a T, AccessError> {
2196 match &internal!(self).vec[idx] {
2197 cell if cell.is_cell() => Ok(unsafe { &cell.val.assume_init_ref() }),
2198 _ => Err(AccessError::ValueDeleted(idx, 0)),
2199 }
2200 }
2201
2202 //------ Prison Private ------
2203 //FN Prison::_add_mut_ref()
2204 #[doc(hidden)]
2205 fn _add_mut_ref(
2206 &self,
2207 idx: usize,
2208 gen: usize,
2209 use_gen: bool,
2210 ) -> Result<(&mut PrisonCell<T>, &mut usize), AccessError> {
2211 let internal = internal!(self);
2212 if idx >= internal.vec.len() {
2213 return Err(AccessError::IndexOutOfRange(idx));
2214 }
2215 match &mut internal.vec[idx] {
2216 cell if cell.is_cell_and_gen_match_opt(gen, use_gen) => {
2217 if cell.refs_or_next == Refs::MUT {
2218 return Err(AccessError::ValueAlreadyMutablyReferenced(idx));
2219 }
2220 if cell.refs_or_next > 0 {
2221 return Err(AccessError::ValueStillImmutablyReferenced(idx));
2222 }
2223 cell.refs_or_next = Refs::MUT;
2224 internal.access_count += 1;
2225 return Ok((cell, &mut internal.access_count));
2226 }
2227 _ => return Err(AccessError::ValueDeleted(idx, gen)),
2228 }
2229 }
2230
2231 //FN Prison::_add_imm_ref()
2232 #[doc(hidden)]
2233 fn _add_imm_ref(
2234 &self,
2235 idx: usize,
2236 gen: usize,
2237 use_gen: bool,
2238 ) -> Result<(&mut PrisonCell<T>, &mut usize), AccessError> {
2239 let internal = internal!(self);
2240 if idx >= internal.vec.len() {
2241 return Err(AccessError::IndexOutOfRange(idx));
2242 }
2243 match &mut internal.vec[idx] {
2244 cell if cell.is_cell_and_gen_match_opt(gen, use_gen) => {
2245 if cell.refs_or_next == Refs::MUT {
2246 return Err(AccessError::ValueAlreadyMutablyReferenced(idx));
2247 }
2248 if cell.refs_or_next == Refs::MAX_IMMUT {
2249 return Err(AccessError::MaximumImmutableReferencesReached(idx));
2250 }
2251 if cell.refs_or_next == 0 {
2252 internal.access_count += 1;
2253 }
2254 cell.refs_or_next += 1;
2255 return Ok((cell, &mut internal.access_count));
2256 }
2257 _ => return Err(AccessError::ValueDeleted(idx, gen)),
2258 }
2259 }
2260
2261 //FN Prison::_add_many_mut_refs()
2262 #[doc(hidden)]
2263 fn _add_many_mut_refs(
2264 &self,
2265 cell_keys: &[CellKey],
2266 ) -> Result<(Vec<&mut T>, Vec<&mut usize>, &mut usize), AccessError> {
2267 let internal = internal!(self);
2268 let mut vals = Vec::new();
2269 let mut refs = Vec::new();
2270 let mut ref_all_result = Ok(());
2271 for key in cell_keys {
2272 let ref_result = self._add_mut_ref(key.idx, key.gen, true);
2273 match ref_result {
2274 Ok((cell, _)) => {
2275 vals.push(unsafe { cell.val.assume_init_mut() });
2276 refs.push(&mut cell.refs_or_next);
2277 }
2278 Err(e) => {
2279 ref_all_result = Err(e);
2280 break;
2281 }
2282 }
2283 }
2284 match ref_all_result {
2285 Ok(_) => {
2286 return Ok((vals, refs, &mut internal.access_count));
2287 }
2288 Err(acc_err) => {
2289 _remove_many_mut_refs(&mut refs, &mut internal.access_count);
2290 return Err(acc_err);
2291 }
2292 }
2293 }
2294
2295 //FN Prison::_add_many_mut_refs_idx()
2296 #[doc(hidden)]
2297 fn _add_many_mut_refs_idx(
2298 &self,
2299 idxs: &[usize],
2300 ) -> Result<(Vec<&mut T>, Vec<&mut usize>, &mut usize), AccessError> {
2301 let internal = internal!(self);
2302 let mut vals = Vec::new();
2303 let mut refs = Vec::new();
2304 let mut ref_all_result = Ok(());
2305 for idx in idxs {
2306 let ref_result = self._add_mut_ref(*idx, 0, false);
2307 match ref_result {
2308 Ok((cell, _)) => {
2309 vals.push(unsafe { cell.val.assume_init_mut() });
2310 refs.push(&mut cell.refs_or_next);
2311 }
2312 Err(e) => {
2313 ref_all_result = Err(e);
2314 break;
2315 }
2316 }
2317 }
2318 match ref_all_result {
2319 Ok(_) => {
2320 return Ok((vals, refs, &mut internal.access_count));
2321 }
2322 Err(acc_err) => {
2323 _remove_many_mut_refs(&mut refs, &mut internal.access_count);
2324 return Err(acc_err);
2325 }
2326 }
2327 }
2328
2329 //FN Prison::_add_many_imm_refs()
2330 #[doc(hidden)]
2331 fn _add_many_imm_refs(
2332 &self,
2333 cell_keys: &[CellKey],
2334 ) -> Result<(Vec<&T>, Vec<&mut usize>, &mut usize), AccessError> {
2335 let internal = internal!(self);
2336 let mut vals = Vec::new();
2337 let mut refs = Vec::new();
2338 let mut ref_all_result = Ok(());
2339 for key in cell_keys {
2340 let ref_result = self._add_imm_ref(key.idx, key.gen, true);
2341 match ref_result {
2342 Ok((cell, _)) => {
2343 vals.push(unsafe { cell.val.assume_init_ref() });
2344 refs.push(&mut cell.refs_or_next);
2345 }
2346 Err(e) => {
2347 ref_all_result = Err(e);
2348 break;
2349 }
2350 }
2351 }
2352 match ref_all_result {
2353 Ok(_) => {
2354 return Ok((vals, refs, &mut internal.access_count));
2355 }
2356 Err(acc_err) => {
2357 _remove_many_imm_refs(&mut refs, &mut internal.access_count);
2358 return Err(acc_err);
2359 }
2360 }
2361 }
2362
2363 //FN Prison::_add_many_imm_refs_idx()
2364 #[doc(hidden)]
2365 fn _add_many_imm_refs_idx(
2366 &self,
2367 idxs: &[usize],
2368 ) -> Result<(Vec<&T>, Vec<&mut usize>, &mut usize), AccessError> {
2369 let internal = internal!(self);
2370 let mut vals = Vec::new();
2371 let mut refs = Vec::new();
2372 let mut ref_all_result = Ok(());
2373 for idx in idxs {
2374 let ref_result = self._add_imm_ref(*idx, 0, false);
2375 match ref_result {
2376 Ok((cell, _)) => {
2377 vals.push(unsafe { cell.val.assume_init_ref() });
2378 refs.push(&mut cell.refs_or_next);
2379 }
2380 Err(e) => {
2381 ref_all_result = Err(e);
2382 break;
2383 }
2384 }
2385 }
2386 match ref_all_result {
2387 Ok(_) => {
2388 return Ok((vals, refs, &mut internal.access_count));
2389 }
2390 Err(acc_err) => {
2391 _remove_many_imm_refs(&mut refs, &mut internal.access_count);
2392 return Err(acc_err);
2393 }
2394 }
2395 }
2396}
2397
2398//FN _remove_mut_ref()
2399#[doc(hidden)]
2400#[inline(always)]
2401fn _remove_mut_ref(refs: &mut usize, accesses: &mut usize) {
2402 *refs = 0;
2403 *accesses -= 1;
2404}
2405
2406//FN _remove_imm_ref()
2407#[doc(hidden)]
2408#[inline(always)]
2409fn _remove_imm_ref(refs: &mut usize, accesses: &mut usize) {
2410 *refs -= 1;
2411 if *refs == 0 {
2412 *accesses -= 1
2413 }
2414}
2415
2416//FN _remove_many_mut_refs()
2417#[doc(hidden)]
2418#[inline(always)]
2419fn _remove_many_mut_refs(refs_list: &mut [&mut usize], accesses: &mut usize) {
2420 for refs in refs_list {
2421 _remove_mut_ref(refs, accesses)
2422 }
2423}
2424
2425//FN _remove_many_imm_refs()
2426#[doc(hidden)]
2427#[inline(always)]
2428fn _remove_many_imm_refs(refs_list: &mut [&mut usize], accesses: &mut usize) {
2429 for refs in refs_list {
2430 _remove_imm_ref(refs, accesses)
2431 }
2432}
2433
2434//IMPL Default for Prison
2435impl<T> Default for Prison<T> {
2436 fn default() -> Self {
2437 Self::new()
2438 }
2439}
2440
2441//STRUCT PrisonInternal
2442#[doc(hidden)]
2443#[derive(Debug)] //COV_IGNORE
2444struct PrisonInternal<T> {
2445 access_count: usize,
2446 generation: usize,
2447 free_count: usize,
2448 next_free: usize,
2449 vec: Vec<PrisonCell<T>>,
2450}
2451
2452//STRUCT PrisonCell
2453#[doc(hidden)]
2454#[derive(Debug)] //COV_IGNORE
2455struct PrisonCell<T> {
2456 refs_or_next: usize,
2457 d_gen_or_prev: usize,
2458 val: MaybeUninit<T>,
2459}
2460
2461//IMPL Drop for PrisonCell
2462impl<T> Drop for PrisonCell<T> {
2463 fn drop(&mut self) {
2464 if self.is_cell() {
2465 unsafe { self.val.assume_init_drop() }
2466 }
2467 }
2468}
2469
2470impl<T> PrisonCell<T> {
2471 #[inline(always)]
2472 fn is_cell_and_gen_match_opt(&self, gen: usize, use_gen: bool) -> bool {
2473 IdxD::is_type_a(self.d_gen_or_prev) && (!use_gen || IdxD::val(self.d_gen_or_prev) == gen)
2474 }
2475 #[inline(always)]
2476 fn is_cell_and_gen_match(&self, gen: usize) -> bool {
2477 IdxD::is_type_a(self.d_gen_or_prev) && IdxD::val(self.d_gen_or_prev) == gen
2478 }
2479 #[inline(always)]
2480 fn is_cell(&self) -> bool {
2481 IdxD::is_type_a(self.d_gen_or_prev)
2482 }
2483 #[inline(always)]
2484 fn is_free(&self) -> bool {
2485 IdxD::is_type_b(self.d_gen_or_prev)
2486 }
2487
2488 fn new_cell(val: T, gen: usize) -> PrisonCell<T> {
2489 PrisonCell {
2490 refs_or_next: 0,
2491 d_gen_or_prev: IdxD::new_type_a(gen),
2492 val: MaybeUninit::new(val),
2493 }
2494 }
2495
2496 fn make_free_unchecked(&mut self, next: usize, prev: usize) -> T {
2497 self.d_gen_or_prev = IdxD::new_type_b(prev);
2498 self.refs_or_next = next;
2499 unsafe { mem_replace(&mut self.val, MaybeUninit::uninit()).assume_init() }
2500 }
2501
2502 fn make_cell_unchecked(&mut self, val: T, gen: usize) {
2503 self.d_gen_or_prev = IdxD::new_type_a(gen);
2504 self.refs_or_next = 0;
2505 self.val = MaybeUninit::new(val);
2506 }
2507
2508 fn overwrite_cell_unchecked(&mut self, val: T, gen: usize) {
2509 self.d_gen_or_prev = IdxD::new_type_a(gen);
2510 self.refs_or_next = 0;
2511 unsafe { self.val.assume_init_drop() };
2512 self.val = MaybeUninit::new(val);
2513 }
2514}
2515
2516//------ Guarded Prison ------
2517//STRUCT PrisonValueMut
2518/// Struct representing a mutable reference to a value that has been allowed to leave the
2519/// [Prison] temporarily, but remains guarded by a wrapper to prevent it from leaking or never unlocking
2520///
2521/// [PrisonValueMut<T>] implements [Deref<Target = T>], [DerefMut<Target = T>], [AsRef<T>], [AsMut<T>],
2522/// [Borrow<T>], and [BorrowMut<T>] to allow transparent access to its underlying value
2523///
2524/// As long as the [PrisonValueMut] remains in scope, the element where it's value resides in the
2525/// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
2526/// You can manually drop the [PrisonValueMut] out of scope by passing it as the first parameter
2527/// to the function [PrisonValueMut::unguard(p_val_mut)]
2528///
2529/// You can obtain a [PrisonValueMut] by calling `guard_mut()` or `guard_mut_idx()` on a [Prison]
2530/// ### Example
2531/// ```rust
2532/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
2533/// # fn main() -> Result<(), AccessError> {
2534/// let prison: Prison<u32> = Prison::new();
2535/// let key_0 = prison.insert(10)?;
2536/// let mut grd_0 = prison.guard_mut(key_0)?;
2537/// assert_eq!(*grd_0, 10);
2538/// *grd_0 = 20;
2539/// PrisonValueMut::unguard(grd_0);
2540/// prison.visit_ref(key_0, |val_0| {
2541/// assert_eq!(*val_0, 20);
2542/// Ok(())
2543/// });
2544/// # Ok(())
2545/// # }
2546/// ```
2547pub struct PrisonValueMut<'a, T> {
2548 cell: &'a mut PrisonCell<T>,
2549 prison_accesses: &'a mut usize,
2550}
2551
2552impl<'a, T> PrisonValueMut<'a, T> {
2553 //FN PrisonValueMut::unguard()
2554 /// Manually end a [PrisonValueMut] value's temporary guarded absence from the [Prison]
2555 ///
2556 /// This method simply takes ownership of the [PrisonValueMut] and immediately lets it go out of scope,
2557 /// causing it's `drop()` method to be called and clearing its mutable reference in the [Prison]
2558 /// ### Example
2559 /// ```rust
2560 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueMut}};
2561 /// # fn main() -> Result<(), AccessError> {
2562 /// let prison: Prison<u32> = Prison::new();
2563 /// prison.insert(10)?;
2564 /// let grd_0 = prison.guard_mut_idx(0)?;
2565 /// // index 0 CANNOT be accessed here because it is being guarded outside the prison
2566 /// assert!(prison.visit_ref_idx(0, |ref_0| Ok(())).is_err());
2567 /// PrisonValueMut::unguard(grd_0);
2568 /// // index 0 CAN be accessed here because it was returned to the prison
2569 /// assert!(prison.visit_ref_idx(0, |ref_0| Ok(())).is_ok());
2570 /// # Ok(())
2571 /// # }
2572 /// ```
2573 pub fn unguard(_prison_val_mut: Self) {}
2574}
2575
2576//IMPL Drop for PrisonValueMut
2577impl<'a, T> Drop for PrisonValueMut<'a, T> {
2578 fn drop(&mut self) {
2579 _remove_mut_ref(&mut self.cell.refs_or_next, self.prison_accesses)
2580 }
2581}
2582
2583//IMPL Deref for PrisonValueMut
2584impl<'a, T> Deref for PrisonValueMut<'a, T> {
2585 type Target = T;
2586
2587 #[inline(always)]
2588 fn deref(&self) -> &Self::Target {
2589 unsafe { self.cell.val.assume_init_ref() }
2590 }
2591}
2592
2593//IMPL DerefMut for PrisonValueMut
2594impl<'a, T> DerefMut for PrisonValueMut<'a, T> {
2595 #[inline(always)]
2596 fn deref_mut(&mut self) -> &mut Self::Target {
2597 unsafe { self.cell.val.assume_init_mut() }
2598 }
2599}
2600
2601//IMPL AsRef for PrisonValueMut
2602impl<'a, T> AsRef<T> for PrisonValueMut<'a, T> {
2603 #[inline(always)]
2604 fn as_ref(&self) -> &T {
2605 unsafe { self.cell.val.assume_init_ref() }
2606 }
2607}
2608
2609//IMPL AsMut for PrisonValueMut
2610impl<'a, T> AsMut<T> for PrisonValueMut<'a, T> {
2611 #[inline(always)]
2612 fn as_mut(&mut self) -> &mut T {
2613 unsafe { self.cell.val.assume_init_mut() }
2614 }
2615}
2616
2617//IMPL Borrow for PrisonValueMut
2618impl<'a, T> Borrow<T> for PrisonValueMut<'a, T> {
2619 #[inline(always)]
2620 fn borrow(&self) -> &T {
2621 unsafe { self.cell.val.assume_init_ref() }
2622 }
2623}
2624
2625//IMPL BorrowMut for PrisonValueMut
2626impl<'a, T> BorrowMut<T> for PrisonValueMut<'a, T> {
2627 #[inline(always)]
2628 fn borrow_mut(&mut self) -> &mut T {
2629 unsafe { self.cell.val.assume_init_mut() }
2630 }
2631}
2632
2633//STRUCT PrisonValueRef
2634/// Struct representing an immutable reference to a value that has been allowed to leave the
2635/// [Prison] temporarily, but remains guarded by a wrapper to prevent it from leaking or never unlocking
2636///
2637/// [PrisonValueRef<T>] implements [Deref<Target = T>], [AsRef<T>], and [Borrow<T>]
2638/// to allow transparent access to its underlying value
2639///
2640/// As long as the [PrisonValueRef] remains in scope, the element where it's value resides in the
2641/// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
2642/// You can manually drop the [PrisonValueRef] out of scope by passing it as the first parameter
2643/// to the function [PrisonValueRef::unguard(p_val_ref)]
2644///
2645/// You can obtain a [PrisonValueRef] by calling `guard_ref()` or `guard_ref_idx()` on a [Prison]
2646/// ### Example
2647/// ```rust
2648/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
2649/// # fn main() -> Result<(), AccessError> {
2650/// let prison: Prison<u32> = Prison::new();
2651/// let key_0 = prison.insert(10)?;
2652/// let mut grd_0 = prison.guard_ref(key_0)?;
2653/// assert_eq!(*grd_0, 10);
2654/// prison.visit_ref(key_0, |val_0| {
2655/// assert_eq!(*val_0, 10);
2656/// Ok(())
2657/// });
2658/// PrisonValueRef::unguard(grd_0);
2659/// # Ok(())
2660/// # }
2661/// ```
2662pub struct PrisonValueRef<'a, T> {
2663 cell: &'a mut PrisonCell<T>,
2664 prison_accesses: &'a mut usize,
2665}
2666
2667impl<'a, T> PrisonValueRef<'a, T> {
2668 //FN PrisonValueRef::unguard()
2669 /// Manually end a [PrisonValueRef] value's temporary guarded absence from the [Prison]
2670 ///
2671 /// This method simply takes ownership of the [PrisonValueRef] and immediately lets it go out of scope,
2672 /// causing it's `drop()` method to be called and decreasing its immutable reference count in the [Prison]
2673 /// ### Example
2674 /// ```rust
2675 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonValueRef}};
2676 /// # fn main() -> Result<(), AccessError> {
2677 /// let prison: Prison<u32> = Prison::new();
2678 /// prison.insert(10)?;
2679 /// let grd_0 = prison.guard_ref_idx(0)?;
2680 /// // index 0 CANNOT be accessed here because it is being guarded outside the prison
2681 /// assert!(prison.visit_mut_idx(0, |ref_0| Ok(())).is_err());
2682 /// PrisonValueRef::unguard(grd_0);
2683 /// // index 0 CAN be accessed here because it was returned to the prison
2684 /// assert!(prison.visit_mut_idx(0, |ref_0| Ok(())).is_ok());
2685 /// # Ok(())
2686 /// # }
2687 /// ```
2688 pub fn unguard(_prison_val_ref: Self) {}
2689}
2690
2691//IMPL Drop for PrisonValueRef
2692impl<'a, T> Drop for PrisonValueRef<'a, T> {
2693 fn drop(&mut self) {
2694 _remove_imm_ref(&mut self.cell.refs_or_next, self.prison_accesses)
2695 }
2696}
2697
2698//IMPL Deref for PrisonValueRef
2699impl<'a, T> Deref for PrisonValueRef<'a, T> {
2700 type Target = T;
2701
2702 #[inline(always)]
2703 fn deref(&self) -> &Self::Target {
2704 unsafe { self.cell.val.assume_init_ref() }
2705 }
2706}
2707
2708//IMPL AsRef for PrisonValueRef
2709impl<'a, T> AsRef<T> for PrisonValueRef<'a, T> {
2710 #[inline(always)]
2711 fn as_ref(&self) -> &T {
2712 unsafe { self.cell.val.assume_init_ref() }
2713 }
2714}
2715
2716//IMPL Borrow for PrisonValueRef
2717impl<'a, T> Borrow<T> for PrisonValueRef<'a, T> {
2718 #[inline(always)]
2719 fn borrow(&self) -> &T {
2720 unsafe { self.cell.val.assume_init_ref() }
2721 }
2722}
2723
2724//STRUCT PrisonSliceMut
2725/// Struct representing a slice of mutable references to values that have been allowed to leave the
2726/// [Prison] temporarily, but remain guarded by a wrapper to prevent them from leaking or never unlocking
2727///
2728/// [PrisonSliceMut<T>] implements [Deref<Target = \[&mut T\]>](Deref), [DerefMut<Target = \[&mut T\]>](DerefMut), [AsRef<\[&mut T\]>](AsRef), [AsMut<\[&mut T\]>](AsMut),
2729/// [Borrow<\[&mut T\]>](Borrow), and [BorrowMut<\[&mut T\]>](BorrowMut) to allow transparent access to its underlying slice of values
2730///
2731/// As long as the [PrisonSliceMut] remains in scope, the elements where it's values reside in the
2732/// [Prison] will remain marked as mutably referenced and unable to be referenced a second time.
2733/// You can manually drop the [PrisonSliceMut] out of scope by passing it as the first parameter
2734/// to the function [PrisonSliceMut::unguard(p_sli_mut)]
2735///
2736/// You can obtain a [PrisonSliceMut] by calling `guard_many_mut()` or `guard_many_mut_idx()` on a [Prison]
2737/// ### Example
2738/// ```rust
2739/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
2740/// # fn main() -> Result<(), AccessError> {
2741/// let prison: Prison<u32> = Prison::new();
2742/// let key_0 = prison.insert(10)?;
2743/// let key_1 = prison.insert(20)?;
2744/// let key_2 = prison.insert(30)?;
2745/// let mut grd_0_1_2 = prison.guard_many_mut(&[key_0, key_1, key_2])?;
2746/// assert_eq!(*grd_0_1_2[1], 20);
2747/// *grd_0_1_2[1] = 42;
2748/// PrisonSliceMut::unguard(grd_0_1_2);
2749/// prison.visit_ref(key_1, |val_1| {
2750/// assert_eq!(*val_1, 42);
2751/// Ok(())
2752/// });
2753/// # Ok(())
2754/// # }
2755/// ```
2756pub struct PrisonSliceMut<'a, T> {
2757 prison_accesses: &'a mut usize,
2758 refs: Vec<&'a mut usize>,
2759 vals: Vec<&'a mut T>,
2760}
2761
2762impl<'a, T> PrisonSliceMut<'a, T> {
2763 //FN PrisonSliceMut::unguard()
2764 /// Manually end a [PrisonSliceMut] value's temporary guarded absence from the [Prison]
2765 ///
2766 /// This method simply takes ownership of the [PrisonSliceMut] and immediately lets it go out of scope,
2767 /// causing it's `drop()` method to be called and decreasing its immutable reference count in the [Prison]
2768 /// ### Example
2769 /// ```rust
2770 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceMut}};
2771 /// # fn main() -> Result<(), AccessError> {
2772 /// let prison: Prison<u32> = Prison::new();
2773 /// prison.insert(10)?;
2774 /// prison.insert(20)?;
2775 /// let grd_all = prison.guard_many_mut_idx(&[0, 1])?;
2776 /// assert!(prison.visit_many_mut_idx(&[0, 1], |ref_all| Ok(())).is_err());
2777 /// PrisonSliceMut::unguard(grd_all);
2778 /// assert!(prison.visit_many_mut_idx(&[0, 1], |ref_all| Ok(())).is_ok());
2779 /// # Ok(())
2780 /// # }
2781 /// ```
2782 pub fn unguard(_prison_sli_mut: Self) {}
2783}
2784
2785//IMPL Drop for PrisonSliceMut
2786impl<'a, T> Drop for PrisonSliceMut<'a, T> {
2787 fn drop(&mut self) {
2788 _remove_many_mut_refs(&mut self.refs, self.prison_accesses)
2789 }
2790}
2791
2792//IMPL Deref for PrisonSliceMut
2793impl<'a, T> Deref for PrisonSliceMut<'a, T> {
2794 type Target = [&'a mut T];
2795
2796 #[inline(always)]
2797 fn deref(&self) -> &Self::Target {
2798 self.vals.as_slice()
2799 }
2800}
2801
2802//IMPL DerefMut for PrisonSliceMut
2803impl<'a, T> DerefMut for PrisonSliceMut<'a, T> {
2804 #[inline(always)]
2805 fn deref_mut(&mut self) -> &mut Self::Target {
2806 self.vals.as_mut_slice()
2807 }
2808}
2809
2810//IMPL AsRef for PrisonSliceMut
2811impl<'a, T> AsRef<[&'a mut T]> for PrisonSliceMut<'a, T> {
2812 #[inline(always)]
2813 fn as_ref(&self) -> &[&'a mut T] {
2814 self.vals.as_slice()
2815 }
2816}
2817
2818//IMPL AsMut for PrisonSliceMut
2819impl<'a, T> AsMut<[&'a mut T]> for PrisonSliceMut<'a, T> {
2820 #[inline(always)]
2821 fn as_mut(&mut self) -> &mut [&'a mut T] {
2822 self.vals.as_mut_slice()
2823 }
2824}
2825
2826//IMPL Borrow for PrisonSliceMut
2827impl<'a, T> Borrow<[&'a mut T]> for PrisonSliceMut<'a, T> {
2828 #[inline(always)]
2829 fn borrow(&self) -> &[&'a mut T] {
2830 self.vals.as_slice()
2831 }
2832}
2833
2834//IMPL BorrowMut for PrisonSliceMut
2835impl<'a, T> BorrowMut<[&'a mut T]> for PrisonSliceMut<'a, T> {
2836 #[inline(always)]
2837 fn borrow_mut(&mut self) -> &mut [&'a mut T] {
2838 self.vals.as_mut_slice()
2839 }
2840}
2841
2842//STRUCT PrisonSliceRef
2843/// Struct representing a slice of immutable references to values that have been allowed to leave the
2844/// [Prison] temporarily, but remain guarded by a wrapper to prevent them from leaking or never unlocking
2845///
2846/// [PrisonSliceRef<T>] implements [Deref<Target = \[&T\]>](Deref), [AsRef<\[&T\]>](AsRef),
2847/// and [Borrow<\[&T\]>](Borrow) to allow transparent access to its underlying slice of values
2848///
2849/// As long as the [PrisonSliceRef] remains in scope, the elements where it's values reside in the
2850/// [Prison] will remain marked as immutably referenced and unable to be mutably referenced.
2851/// You can manually drop the [PrisonSliceRef] out of scope by passing it as the first parameter
2852/// to the function [PrisonSliceRef::unguard(p_sli_ref)]
2853///
2854/// You can obtain a [PrisonSliceRef] by calling `guard_many_ref()` or `guard_many_ref_idx()` on a [Prison]
2855/// ### Example
2856/// ```rust
2857/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
2858/// # fn main() -> Result<(), AccessError> {
2859/// let prison: Prison<u32> = Prison::new();
2860/// let key_0 = prison.insert(10)?;
2861/// let key_1 = prison.insert(20)?;
2862/// let key_2 = prison.insert(30)?;
2863/// let mut grd_0_1_2 = prison.guard_many_ref(&[key_0, key_1, key_2])?;
2864/// assert_eq!(*grd_0_1_2[1], 20);
2865/// prison.visit_ref(key_1, |val_1| {
2866/// assert_eq!(*val_1, 20);
2867/// Ok(())
2868/// });
2869/// PrisonSliceRef::unguard(grd_0_1_2);
2870/// # Ok(())
2871/// # }
2872/// ```
2873pub struct PrisonSliceRef<'a, T> {
2874 prison_accesses: &'a mut usize,
2875 refs: Vec<&'a mut usize>,
2876 vals: Vec<&'a T>,
2877}
2878
2879impl<'a, T> PrisonSliceRef<'a, T> {
2880 //FN PrisonSliceRef::unguard()
2881 /// Manually end a [PrisonSliceRef] value's temporary guarded absence from the [Prison]
2882 ///
2883 /// This method simply takes ownership of the [PrisonSliceRef] and immediately lets it go out of scope,
2884 /// causing it's `drop()` method to be called and decreasing its immutable reference count in the [Prison]
2885 /// ### Example
2886 /// ```rust
2887 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{Prison, PrisonSliceRef}};
2888 /// # fn main() -> Result<(), AccessError> {
2889 /// let prison: Prison<u32> = Prison::new();
2890 /// prison.insert(10)?;
2891 /// prison.insert(20)?;
2892 /// let grd_all = prison.guard_many_ref_idx(&[0, 1])?;
2893 /// assert!(prison.visit_many_mut_idx(&[0, 1], |ref_all| Ok(())).is_err());
2894 /// PrisonSliceRef::unguard(grd_all);
2895 /// assert!(prison.visit_many_mut_idx(&[0, 1], |ref_all| Ok(())).is_ok());
2896 /// # Ok(())
2897 /// # }
2898 /// ```
2899 pub fn unguard(_prison_sli_ref: Self) {}
2900}
2901
2902//IMPL Drop for PrisonSliceRef
2903impl<'a, T> Drop for PrisonSliceRef<'a, T> {
2904 fn drop(&mut self) {
2905 _remove_many_imm_refs(&mut self.refs, self.prison_accesses)
2906 }
2907}
2908
2909//IMPL Deref for PrisonSliceRef
2910impl<'a, T> Deref for PrisonSliceRef<'a, T> {
2911 type Target = [&'a T];
2912
2913 #[inline(always)]
2914 fn deref(&self) -> &Self::Target {
2915 self.vals.as_slice()
2916 }
2917}
2918
2919//IMPL AsRef for PrisonSliceRef
2920impl<'a, T> AsRef<[&'a T]> for PrisonSliceRef<'a, T> {
2921 #[inline(always)]
2922 fn as_ref(&self) -> &[&'a T] {
2923 self.vals.as_slice()
2924 }
2925}
2926
2927//IMPL Borrow for PrisonSliceRef
2928impl<'a, T> Borrow<[&'a T]> for PrisonSliceRef<'a, T> {
2929 #[inline(always)]
2930 fn borrow(&self) -> &[&'a T] {
2931 self.vals.as_slice()
2932 }
2933}
2934
2935//====== JailCell ======
2936//STRUCT JailCell
2937/// Represents a single standalone value that allows interior mutability while upholding memory safety
2938/// with a reference counting [usize]
2939///
2940/// This is a very simple implementation of the principles found in [Prison]
2941///
2942/// It has a single [UnsafeCell] to allow interior mutability. The [UnsafeCell] holds
2943/// one single [usize] to track mutable and immutable references, and the value itself
2944/// of type `T`
2945///
2946/// It has `visit_ref()`, `visit_mut()`, `guard_ref()`, and `guard_mut()` methods, just like [Prison],
2947/// but with drastically simpler requirements for safety checking.
2948/// ### Example
2949/// ```rust
2950/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueRef}};
2951/// # fn main() -> Result<(), AccessError> {
2952/// let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
2953/// string_jail.visit_mut(|criminal| {
2954/// let bigger_bad = String::from("Dr. Lego-Step");
2955/// println!("Breaking News: {} to be set free to make room for {}", *criminal, bigger_bad);
2956/// *criminal = bigger_bad;
2957/// Ok(())
2958/// })?;
2959/// let guarded_criminal = string_jail.guard_ref()?;
2960/// println!("{} will now be paraded around town for public shaming", *guarded_criminal);
2961/// assert_eq!(*guarded_criminal, String::from("Dr. Lego-Step"));
2962/// JailValueRef::unguard(guarded_criminal);
2963/// # Ok(())
2964/// # }
2965/// ```
2966pub struct JailCell<T> {
2967 internal: UnsafeCell<JailCellMutable<T>>,
2968}
2969
2970impl<T> JailCell<T> {
2971 //FN JailCell::new()
2972 /// Creates a new [JailCell] with the supplied value of type `T`
2973 ///
2974 /// After creation, mutable or immutable references to it's value can only be obtained
2975 /// through its `visit_*()` or `guard_*()` methods
2976 pub fn new(value: T) -> JailCell<T> {
2977 return JailCell {
2978 internal: UnsafeCell::new(JailCellMutable {
2979 refs: 0,
2980 val: value,
2981 }),
2982 };
2983 }
2984
2985 //FN JailCell::visit_mut()
2986 /// Obtain a mutable reference to the [JailCell]'s internal value that gets passed to
2987 /// a closure you provide.
2988 /// ### Example
2989 /// ```rust
2990 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell}};
2991 /// # fn main() -> Result<(), AccessError> {
2992 /// let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
2993 /// string_jail.visit_mut(|criminal| {
2994 /// let bigger_bad = String::from("Dr. Lego-Step");
2995 /// println!("Breaking News: {} to be set free to make room for {}", *criminal, bigger_bad);
2996 /// *criminal = bigger_bad;
2997 /// Ok(())
2998 /// })?;
2999 /// # Ok(())
3000 /// # }
3001 /// ```
3002 /// ## Errors
3003 /// - [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
3004 /// - [AccessError::ValueStillImmutablyReferenced(0)] if value has any number of immutable references
3005 /// ### Example
3006 /// ```rust
3007 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell}};
3008 /// # fn main() -> Result<(), AccessError> {
3009 /// let jail: JailCell<u32> = JailCell::new(42);
3010 /// jail.visit_mut(|val| {
3011 /// assert!(jail.visit_mut(|val| Ok(())).is_err());
3012 /// Ok(())
3013 /// })?;
3014 /// jail.visit_ref(|val| {
3015 /// assert!(jail.visit_mut(|val| Ok(())).is_err());
3016 /// Ok(())
3017 /// })?;
3018 /// # Ok(())
3019 /// # }
3020 /// ```
3021 pub fn visit_mut<F>(&self, mut operation: F) -> Result<(), AccessError>
3022 where
3023 F: FnMut(&mut T) -> Result<(), AccessError>,
3024 {
3025 let internal = internal!(self);
3026 internal.add_ref_internal(true)?;
3027 let result = operation(&mut internal.val);
3028 internal.remove_ref_internal();
3029 return result;
3030 }
3031
3032 //FN JailCell::visit_ref()
3033 /// Obtain an immutable reference to the [JailCell]'s internal value that gets passed to
3034 /// a closure you provide.
3035 /// ### Example
3036 /// ```rust
3037 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell}};
3038 /// # fn main() -> Result<(), AccessError> {
3039 /// let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
3040 /// string_jail.visit_ref(|criminal| {
3041 /// println!("Breaking News: {} was just captured!", *criminal);
3042 /// Ok(())
3043 /// })?;
3044 /// # Ok(())
3045 /// # }
3046 /// ```
3047 /// ## Errors
3048 /// - [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
3049 /// - [AccessError::MaximumImmutableReferencesReached(0)] if value has usize::MAX - 2 immutable references already
3050 /// ### Example
3051 /// ```rust
3052 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell}};
3053 /// # fn main() -> Result<(), AccessError> {
3054 /// let jail: JailCell<u32> = JailCell::new(42);
3055 /// jail.visit_mut(|val| {
3056 /// assert!(jail.visit_ref(|val| Ok(())).is_err());
3057 /// Ok(())
3058 /// })?;
3059 /// # Ok(())
3060 /// # }
3061 /// ```
3062 pub fn visit_ref<F>(&self, mut operation: F) -> Result<(), AccessError>
3063 where
3064 F: FnMut(&T) -> Result<(), AccessError>,
3065 {
3066 let internal = internal!(self);
3067 internal.add_ref_internal(false)?;
3068 let result = operation(&internal.val);
3069 internal.remove_ref_internal();
3070 return result;
3071 }
3072
3073 //FN JailCell::guard_mut()
3074 /// Obtain an [JailValueMut] that marks the [JailCell] mutably referenced as long as it remains
3075 /// in scope and automatically unlocks it when it falls out of scope
3076 ///
3077 /// [JailValueMut<T>] implements [Deref<Target = T>], [DerefMut<Target = T>], [AsRef<T>], [AsMut<T>],
3078 /// [Borrow<T>], and [BorrowMut<T>] to allow transparent access to its underlying value
3079 ///
3080 /// You may manually drop the [JailValueMut] out of scope by passing it to the function
3081 /// [JailValueMut::unguard(_jail_val_mut)]
3082 /// ### Example
3083 /// ```rust
3084 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueMut}};
3085 /// # fn main() -> Result<(), AccessError> {
3086 /// let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
3087 /// let mut grd_criminal = string_jail.guard_mut()?;
3088 /// let bigger_bad = String::from("Dr. Lego-Step");
3089 /// println!("Breaking News: {} to be set free to make room for {}", *grd_criminal, bigger_bad);
3090 /// *grd_criminal = bigger_bad;
3091 /// JailValueMut::unguard(grd_criminal);
3092 /// # Ok(())
3093 /// # }
3094 /// ```
3095 /// ## Errors
3096 /// - [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
3097 /// - [AccessError::ValueStillImmutablyReferenced(0)] if value has any number of immutable references
3098 /// ### Example
3099 /// ```rust
3100 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueRef, JailValueMut}};
3101 /// # fn main() -> Result<(), AccessError> {
3102 /// let jail: JailCell<u32> = JailCell::new(42);
3103 /// let guard_ref = jail.guard_ref()?;
3104 /// assert!(jail.guard_mut().is_err());
3105 /// JailValueRef::unguard(guard_ref);
3106 /// let guard_mut = jail.guard_mut()?;
3107 /// assert!(jail.guard_mut().is_err());
3108 /// JailValueMut::unguard(guard_mut);
3109 /// # Ok(())
3110 /// # }
3111 /// ```
3112 #[must_use = "guarded reference will immediately fall out of scope"]
3113 pub fn guard_mut<'a>(&'a self) -> Result<JailValueMut<'a, T>, AccessError> {
3114 let internal = internal!(self);
3115 internal.add_ref_internal(true)?;
3116 return Ok(JailValueMut {
3117 ref_internal: internal,
3118 });
3119 }
3120
3121 //FN JailCell::guard_ref()
3122 /// Obtain an [JailValueRef] that marks the [JailCell] mutably referenced as long as it remains
3123 /// in scope and automatically unlocks it when it falls out of scope
3124 ///
3125 /// [JailValueRef<T>] implements [Deref<Target = T>], [AsRef<T>], and [Borrow<T>]
3126 /// to allow transparent access to its underlying value
3127 ///
3128 /// You may manually drop the [JailValueRef] out of scope by passing it to the function
3129 /// [JailValueRef::unguard(_jail_val_ref)]
3130 /// ### Example
3131 /// ```rust
3132 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueRef}};
3133 /// # fn main() -> Result<(), AccessError> {
3134 /// let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
3135 /// let grd_criminal = string_jail.guard_ref()?;
3136 /// println!("Breaking News: {} has been captured!", *grd_criminal);
3137 /// JailValueRef::unguard(grd_criminal);
3138 /// # Ok(())
3139 /// # }
3140 /// ```
3141 /// ## Errors
3142 /// - [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
3143 /// - [AccessError::MaximumImmutableReferencesReached(0)] if value has usize::MAX - 2 immutable references already
3144 /// ### Example
3145 /// ```rust
3146 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueMut}};
3147 /// # fn main() -> Result<(), AccessError> {
3148 /// let jail: JailCell<u32> = JailCell::new(42);
3149 /// let guard_mut = jail.guard_mut()?;
3150 /// assert!(jail.guard_ref().is_err());
3151 /// JailValueMut::unguard(guard_mut);
3152 /// # Ok(())
3153 /// # }
3154 /// ```
3155 #[must_use = "guarded reference will immediately fall out of scope"]
3156 pub fn guard_ref<'a>(&'a self) -> Result<JailValueRef<'a, T>, AccessError> {
3157 let internal = internal!(self);
3158 internal.add_ref_internal(false)?;
3159 return Ok(JailValueRef {
3160 ref_internal: internal,
3161 });
3162 }
3163 //FN JailCell::clone_val()
3164 /// Clones the requested value out of the [JailCell] into a new variable
3165 ///
3166 /// Only available when type T implements [Clone] (it is assumed that the implementation of `T::clone()` is memory safe).
3167 ///
3168 /// Because cloning does not alter the original, and because the new variable to hold the clone does not have any presumtions about the value, it
3169 /// is safe (in a single-threaded context) to clone out the value even if it is being visited or guarded.
3170 /// ### Example
3171 /// ```rust
3172 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueMut}};
3173 /// # fn main() -> Result<(), AccessError> {
3174 /// let jail: JailCell<String> = JailCell::new(String::from("Dolly"));
3175 /// let guard_mut = jail.guard_mut()?;
3176 /// let dolly_2 = jail.clone_val();
3177 /// JailValueMut::unguard(guard_mut);
3178 /// assert_eq!(dolly_2, String::from("Dolly"));
3179 /// # Ok(())
3180 /// # }
3181 /// ```
3182 pub fn clone_val(&self) -> T
3183 where
3184 T: Clone,
3185 {
3186 internal!(self).val.clone()
3187 }
3188
3189 //FN: JailCell::peek_ref()
3190 /// Get a reference to the value while ***ignoring reference counting and most other safety measures***
3191 ///
3192 /// This method is provided as a way for libraries depending on this code to perform niche
3193 /// optimized reads of contained values without the overhead of the normal safety checks,
3194 /// or when a mutable reference is active but you can statically confirm that the value will
3195 /// not be mutated from the begining of the returned `&T`'s lifetime to the end of it's lifetime.
3196 ///
3197 /// The returned reference is intended to be short-lived and safely contained in a scope where no
3198 /// mutation of the value takes place
3199 /// # Safety
3200 /// When you call this method and as long as the `&T` it returns remains in-scope/alive,
3201 /// you MUST ensure the following:
3202 /// - The value MUST NOT be mutated by ANY source, including active safe reference-counted mutable references
3203 /// - NO operation can be performed that could *potentially* cause the underlying memory address of the [JailCell]'s data to relocate
3204 pub unsafe fn peek_ref<'a>(&'a self) -> &'a T {
3205 &internal!(self).val
3206 }
3207}
3208
3209//IMPL Default for JailCell
3210impl<T> Default for JailCell<T>
3211where
3212 T: Default,
3213{
3214 fn default() -> Self {
3215 Self::new(T::default())
3216 }
3217}
3218
3219//STRUCT JailCellMutable
3220#[doc(hidden)]
3221struct JailCellMutable<T> {
3222 refs: usize,
3223 val: T,
3224}
3225
3226impl<T> JailCellMutable<T> {
3227 //FN JailCellMutable::add_ref_internal()
3228 fn add_ref_internal(&mut self, mutable: bool) -> Result<(), AccessError> {
3229 if self.refs == Refs::MUT {
3230 return Err(AccessError::ValueAlreadyMutablyReferenced(0));
3231 }
3232 if mutable && self.refs > 0 {
3233 return Err(AccessError::ValueStillImmutablyReferenced(0));
3234 }
3235 if self.refs == Refs::MAX_IMMUT {
3236 return Err(AccessError::MaximumImmutableReferencesReached(0));
3237 }
3238 if mutable {
3239 self.refs = Refs::MUT;
3240 } else {
3241 self.refs += 1;
3242 }
3243 return Ok(());
3244 }
3245
3246 //FN JailCellMutable::remove_ref_internal()
3247 fn remove_ref_internal(&mut self) {
3248 if self.refs == Refs::MUT {
3249 self.refs = 0;
3250 } else if self.refs > 0 {
3251 self.refs -= 1;
3252 }
3253 }
3254}
3255
3256//------ Guarded JailCell ------
3257//STRUCT JailValueMut
3258/// A guarded wrapper around a mutable reference to the value contained in a [JailCell]
3259///
3260/// [JailValueMut<T>] implements [Deref<Target = T>], [DerefMut<Target = T>], [AsRef<T>], [AsMut<T>],
3261/// [Borrow<T>], and [BorrowMut<T>] to allow transparent access to its underlying value
3262///
3263/// As long as the [JailValueMut] remains in scope, the value in [JailCell] will
3264/// remain marked as mutably referenced and unable to be referenced a second time.
3265/// You can manually drop the [JailValueMut] out of scope by passing it as the first parameter
3266/// to the function [JailValueMut::unguard(jail_val_mut)]
3267///
3268/// You can obtain a [JailValueMut] by calling `guard_mut()` on a [JailCell]
3269/// ### Example
3270/// ```rust
3271/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueMut}};
3272/// # fn main() -> Result<(), AccessError> {
3273/// let jail: JailCell<u32> = JailCell::new(42);
3274/// let mut grd_mut = jail.guard_mut()?;
3275/// assert_eq!(*grd_mut, 42);
3276/// *grd_mut = 69;
3277/// JailValueMut::unguard(grd_mut);
3278/// jail.visit_ref(|val| {
3279/// assert_eq!(*val, 69);
3280/// Ok(())
3281/// });
3282/// # Ok(())
3283/// # }
3284/// ```
3285pub struct JailValueMut<'a, T> {
3286 ref_internal: &'a mut JailCellMutable<T>,
3287}
3288
3289impl<'a, T> JailValueMut<'a, T> {
3290 //FN JailValueMut::unguard()
3291 /// Manually end a [JailValueMut] value's temporary guarded absence from the [JailCell]
3292 ///
3293 /// This method simply takes ownership of the [JailValueMut] and immediately lets it go out of scope,
3294 /// causing it's `drop()` method to be called and clearing its mutable reference in the [JailCell]
3295 /// ### Example
3296 /// ```rust
3297 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueMut}};
3298 /// # fn main() -> Result<(), AccessError> {
3299 /// let jail: JailCell<u32> = JailCell::new(42);
3300 /// let grd_mut = jail.guard_mut()?;
3301 /// // val CANNOT be referenced again because the mutable reference is still in scope
3302 /// assert!(jail.visit_ref(|val| Ok(())).is_err());
3303 /// JailValueMut::unguard(grd_mut);
3304 /// // val CAN be referenced again because the mutable reference was dropped
3305 /// assert!(jail.visit_ref(|val| Ok(())).is_ok());
3306 /// # Ok(())
3307 /// # }
3308 /// ```
3309 pub fn unguard(_guarded_jail_value: JailValueMut<'a, T>) {}
3310}
3311
3312//IMPL Drop for JailValueMut
3313impl<'a, T> Drop for JailValueMut<'a, T> {
3314 fn drop(&mut self) {
3315 self.ref_internal.remove_ref_internal();
3316 }
3317}
3318
3319//IMPL Deref for JailValueMut
3320impl<'a, T> Deref for JailValueMut<'a, T> {
3321 type Target = T;
3322
3323 #[inline(always)]
3324 fn deref(&self) -> &Self::Target {
3325 &self.ref_internal.val
3326 }
3327}
3328
3329//IMPL DerefMut for JailValueMut
3330impl<'a, T> DerefMut for JailValueMut<'a, T> {
3331 #[inline(always)]
3332 fn deref_mut(&mut self) -> &mut Self::Target {
3333 &mut self.ref_internal.val
3334 }
3335}
3336
3337//IMPL AsRef for JailValueMut
3338impl<'a, T> AsRef<T> for JailValueMut<'a, T> {
3339 #[inline(always)]
3340 fn as_ref(&self) -> &T {
3341 &self.ref_internal.val
3342 }
3343}
3344
3345//IMPL AsMut for JailValueMut
3346impl<'a, T> AsMut<T> for JailValueMut<'a, T> {
3347 #[inline(always)]
3348 fn as_mut(&mut self) -> &mut T {
3349 &mut self.ref_internal.val
3350 }
3351}
3352
3353//IMPL Borrow for JailValueMut
3354impl<'a, T> Borrow<T> for JailValueMut<'a, T> {
3355 #[inline(always)]
3356 fn borrow(&self) -> &T {
3357 &self.ref_internal.val
3358 }
3359}
3360
3361//IMPL BorrowMut for JailValueMut
3362impl<'a, T> BorrowMut<T> for JailValueMut<'a, T> {
3363 #[inline(always)]
3364 fn borrow_mut(&mut self) -> &mut T {
3365 &mut self.ref_internal.val
3366 }
3367}
3368
3369//STRUCT JailValueRef
3370/// A guarded wrapper around an immutable reference to the value contained in a [JailCell]
3371///
3372/// [JailValueRef<T>] implements [Deref<Target = T>], [AsRef<T>], and [Borrow<T>]
3373/// to allow transparent access to its underlying value
3374///
3375/// As long as the [JailValueRef] remains in scope, the value in [JailCell] will
3376/// remain marked as immutably referenced and unable to be mutably referenced.
3377/// You can manually drop the [JailValueRef] out of scope by passing it as the first parameter
3378/// to the function [JailValueRef::unguard(jail_val_ref)]
3379///
3380/// You can obtain a [JailValueRef] by calling `guard_ref()` on a [JailCell]
3381/// ### Example
3382/// ```rust
3383/// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueRef}};
3384/// # fn main() -> Result<(), AccessError> {
3385/// let jail: JailCell<u32> = JailCell::new(42);
3386/// let mut grd_ref = jail.guard_ref()?;
3387/// assert_eq!(*grd_ref, 42);
3388/// jail.visit_ref(|val| {
3389/// assert_eq!(*val, 42);
3390/// Ok(())
3391/// });
3392/// JailValueRef::unguard(grd_ref);
3393/// # Ok(())
3394/// # }
3395/// ```
3396pub struct JailValueRef<'a, T> {
3397 ref_internal: &'a mut JailCellMutable<T>,
3398}
3399
3400impl<'a, T> JailValueRef<'a, T> {
3401 //FN JailValueRef::unguard()
3402 /// Manually end a [JailValueRef] value's temporary guarded absence from the [JailCell]
3403 ///
3404 /// This method simply takes ownership of the [JailValueRef] and immediately lets it go out of scope,
3405 /// causing it's `drop()` method to be called and decreasing its immutable reference count in the [JailCell]
3406 /// ### Example
3407 /// ```rust
3408 /// # use grit_data_prison::{AccessError, CellKey, single_threaded::{JailCell, JailValueRef}};
3409 /// # fn main() -> Result<(), AccessError> {
3410 /// let jail: JailCell<u32> = JailCell::new(42);
3411 /// let grd_ref = jail.guard_ref()?;
3412 /// // val CANNOT be mutably referenced because the immutable reference is still in scope
3413 /// assert!(jail.visit_mut(|val| Ok(())).is_err());
3414 /// JailValueRef::unguard(grd_ref);
3415 /// // val CAN be mutably referenced because the immutable reference was dropped
3416 /// assert!(jail.visit_mut(|val| Ok(())).is_ok());
3417 /// # Ok(())
3418 /// # }
3419 /// ```
3420 pub fn unguard(_guarded_jail_value: Self) {}
3421}
3422
3423//IMPL Drop for JailValueRef
3424impl<'a, T> Drop for JailValueRef<'a, T> {
3425 fn drop(&mut self) {
3426 self.ref_internal.remove_ref_internal();
3427 }
3428}
3429
3430//IMPL Deref for JailValueRef
3431impl<'a, T> Deref for JailValueRef<'a, T> {
3432 type Target = T;
3433
3434 #[inline(always)]
3435 fn deref(&self) -> &Self::Target {
3436 &self.ref_internal.val
3437 }
3438}
3439
3440//IMPL AsRef for JailValueRef
3441impl<'a, T> AsRef<T> for JailValueRef<'a, T> {
3442 #[inline(always)]
3443 fn as_ref(&self) -> &T {
3444 &self.ref_internal.val
3445 }
3446}
3447
3448//IMPL Borrow for JailValueRef
3449impl<'a, T> Borrow<T> for JailValueRef<'a, T> {
3450 #[inline(always)]
3451 fn borrow(&self) -> &T {
3452 &self.ref_internal.val
3453 }
3454}
3455