restor 2.0.2

A dynamic resource storage system in rust.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
use std::any::{Any, TypeId};
use std::collections::HashMap;

mod errors;
mod hasher;
mod many;
mod map;
mod refcell_unit;
mod storageunit;
mod unit;

pub use errors::{DynamicResult, ErrorDesc, UnitError};
use hasher::PassthroughHasherBuilder;
pub use many::{Fetch, FetchMultiple};
pub use map::{Map, MapMut};
pub use refcell_unit::{DynamicStorage, RefCellUnit};
pub use storageunit::StorageUnit;
pub use unit::{Unit, Waitable};

///
/// The base structure for this library, contains all of the
/// dynamically typed storage units
///
/// This is the basis for this library. This should not be
/// directly interacted with, and should instead be interfaced
/// with the type alias at the root of this library:
///
/// * `DynamicStorage`:
/// Based on `RefCell`s, for its interior mutability.
/// This is _NOT_ `Send`, but it is faster, because it
/// does not use atomic operations.
/// * `MutexStorage`:
/// Uses a `Mutex` for `Send` capabilities, and interior mutability
/// This only exposes mutable getter methods, as there is only
/// a `&mut` api available for a `MappedMutexGuard`
/// * `RwLockStorage`:
/// This exposes the same api as a `RefCell` but is atomically guarded
/// and therefore guarantees a safe `Send`, while allowing multiple
/// readers.
///
/// The type parameter `U` is the `Unit` that is going to be used to store
/// the data that is placed into it. This type parameter should, once
/// again be avoided by the user, and should instead use the
/// type definitions that are noted above.
///
#[derive(Default)]
pub struct BlackBox<U: ?Sized> {
    pub(crate) data: HashMap<TypeId, Box<U>, PassthroughHasherBuilder>,
}

pub(crate) type Borrowed<'a, T> = <T as Unit<'a>>::Borrowed;
pub(crate) type MutBorrowed<'a, T> = <T as Unit<'a>>::MutBorrowed;

impl<U: ?Sized + for<'a> Unit<'a>> BlackBox<U> {
    ///
    /// A default implementation of `BlackBox`
    ///
    pub fn new() -> Self {
        Self {
            data: HashMap::with_hasher(PassthroughHasherBuilder),
        }
    }

