#interior-mutability #pin #b-tree

pinus

带刺的BTreeMap。您可以通过共享引用进行插入,并且值是pin-projected。

2个版本

0.0.4 2021年10月10日
0.0.3 2021年9月19日
0.0.2 2021年9月18日
0.0.1 2021年9月10日

数据结构中排名第1238

每月下载量35

MIT/Apache

60KB
904

pinus

Lib.rs Crates.io Docs.rs

Rust 1.55 CI Crates.io - License

GitHub open issues open pull requests good first issues

crev reviews

带刺的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-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