2个版本
0.0.4 | 2021年10月10日 |
---|---|
0.0.3 | 2021年9月19日 |
0.0.2 |
|
0.0.1 |
|
在数据结构中排名第1238
每月下载量35次
60KB
904 行
pinus
带刺的BTreeMap。
- 您可以通过共享引用进行插入,并且值是pin-projected。
- 您可以通过独占引用删除键和释放条目。
- 您可以通过独占引用删除值,直到
PineMap
被固定。
这个容器API 是好的 ☕🐕,但即使不直接引用该crate也可以完全使用。
这个crate与fruit-salad 🥗配合得很好
需要帮助!
我只需要为我的项目(们)提供一个相当简单的数据结构实现,不一定是优化版本,但如果有人感兴趣,我将致力于维护它。
请遵循上面的“良好入门问题”徽章作为起点!
请注意,该crate非常频繁地使用unsafe代码,因此您应该至少在一定程度上熟悉手动确保其正确性。代码审查也非常受欢迎,无论是内部还是外部。
安装
请使用cargo-edit始终添加此库的最新版本
cargo add pinus
示例
同质映射
use pinus::{prelude::*, sync::PineMap};
use std::{convert::Infallible, pin::Pin};
use this_is_fine::prelude::*;
// `PineMap` is interior-mutable, so either is useful:
let map = PineMap::new();
let mut mut_map = PineMap::new();
// Get parallel shared references by inserting like this:
let a: &String = map.insert("Hello!", "Hello!".to_string())
.unwrap(/* Your data back if the entry already existed. */);
let b: &String = map.insert_with("Hello again!", |k| k.to_string())
.map_err(|(key, _factory)| key).unwrap();
let c: &String = map.try_insert_with::<_, Infallible>("Hello once again!", |k| Ok(k.to_string()))
.unwrap(/* Error from factory. */)
.map_err(|(key, _factory)| key).unwrap();
let a2: &String = map.get("Hello!").unwrap();
let _ = (a, a2, b, c);
// Get exclusive references like this (also with or without factory):
let mut_a: &mut String = mut_map.insert_with_mut("Hi!", |k| k.to_string())
.map_err(|(key, _factory)| key).unwrap();
let mut_a2: &mut String = mut_map.get_mut("Hi!").unwrap();
// The `…_mut` methods are actually faster, but their results can't be held onto at once:
// let _ = (mut_a, mut_a2); // "error[E0499]: cannot borrow `mut_map` as mutable more than once at a time"
// Remove entries like this:
mut_map.clear();
let _: Option<(&str, String)> = mut_map.remove_pair("A");
let _: Option<String> = mut_map.remove_value("B");
let _: Option<&str> = mut_map.remove_key("C");
let _: bool = mut_map.drop_entry("D");
/////
// Now on to part 2, value pinning:
let mut map: Pin<_> = map.pin();
let mut mut_map: Pin<_> = mut_map.pin();
// Shared references to values are now pinned:
let a: Pin<&String> = map.insert("Hello!!", "Hello!!".to_string())
.unwrap();
let b: Pin<&String> = map.insert_with("Hello again!!", |k| k.to_string())
.ok().unwrap();
let c: Pin<&String> = map.try_insert_with::<_, Infallible>("Hello once again!!", |k| Ok(k.to_string()))
.unwrap().ok().unwrap();
let a2: Pin<&String> = map.get("Hello!").unwrap();
let _ = (a, a2, b, c);
// Exclusive references to values are also pinned:
let mut mut_a: Pin<&mut String> = mut_map.insert_with_mut("Hi!", |k| k.to_string())
.map_err(|(key, _factory)| key).unwrap();
let mut mut_a2: Pin<&mut String> = mut_map.get_mut("Hi!").unwrap();
// The `…_mut` methods are actually faster, but their results can't be held onto at once:
// let _ = (mut_a, mut_a2); // "error[E0499]: cannot borrow `mut_map` as mutable more than once at a time"
// Only keys can be removed now, but values must be dropped in place:
mut_map.clear();
let _: Option<&str> = mut_map.remove_key("C");
let _: bool = mut_map.drop_entry("D");
异质映射
use pinus::{prelude::*, sync::PressedPineMap};
use std::{
any::Any,
borrow::{Borrow, BorrowMut},
convert::Infallible,
pin::Pin,
};
use this_is_fine::prelude::*;
let map = PressedPineMap::<_, dyn Any>::new();
// `dyn Any` is `!Sized`,
// so it's necessary to use the loosely-typed emplacement methods:
let _: &dyn Any = map
.emplace_with(1, |_key, slot| slot.write(()))
.ok(/* or key and factory */).unwrap();
let _: &dyn Any = map
.try_emplace_with::<_, Infallible>(2, |_key, slot| Ok(slot.write(())))
.unwrap(/* or factory error */)
.ok(/* or key and factory */).unwrap();
// There's also a by-value method,
// but it has slightly steeper requirements:
#[derive(Debug)]
struct MyAny;
impl std::borrow::Borrow<dyn Any> for MyAny { //…
# fn borrow(&self) -> &dyn Any { self }
# }
impl std::borrow::BorrowMut<dyn Any> for MyAny { //…
# fn borrow_mut(&mut self) -> &mut dyn Any { self }
# }
let _: &dyn Any = map
.emplace(3, MyAny)
.unwrap(/* or key and value */);
// As usual the map's values can be pinned:
let map: Pin<PressedPineMap<_, _>> = map.pin();
// And then further value references are pinned:
let _: Pin<&dyn Any> = map.emplace(4, MyAny).unwrap();
// To immediately get an unpinned reference, just use `.as_unpinned()`:
let _: &dyn Any = map.as_unpinned().emplace(5, MyAny).unwrap();
许可协议
受以下任一协议许可:
- Apache License,版本2.0 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确声明,否则您有意提交的任何贡献,根据Apache-2.0许可协议定义,应按上述方式双重许可,不附加任何额外条款或条件。
有关更多信息,请参阅CONTRIBUTING。
行为准则
变更日志
版本控制
pinus
严格遵循语义版本控制2.0.0,但有以下例外:
- 在主版本变更时,次要版本不会重置为0(除v1外)。
请将其视为全局功能级别。 - 补丁版本在主版本或次版本变更时不会重置为0(除了v0.1和v1)。
请将其视为全局补丁级别。
这包括上面指定的Rust版本要求。
较早的Rust版本可能兼容,但这可能会随着次版本或补丁版本而变化。
受功能和补丁影响的版本可以从CHANGELOG.md中的相应标题确定。
请注意,此crate的依赖可能具有更宽松的MSRV策略!如果您不手动生成Cargo.lock(或根据需要生成)并且需要支持比当前稳定版本更旧的编译器,请在您的自动化中使用cargo +nightly update -Z minimal-versions
。
依赖项
~0.7–1MB
~16K SLoC