16 次重大发布
0.17.0 | 2023年9月23日 |
---|---|
0.16.1 | 2023年4月6日 |
0.16.0 | 2022年12月26日 |
0.15.0 | 2022年7月5日 |
0.3.0 | 2021年6月28日 |
#141 in 并发
每月 233 次下载
用于 28 个 Crates (直接使用 3 个)
120KB
3K SLoC
🗂️ resman
运行时管理资源借用。
此库提供了一个可以存储任何类型之一以及同时为每种类型提供可变借用的映射。
注意: 此实现是从 shred
中提取的,以下有一些不同:
Debug
实现打印出键的类型名称而不是类型 ID。- 使用
downcast-rs
而不是mopa
来进行类型降级。 - 当资源类型实现了这些特质时,为借用类型添加了
Debug
和PartialEq
实现。 - 当资源已被借用时,对于
try_borrow*
函数,返回Err
而不是引发恐慌。
用法
将以下内容添加到 Cargo.toml
resman = "0.16.0"
# or
resman = { version = "0.17.0", features = ["debug"] }
resman = { version = "0.17.0", features = ["fn_res"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_meta"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut", "fn_meta"] }
# requires nightly
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut", "fn_res_once"] }
代码中
use resman::Resources;
#[derive(Debug)]
struct A(u32);
#[derive(Debug)]
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.borrow_mut::<A>();
let mut b = resources.borrow_mut::<B>();
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 a_0 = resources.borrow::<A>();
let _a_1 = resources.borrow::<A>();
let b = resources.borrow::<B>();
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 a_try_borrow_mut = resources.try_borrow_mut::<A>();
let exists = if a_try_borrow_mut.is_ok() {
"Ok(..)"
} else {
"Err"
};
println!("a_try_borrow_mut: {}", exists); // prints "Err"
功能
"debug"
:
Debug
实现 Resources
将在打印时使用值的 Debug
实现。这要求所有 Resources
也实现 Debug
。
示例
use resman::Resources;
let mut resources = Resources::default();
resources.insert(1u32);
println!("{:?}", resources);
// Without `"debug"` feature:
// {u32: ".."}
// With `"debug"` feature:
// {u32: 1}
"fn_res"
:
启用 FnRes
特质,允许在泛型函数类型下动态调用函数。
此 API 的使用方法如下:
-
定义要运行的常规函数或闭包。
- 函数应将
&T
或&mut T
作为参数。 - 所有函数的返回类型应相同。
目前参数限制为 7 个。
- 函数应将
-
调用
my_function.into_fn_res()
以获得Box<dyn FnRes>
。 -
调用
fn_res.call(&resources)
以自动从resources
借用T
并调用函数。
示例
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.into_fn_res(),
f2.into_fn_res(),
(|a: &u32, b: &u64| *a as u64 + *b).into_fn_res(),
];
let mut resources = Resources::default();
resources.insert(0u32);
resources.insert(0u64);
let sum = functions
.iter()
.fold(0, |sum, fn_res| sum + fn_res.call(&resources));
assert_eq!(5, sum); // 1 + 2 + 2
let debug_str = format!("{:?}", resources);
assert!(debug_str.contains("u32: 1"));
assert!(debug_str.contains("u64: 1"));
由于 Resources
具有内部可变性,在使用 FnRes::call
时,必须注意不要同时运行多个从 Resources
可变借用相同值的函数,否则会导致恐慌。
使用 FnRes::try_call
的非恐慌版本,如果在运行时出现重叠借用冲突,它将返回一个 BorrowFail
错误。
"fn_res_mut"
:
与 "fn_res"
类似,启用 IntoFnResMut
和 FnResMut
特性。
FnResMut
为实现了 impl FnMut
的函数和闭包实现,但不为 Fn
实现。
"fn_res_once"
:
需要使用 nightly
与 "fn_res_mut"
类似,启用 IntoFnResOnce
和 FnResOnce
特性。
FnResOnce
为实现了 impl FnOnce
的函数和闭包实现,但不为 FnMut
实现。
"fn_meta"
:
将 FnMeta
作为隐式特性添加到 FnRes
。这意味着可以查询任何 FnRes
的函数元数据。
"high_arg_count"
:
将 FnRes
、IntoFnRes
和 IntoFnResource
实现的参数数量从 6 增加到 8。
这是因为随着参数数量的增加,编译时间显著增加——当仅启用 "fn_res"
时,从 6 个参数的 4 秒增加到 8 个参数的 26 秒,当启用 "fn_mut"
和 "fn_once"
时,可高达一分钟。
另请参阅
许可证
根据您选择,许可为以下之一
- Apache License,版本 2.0,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
自由选择。
贡献
除非您明确说明,否则根据 Apache-2.0 许可证定义,任何有意提交以包含在您的工作中的贡献,都将按上述方式双许可,没有任何额外的条款或条件。
依赖关系
~1MB
~22K SLoC