Runtime managed resource borrowing.
This library provides a map that can store one of any type, as well as mutable borrows to each type at the same time.
Note: This implementation is extracted from [shred
], with the
following differences:
Debug
implementation prints out the type name instead of type ID for the
key.downcast-rs
] instead of [mopa
] for downcasting types.Debug
and PartialEq
implementations for borrow types when the
resource type implements those traits.Err
instead of panicking for try_borrow*
functions when the
resource is already borrowed.Add the following to Cargo.toml
```toml resman = "0.16.0"
resman = { version = "0.16.0", features = ["debug"] } resman = { version = "0.16.0", features = ["fnres"] } resman = { version = "0.16.0", features = ["fnres", "fnresmut"] } resman = { version = "0.16.0", features = ["fnres", "fnmeta"] } resman = { version = "0.16.0", features = ["fnres", "fnresmut", "fnmeta"] }
resman = { version = "0.16.0", features = ["fnres", "fnresmut", "fnres_once"] } ```
In code:
```rust use resman::Resources;
struct A(u32);
struct B(u32);
let mut resources = Resources::default();
resources.insert(A(1)); resources.insert(B(2));
// We can validly have two mutable borrows from the Resources
map!
let mut a = resources.borrowmut::();
let mut b = resources.borrowmut::();
a.0 = 2;
b.0 = 3;
// We need to explicitly drop the A and B borrows, because they are runtime // managed borrows, and rustc doesn't know to drop them before the immutable // borrows after this. drop(a); drop(b);
// Multiple immutable borrows to the same resource are valid. let a0 = resources.borrow::(); let _a1 = resources.borrow::(); let b = resources.borrow::();
println!("A: {}", a_0.0); println!("B: {}", b.0);
// Trying to mutably borrow a resource that is already borrowed (immutably
// or mutably) returns Err
.
let atryborrowmut = resources.tryborrowmut::();
let exists = if atryborrowmut.isok() {
"Ok(..)"
} else {
"Err"
};
println!("atryborrowmut: {}", exists); // prints "Err"
```
"debug"
:The Debug
implementation for Resources
will use the Debug
implementation for the values when printed. This requires that all
Resources
to also implement Debug
.
Example:
```rust use resman::Resources;
let mut resources = Resources::default(); resources.insert(1u32); println!("{:?}", resources);
// Without "debug"
feature:
// {u32: ".."}
// With "debug"
feature:
// {u32: 1}
```
"fn_res"
:Enables the [FnRes
] trait, allowing dynamic functions invocation under a
generic function type.
Usage of this API is as follows:
Define regular functions or closures to run.
&T
or &mut T
as parameters.Currently there is a limit of 7 parameters.
Call my_function.into_fn_res()
to obtain a Box<dyn FnRes>
.
fn_res.call(&resources)
to automatically borrow T
from
resources
and invoke the function.Example:
```rust use resman::{FnRes, IntoFnRes, Resources};
/// Borrows u32
mutably, and u64
immutably.
fn f1(a: &mut u32, b: &u64) -> u64 {
*a += 1;
*a as u64 + *b
}
/// Borrows u32
immutably, and u64
mutably.
fn f2(a: &u32, b: &mut u64) -> u64 {
*b += 1;
*a as u64 + *b
}
let functions = [ f1.intofnres(), f2.intofnres(), (|a: &u32, b: &u64| *a as u64 + *b).intofnres(), ];
let mut resources = Resources::default(); resources.insert(0u32); resources.insert(0u64);
let sum = functions .iter() .fold(0, |sum, fnres| sum + fnres.call(&resources));
assert_eq!(5, sum); // 1 + 2 + 2
let debugstr = format!("{:?}", resources); assert!(debugstr.contains("u32: 1")); assert!(debug_str.contains("u64: 1")); ```
Since Resources
has internal mutability, care must be taken to not run
multiple functions that borrow the same value mutably from Resources
at
the same time when using [FnRes::call
], otherwise it will panic.
Use [FnRes::try_call
] for a non-panicking version, which will return a
[BorrowFail
] error if there is an overlapping borrow conflict at runtime.
"fn_res_mut"
:Like "fn_res"
, enables the IntoFnResMut
and FnResMut
traits.
FnResMut
is implemented for functions and closures that impl FnMut
, but
not Fn
.
"fn_res_once"
:Requires nightly
Like "fn_res_mut"
, enables the IntoFnResOnce
and FnResOnce
traits.
FnResOnce
is implemented for functions and closures that impl FnOnce
,
but not FnMut
.
"fn_meta"
:Adds [FnMeta
] as an implied trait to [FnRes
]. This means function
metadata can be queried for any FnRes
.
"high_arg_count"
:Raises the number of arguments that [FnRes
], [IntoFnRes
], and
[IntoFnResource
] are implemented for from 6 to 8.
This is feature gated because compilation time increasing significantly with
higher numbers of arguments -- as much as from 4 seconds for 6 arguments
to 26 seconds for 8 arguments when only "fn_res"
is enabled, and up to a
minute when "fn_mut"
and "fn_once"
are enabled.
anymap
]: Map of any type, without multiple mutable borrows.rt_map
]: Runtime managed mutable borrowing from a map.shred
]: Contains Resources
type, plus a task dispatcher.Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.