[−][src]Struct restor::BlackBox
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 onRefCell
s, for its interior mutability. This is NOTSend
, but it is faster, because it does not use atomic operations.MutexStorage
: Uses aMutex
forSend
capabilities, and interior mutability This only exposes mutable getter methods, as there is only a&mut
api available for aMappedMutexGuard
RwLockStorage
: This exposes the same api as aRefCell
but is atomically guarded and therefore guarantees a safeSend
, 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.
Methods
impl<U: ?Sized + for<'a> Unit<'a>> BlackBox<U>
[src]
pub fn new() -> Self
[src]
A default implementation of BlackBox
pub fn has_unit<T: 'static>(&self) -> bool
[src]
Checks if there is an allocated unit for the type parameter in the internal hashmap.
Example
use restor::DynamicStorage; let mut storage = DynamicStorage::new(); assert!(!storage.has_unit::<usize>()); storage.allocate_for::<usize>(); assert!(storage.has_unit::<usize>());
pub fn insert<T: 'static>(&self, data: T) -> Result<(), (T, ErrorDesc)>
[src]
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
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
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 insertingT
s.
pub fn waiting_insert<'a, T: 'static>(
&'a self,
data: T
) -> Result<(), (T, ErrorDesc)> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
[src]
&'a self,
data: T
) -> Result<(), (T, ErrorDesc)> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
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
.
pub fn insert_many<T: 'static>(
&self,
data: Vec<T>
) -> Result<(), (Vec<T>, ErrorDesc)>
[src]
&self,
data: Vec<T>
) -> Result<(), (Vec<T>, ErrorDesc)>
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
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 waiting_insert_many<'a, T: 'static>(
&'a self,
data: Vec<T>
) -> Result<(), (Vec<T>, ErrorDesc)> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
[src]
&'a self,
data: Vec<T>
) -> Result<(), (Vec<T>, ErrorDesc)> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
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
.
pub fn run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::Borrowed: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>>,
[src]
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::Borrowed: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>>,
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.
Example
Return nothing
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
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
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 waiting_run_for<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&[T]) -> D + 'a>(
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::Borrowed: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>> + Waitable,
[src]
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::Borrowed: Map<dyn Any, StorageUnit<T>, Func = dyn Fn(&dyn Any) -> &StorageUnit<T>> + Waitable,
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.
pub fn run_for_mut<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&mut Vec<T>) -> D + 'a>(
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::MutBorrowed: MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>,
[src]
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::MutBorrowed: MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>>,
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.
Examples
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();
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 waiting_run_for_mut<'a, 'b, T: 'static, D: 'static + Any, F: FnMut(&mut Vec<T>) -> D + 'a>(
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::MutBorrowed: MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>> + Waitable,
[src]
&'b self,
f: F
) -> Result<D, ErrorDesc> where
<U as Unit<'b>>::MutBorrowed: MapMut<dyn Any, StorageUnit<T>, Func = dyn Fn(&mut dyn Any) -> &mut StorageUnit<T>> + Waitable,
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.
pub fn get<'a, T: FetchMultiple<'a, U>>(
&'a self
) -> Result<T::Output, ErrorDesc>
[src]
&'a self
) -> Result<T::Output, ErrorDesc>
"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.
Examples
Read a single resource either mutably or immutably
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
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
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]);
pub fn waiting_get<'a, T: FetchMultiple<'a, U>>(
&'a self
) -> Result<T::Output, ErrorDesc> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
[src]
&'a self
) -> Result<T::Output, ErrorDesc> where
<U as Unit<'a>>::Borrowed: Waitable,
<U as Unit<'a>>::MutBorrowed: Waitable,
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.
Trait Implementations
Auto Trait Implementations
impl<U: ?Sized> Send for BlackBox<U> where
U: Send,
U: Send,
impl<U: ?Sized> Sync for BlackBox<U> where
U: Sync,
U: Sync,
Blanket Implementations
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> From<T> for T
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,