    ///
    /// Checks if there is an allocated unit for
    /// the type parameter in the internal hashmap.
    ///
    /// # Example
    /// ```
    /// # fn main() {
    /// use restor::DynamicStorage;
    /// let mut storage = DynamicStorage::new();
    /// assert!(!storage.has_unit::<usize>());
    /// storage.allocate_for::<usize>();
    /// assert!(storage.has_unit::<usize>());
    /// # }
    /// ```
    #[inline]
    pub fn has_unit<T: 'static>(&self) -> bool {
        self.data.contains_key(&TypeId::of::<T>())
    }

    ///
    /// Inserts a value into the storage and returns it in the case
    /// that it's impossible to insert or it is already borrowed.
    ///
    /// This appends to a list of values in the case that there is
    /// one or values of the type in the internal storage.
    ///
    /// # Example
    /// ```
    /// # fn main() {
    /// use restor::{DynamicStorage, ErrorDesc};
    /// let mut storage = DynamicStorage::new();
    /// assert_eq!(storage.insert(0usize), Err((0usize, ErrorDesc::NoAllocatedUnit)));
    /// storage.allocate_for::<usize>();
    /// storage.insert(0usize).unwrap();
    /// # }
    /// ```
    ///
    /// # Example 2: Appending
    /// ```
    /// # fn main() {
    /// use restor::{DynamicStorage, ErrorDesc};
    /// let mut storage = DynamicStorage::new();
    /// storage.allocate_for::<usize>();
    /// storage.insert(0usize).unwrap();
    /// storage.insert(1usize).unwrap();
    /// storage.insert(2usize).unwrap();
    /// storage.run_for::<usize, (), _>(|x| {
    ///     assert_eq!(x.len(), 3);
    /// });
    /// # }
    /// ```
    ///
    /// ## Note
    /// - This returns a `Result<(), (T, ErrorDesc)>` for ease of use, with calling `.unwrap()`.
    /// - It is currently impossible to insert `Vec<T>`s, which would result in inserting `T`s.
    ///
    pub fn insert<T: 'static>(&self, data: T) -> Result<(), (T, ErrorDesc)> {
        let entry = self.data.get(&TypeId::of::<T>());
        match entry {
            Some(x) => match x.insert_any(Box::new(data)) {
                Some((x, e)) => Err((*x.downcast().unwrap(), e)),
                None => Ok(()),
            },
            None => Err((data, ErrorDesc::NoAllocatedUnit)),
        }
    }

    ///
    /// A waiting version of [`BlackBox::insert`]. This will wait for a lock to be available
    /// so as to be able to insert the data. This will work with all of the examples from
    /// [`BlackBox::insert`], as long as the storage type is `RwLockStorage` or `MutexStorage`.
    ///
    /// [`BlackBox::insert`]: #method.insert
    ///
    pub fn waiting_insert<'a, T: 'static>(&'a self, data: T) -> Result<(), (T, ErrorDesc)>
    where
        Borrowed<'a, U>: Waitable,
        MutBorrowed<'a, U>: Waitable,
    {
        let entry = self.data.get(&TypeId::of::<T>());
        match entry {
            Some(x) => match x.waiting_insert(Box::new(data)) {
                Some((x, e)) => Err((*x.downcast().unwrap(), e)),
                None => Ok(()),
            },
            None => Err((data, ErrorDesc::NoAllocatedUnit)),
        }
    }

    ///
    /// Sibling to `insert`, this inserts many values at the same time and returns them
    /// in the case of an error. This will append to a pre-exisiting dataset if there
    /// is one present, or a single value, if possible.
    ///
    /// # Example
    /// ```
    /// # fn main() {
    /// use restor::{DynamicStorage, ErrorDesc};
    /// let mut storage = DynamicStorage::new();
    /// assert_eq!(storage.insert_many(vec![0usize, 1, 2, 3]), Err((vec![0usize, 1, 2, 3], ErrorDesc::NoAllocatedUnit)));
    /// storage.allocate_for::<usize>();
    /// storage.insert_many(vec![0usize, 1, 2, 3]).unwrap();
    /// storage.insert_many(vec![4usize, 5, 6, 7]).unwrap();
    /// storage.run_for::<usize, (), _>(|x| {
    ///     assert_eq!(x, &[0usize, 1, 2, 3, 4, 5, 6, 7]);
    /// });
    /// # }
    /// ```
    ///
    /// ## Note
    /// This returns the `Vec` passed to it in the case of an erroneous attempt
    /// at inserting into the storage.
    ///
    pub fn insert_many<T: 'static>(&self, data: Vec<T>) -> Result<(), (Vec<T>, ErrorDesc)> {
        let entry = self.data.get(&TypeId::of::<T>());
        match entry {
            Some(x) => match x.insert_any(Box::new(data)) {
                Some((x, e)) => Err((*x.downcast().unwrap(), e)),
                None => Ok(()),
            },
            None => Err((data, ErrorDesc::NoAllocatedUnit)),
        }
    }

    ///
    /// Waits for a lock and inserts when possible. This, like [`insert_many`]
    /// returns a `Result<(), (Vec<T>, ErrorDesc)>`, which is meant to be used
    /// in most contexts as `storage.insert(value).unwrap()`.
    ///
    /// Please refer to both [`insert_many`] and [`insert`] for further info on
    /// this and related functions. Examples from both will work as long as the
    /// storage type used supports waiting, including both `RwLockStorage` and
    /// `MutexStorage`.
    ///
    /// [`insert_many`]: #method.insert_many
    /// [`insert`]: #method.insert
    ///
    pub fn waiting_insert_many<'a, T: 'static>(
        &'a self,
        data: Vec<T>,
    ) -> Result<(), (Vec<T>, ErrorDesc)>
    where
        Borrowed<'a, U>: Waitable,
        MutBorrowed<'a, U>: Waitable,
    {
        let entry = self.data.get(&TypeId::of::<T>());
        match entry {
            Some(x) => match x.waiting_insert(Box::new(data)) {
                Some((x, e)) => Err((*x.downcast().unwrap(), e)),
                None => Ok(()),
            },
            None => Err((data, ErrorDesc::NoAllocatedUnit)),
        }
    }

    ///
    /// Internal function. Returns a reference to the `Unit` for `T`
    ///
    #[inline]
    pub(crate) fn unit_get<T: 'static>(&self) -> DynamicResult<&U> {
        self.data
            .get(&TypeId::of::<T>())
            .map(|x| &**x)
            .ok_or(ErrorDesc::NoAllocatedUnit)
    }

    ///
    /// Takes a function and runs it on the internal slice of data.
    ///
    /// The function may return a piece of data, which will be returned
    /// in the [`DynamicResult`]`<D>` that is returned.
    ///
    /// The function takes a `&[T]`, so in the case it is impossible
    /// to acquire the appropriate data, it will short circuit and
    /// return the appropriate error instead of running `f`.
    ///
    /// The function is also `FnMut` so it can therefore mutate state
    /// such as in a `move ||` closure.
    ///
    /// [`DynamicResult`]: ./enum.ErrorDesc.html
    ///
    /// # Example
    /// ### Return nothing
    /// ```rust
    /// # fn main() {
    /// use restor::{DynamicStorage, make_storage};
    /// let storage = make_storage!(DynamicStorage: usize);
    /// storage.insert_many(vec![1usize, 2, 4, 8, 16, 32, 64, 128]).unwrap();
    /// storage.run_for::<usize, _, _>(|x| {
    ///     assert_eq!(x.iter().sum::<usize>(), 0b11111111);
    /// });
    /// # }
    /// ```
    /// ### Return something
    /// ```rust
    /// # fn main() {
    /// use restor::{DynamicStorage, make_storage};
    /// let storage = make_storage!(DynamicStorage: usize);
    /// storage.insert_many(vec![0usize, 1, 2, 3, 4, 5, 6, 7]).unwrap();
    /// let transformed = storage.run_for::<usize, _, _>(|x| {
    ///     x.iter()
    ///      .cloned()
    ///      .map(|nx| 2usize.pow(nx as u32))
    ///      .collect::<Vec<_>>()
    /// }).unwrap();
    /// assert_eq!(transformed,
    ///     vec![1, 2, 4, 8, 16, 32, 64, 128]
    /// );
    /// # }
    /// ```
    /// ### Handle error case
    /// ```
    /// # fn main() {
    /// use restor::{DynamicStorage, make_storage};
    /// let storage = make_storage!(DynamicStorage: usize);
    /// storage.insert_many(vec![1usize, 2, 4, 8, 16, 32, 64, 128]).unwrap();
    /// let res = storage.run_for::<usize, _, _>(|x| {
    ///     x.iter().sum::<usize>()
    /// }).expect("Error, couldn't get lock");
    /// println!("{:?}", res);
    /// # }
    /// ```
    ///
    pub fn run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
        &'b self,
        mut f: F,
    ) -> DynamicResult<D>
    where
        Borrowed<'b, U>: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>>,
    {
        let unit = self.unit_get::<T>()?;
        let dynstorage = unit.storage()?;
        let conv_func: &dyn for<'r> Fn(&'r dyn Any) -> &'r StorageUnit<T> =
            &|x| x.downcast_ref::<StorageUnit<T>>().unwrap();
        let storage = Map::map(dynstorage, conv_func);
        Ok(f(storage.many()?))
    }

    ///
    /// Waits for a lock and then runs a function over a slice within the lock.
    ///
    /// The only difference between this and [`run_for`] is that this will
    /// not immediately return in the case that it is impossible to acquire a
    /// lock to the data immediately upon calling.
    ///
    /// Any examples from [`run_for`] will work as long as the storage used
    /// is either [`RwLockStorage`] or [`MutexStorage`], because you cannot wait
    /// for a lock on a [`RefCell`] due to its single-threaded nature.
    ///
    /// [`run_for`]: #method.run_for
    /// [`RwLockStorage`]: ./struct.RwLockStorage.html
    /// [`MutexStorage`]: ./struct.MutexStorage.html
    /// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
    ///
    pub fn waiting_run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
        &'b self,
        mut f: F,
    ) -> DynamicResult<D>
    where
        Borrowed<'b, U>:
            Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>> + Waitable,
    {
        let unit = self.unit_get::<T>()?;
        let dynstorage = unit.waiting_storage();
        let conv_func: &dyn for<'r> Fn(&'r dyn Any) -> &'r StorageUnit<T> =
            &|x| x.downcast_ref::<StorageUnit<T>>().unwrap();
        let storage = Map::map(dynstorage, conv_func);
        Ok(f(storage.many()?))
    }

    ///
    /// Runs a function over a mutable [`Vec`] of type `T`, if there is a storage for
    /// `T` allocated. Similar to [`BlackBox::run_for`], this can optionally return an
    /// item, as long as it is an owned item, or has the same lifetime of the closure.
    ///
    /// The argument passed to the function is of type `Result<&mut Vec<T>, ErrorDesc>`
    /// so invalid attempts at running this function are handled within the closure.
    ///
    /// In the case that the `Vec` is left in an invalid state, only one value or no
    /// values, the internal storage is rearranged.
    ///
    /// # Note
    /// That this is the only way to extract an item from the storage given an index.
    ///
    /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
    /// [`BlackBox::run_for`]: #method.run_for
    ///
    /// # Examples
    /// ```rust
    /// # fn main() {
    /// use restor::{DynamicStorage, make_storage};
    /// let storage = make_storage!(DynamicStorage: usize);
    /// storage.insert_many(vec![0usize, 1, 2, 3, 4]);
    /// storage.run_for_mut::<usize, _, _>(|x| for i in x {*i *= 2; *i += 1;}).unwrap();
    /// storage.run_for::<usize, _, _>(|x| assert_eq!(x, &[1, 3, 5, 7, 9])).unwrap();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # fn main() {
    /// use restor::{DynamicStorage, make_storage};
    /// let storage = make_storage!(DynamicStorage: usize);
    /// storage.insert_many(vec![0usize, 1, 2, 3, 4]);
    /// //Remove all but one element from the contents:
    /// let v = storage.run_for_mut::<usize, _, _>(|x| {
    ///     x.split_off(1)
    /// }).unwrap();
    /// assert_eq!(v, vec![1, 2, 3, 4]);
    /// assert_eq!(*storage.get::<&usize>().unwrap(), 0usize);
    /// # }
    /// ```
    ///
    pub fn run_for_mut<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&mut Vec<T>) -> D + 'a>(
        &'b self,
        mut f: F,
    ) -> DynamicResult<D>
    where
        MutBorrowed<'b, U>:
            MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>,
    {
        let unit = self.unit_get::<T>()?;
        let dynstorage = unit.storage_mut()?;
        let conv_func: &dyn for<'r> Fn(&'r mut dyn Any) -> &'r mut StorageUnit<T> =
            &|x: &mut dyn Any| x.downcast_mut::<StorageUnit<T>>().unwrap();
        let mut storage = MapMut::map(dynstorage, conv_func);
        let res = f(storage.many_mut()?);
        storage.rearrange_if_necessary();
        Ok(res)
    }

    ///
    /// Waits for a lock and then runs a function over a slice within the lock.
    ///
    /// The only difference between this and [`run_for_mut`] is that this will
    /// not immediately return in the case that it is impossible to acquire a
    /// lock to the data immediately upon calling.
    ///
    /// Any examples from [`run_for_mut`] will work as long as the storage used
    /// is either [`RwLockStorage`] or [`MutexStorage`], because you cannot wait
    /// for a lock on a [`RefCell`] due to its single-threaded nature.
    ///
    /// [`run_for_mut`]: #method.run_for_mut
    /// [`RwLockStorage`]: ./struct.RwLockStorage.html
    /// [`MutexStorage`]: ./struct.MutexStorage.html
    /// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
    ///
    pub fn waiting_run_for_mut<
        'a,
        'b,
        T: 'static,
        D: 'static + Any,
        F: FnMut(&mut Vec<T>) -> D + 'a,
    >(
        &'b self,
        mut f: F,
    ) -> DynamicResult<D>
    where
        MutBorrowed<'b, U>:
            MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>
                + Waitable,
    {
        let unit = self.unit_get::<T>()?;
        let dynstorage = unit.waiting_storage_mut();
        let conv_func: &dyn for<'r> Fn(&'r mut dyn Any) -> &'r mut StorageUnit<T> =
            &|x: &mut dyn Any| x.downcast_mut::<StorageUnit<T>>().unwrap();
        let mut storage = MapMut::map(dynstorage, conv_func);
        let res = f(storage.many_mut()?);
        storage.rearrange_if_necessary();
        Ok(res)
    }

    ///
    /// "`get`"s values from the `BlackBox`, acquiring either locks or owned values
    /// depending on the type parameter(s) passed to this function. It follow these
    /// type mappings:
    ///
    /// - `&T -> Lock<T>`
    /// - `&mut T -> MutLock<T>`
    /// - `&[T] -> Lock<[T]>`
    /// - `&mut [T] -> MutLock<T>`
    /// - `Box<T> -> T`
    /// - `Vec<T> -> Vec<T>`
    ///
    /// Where `Lock` and `MutLock` are dependent on the kind of storage that you is
    /// being asked. For `DynamicStorage` it's [`Ref`] and [`RefMut`] respecitvely.
    /// For `MutexStorage` it is [`MappedMutexGuard`] for `MutLock`. It isn't possible
    /// to get a `Lock` from a `MutexStorage` due to its nature. For `RwLockStorage`
    /// a [`MappedRwLockReadGuard`] and a [`MappedRwLockWriteGuard`] are provided.
    ///
    /// [`Ref`]: https://doc.rust-lang.org/std/cell/struct.Ref.html
    /// [`RefMut`]: https://doc.rust-lang.org/std/cell/struct.RefMut.html
    /// [`MappedMutexGuard`]: https://docs.rs/parking_lot/0.8.0/parking_lot/type.MappedMutexGuard.html
    /// [`MappedRwLockReadGuard`]: https://docs.rs/parking_lot/0.8.0/parking_lot/type.MappedRwLockReadGuard.html
    /// [`MappedRwLockWriteGuard`]: https://docs.rs/parking_lot/0.8.0/parking_lot/type.MappedRwLockWriteGuard.html
    ///
    /// # Examples
    /// Read a single resource either mutably or immutably
    /// ```rust
    /// use restor::{DynamicStorage, make_storage, ok};
    /// let x = make_storage!(DynamicStorage: usize);
    /// x.insert(32usize).unwrap();
    /// let y = ok!(x.get::<&usize>());
    /// assert_eq!(*y, 32usize);
    /// drop(y);
    /// let mut y = ok!(x.get::<&mut usize>());
    /// *y = 20;
    /// drop(y);
    /// let y = ok!(x.get::<&usize>());
    /// assert_eq!(*y, 20);
    /// ```
    /// Read multiple resources either mutably or immutably
    /// ```rust
    /// use restor::{DynamicStorage, make_storage, ok};
    /// #[derive(Debug)]
    /// struct Person {
    ///     pub name: &'static str,
    ///     pub age: usize,
    /// }
    /// let x = make_storage!(DynamicStorage: usize, String, Person);
    /// let no_relatives = 3usize;
    /// let email = "john.doe@mailme.com".to_string();
    /// let person = Person {
    ///     name: "John Doe",
    ///     age: 32
    /// };
    /// x.insert(no_relatives).unwrap();
    /// x.insert(email).unwrap();
    /// x.insert(person).unwrap();
    /// {
    ///     let (person, no_relatives, mut email) = x.get::<(&Person, &usize, &mut String)>().unwrap();
    ///     println!("{:?}'s email is ", &*person);
    ///     println!("{}", &*email);
    ///     println!("And they've got {} relatives", *no_relatives);
    ///     *email = "doe.john@mailme.com".to_string();
    ///     println!("Their new email is {}", &*email);
    /// }
    /// ```
    /// Acquiring other forms of data
    /// ```rust
    /// use restor::{make_storage, DynamicStorage};
    /// let storage = make_storage!(DynamicStorage: usize, String);
    /// storage.insert_many(vec![0usize, 1, 2, 3, 4, 3, 2, 1, 0]).unwrap();
    /// storage.insert(String::new()).unwrap();
    /// storage.insert(String::from("Text")).unwrap();
    /// //We can iter over the returned lock
    /// assert_eq!(storage.get::<&[usize]>().unwrap().iter().sum::<usize>(), 16);
    /// //We can also get mutable locks to slices
    /// for i in storage.get::<&mut [usize]>().unwrap().iter_mut() {
    ///     *i += 30;
    /// }
    /// //We can extract an item, either from the
    /// //first slot or the only item. Note that
    /// //the returned value is not `Box<usize>`
    /// assert_eq!(storage.get::<Box<usize>>().unwrap(), 30);
    /// //This works for tuples. Each item in the
    /// //tuple is individually acquired, so we can
    /// //acquire multiple of the same type at the
    /// //same time.
    /// let (strings, number, nums) = storage.get::<(Vec<String>, Box<usize>, &[usize])>().unwrap();
    /// assert_eq!(strings, vec![String::new(), String::from("Text")]);
    /// assert_eq!(number, 31);
    /// assert_eq!(&*nums, &[32, 33, 34, 33, 32, 31, 30]);
    /// ```
    ///
    #[inline(always)]
    pub fn get<'a, T: FetchMultiple<'a, U>>(&'a self) -> DynamicResult<T::Output> {
        T::get_many(self)
    }
    ///
    /// Waits to get a lock for each of the types instead of returning an error in the case of
    /// a blocking operation. This will still return an error in the case that it is impossible
    /// to acquire the lock, due to a data format inconsistency (Such as a `Many` present when
    /// a `One` was requested) or a lack of an allocated `StorageUnit`. All the examples on
    /// [`BlackBox::get`] still apply as long as the type of storage used is either `RwLockStorage`
    /// or `MutexStorage`, because they are able to block the thread to acquire a lock.
    ///
    #[inline(always)]
    pub fn waiting_get<'a, T: FetchMultiple<'a, U>>(&'a self) -> DynamicResult<T::Output>
    where
        Borrowed<'a, U>: Waitable,
        MutBorrowed<'a, U>: Waitable,
    {
        T::waiting_get_many(self)
    }
}