parent
2eefaef0ae
commit
5d46a7bf6b
@ -0,0 +1,112 @@
|
|||||||
|
//! Entry API
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OccupiedEntry<'a, K, V>(pub(crate) &'a mut Option<(K,V)>);
|
||||||
|
|
||||||
|
impl<'a, K, V> OccupiedEntry<'a, K, V>
|
||||||
|
where K: Collapse
|
||||||
|
{
|
||||||
|
pub fn get(&self) -> &V
|
||||||
|
{
|
||||||
|
&self.0.as_ref().unwrap().1
|
||||||
|
}
|
||||||
|
pub fn get_mut(&mut self) -> &mut V
|
||||||
|
{
|
||||||
|
&mut self.0.as_mut().unwrap().1
|
||||||
|
}
|
||||||
|
pub fn into_mut(self) -> &'a mut V
|
||||||
|
{
|
||||||
|
&mut self.0.as_mut().unwrap().1
|
||||||
|
}
|
||||||
|
pub fn key(&self) -> &K
|
||||||
|
{
|
||||||
|
&self.0.as_ref().unwrap().0
|
||||||
|
}
|
||||||
|
pub fn insert(&mut self, value: V) -> V
|
||||||
|
{
|
||||||
|
std::mem::replace(&mut self.0.as_mut().unwrap().1, value)
|
||||||
|
}
|
||||||
|
pub fn remove(self) -> V
|
||||||
|
{
|
||||||
|
self.remove_entry().1
|
||||||
|
}
|
||||||
|
pub fn remove_entry(self) -> (K, V)
|
||||||
|
{
|
||||||
|
self.0.take().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VacantEntry<'a,K,V>(pub(crate) &'a mut Option<(K,V)>, pub(crate) K);
|
||||||
|
|
||||||
|
impl<'a, K, V> VacantEntry<'a, K, V>
|
||||||
|
where K: Collapse
|
||||||
|
{
|
||||||
|
pub fn insert(self, value: V) -> &'a mut V
|
||||||
|
{
|
||||||
|
*self.0 = Some((self.1, value));
|
||||||
|
&mut self.0.as_mut().unwrap().1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_key(self) -> K
|
||||||
|
{
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key(&self) -> &K
|
||||||
|
{
|
||||||
|
&self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Entry<'a, K, V>
|
||||||
|
{
|
||||||
|
Vacant(VacantEntry<'a, K, V>),
|
||||||
|
Occupied(OccupiedEntry<'a, K, V>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> Entry<'a, K, V>
|
||||||
|
where K: Collapse
|
||||||
|
{
|
||||||
|
pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Entry<'a, K, V>
|
||||||
|
{
|
||||||
|
if let Self::Occupied(occuped) = &mut self {
|
||||||
|
f(occuped.get_mut())
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key(&self) -> &K
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Vacant(v) => v.key(),
|
||||||
|
Entry::Occupied(o) => o.key(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn or_insert_with<F: FnOnce() -> V>(self, with: F) -> &'a mut V
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Occupied(o) => o.into_mut(),
|
||||||
|
Entry::Vacant(v) => v.insert(with())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline] pub fn or_insert(self, value: V) -> &'a mut V
|
||||||
|
{
|
||||||
|
self.or_insert_with(|| value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> Entry<'a, K, V>
|
||||||
|
where K: Collapse,
|
||||||
|
V: Default
|
||||||
|
{
|
||||||
|
#[inline] pub fn or_default(self) -> &'a mut V
|
||||||
|
{
|
||||||
|
self.or_insert_with(Default::default)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,192 @@
|
|||||||
|
//! Tests
|
||||||
|
use super::*;
|
||||||
|
use std::collections::{
|
||||||
|
HashMap,
|
||||||
|
BTreeMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works()
|
||||||
|
{
|
||||||
|
let mut map = Map::new();
|
||||||
|
|
||||||
|
map.insert('>', false);
|
||||||
|
map.insert('<', true);
|
||||||
|
map.insert('ł', true);
|
||||||
|
|
||||||
|
let clone = map.clone();
|
||||||
|
|
||||||
|
for (k, v) in clone.into_iter()
|
||||||
|
{
|
||||||
|
assert!(map.get(&k) == Some(&v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_insert_type {
|
||||||
|
($ty:ty, $data:expr) => {
|
||||||
|
{
|
||||||
|
print!("Testing {}... ", std::any::type_name::<$ty>());
|
||||||
|
let mut small = Map::new();
|
||||||
|
let mut hash = HashMap::new();
|
||||||
|
|
||||||
|
for (i,x) in (0..).zip($data)
|
||||||
|
{
|
||||||
|
small.insert(x, i);
|
||||||
|
hash.insert(x, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(small.len(), hash.len());
|
||||||
|
|
||||||
|
for (k,v) in hash.iter()
|
||||||
|
{
|
||||||
|
assert_eq!(v, small.get(k).unwrap());
|
||||||
|
}
|
||||||
|
println!("OK");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($ty:tt) => {
|
||||||
|
test_insert_type!($ty, $ty::MIN..$ty::MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_char()
|
||||||
|
{
|
||||||
|
test_insert_type!(char, TEST_STRING.chars());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_primitive()
|
||||||
|
{
|
||||||
|
test_insert_type!(i8, TEST_STRING.chars());
|
||||||
|
test_insert_type!(u8);
|
||||||
|
test_insert_type!(i16);
|
||||||
|
test_insert_type!(u16);
|
||||||
|
test_insert_type!(i32, -100..1000);
|
||||||
|
test_insert_type!(u32, 0..10000);
|
||||||
|
test_insert_type!(u64, -100..1000);
|
||||||
|
test_insert_type!(i64, 0..10000);
|
||||||
|
test_insert_type!(u128, -100..1000);
|
||||||
|
test_insert_type!(i128, 0..10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(nightly)]
|
||||||
|
mod benchmarks
|
||||||
|
{
|
||||||
|
use super::*;
|
||||||
|
use test::{Bencher, black_box};
|
||||||
|
|
||||||
|
macro_rules! map_bench {
|
||||||
|
($b:expr, $map:ident) => {
|
||||||
|
let mut map = $map::new();
|
||||||
|
$b.iter(|| {
|
||||||
|
for chr in TEST_STRING.chars()
|
||||||
|
{
|
||||||
|
if let Some(ent) = map.get_mut(&chr) {
|
||||||
|
*ent += 1;
|
||||||
|
} else {
|
||||||
|
black_box(map.insert(chr, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! ent_bench {
|
||||||
|
($b:expr, $map:ident) => {
|
||||||
|
let mut map = $map::new();
|
||||||
|
$b.iter(|| {
|
||||||
|
for chr in TEST_STRING.chars()
|
||||||
|
{
|
||||||
|
black_box(*map.entry(chr).or_insert(0usize) += 1);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn es_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
ent_bench!(b, Map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn eh_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
ent_bench!(b, HashMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn eb_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
ent_bench!(b, BTreeMap);
|
||||||
|
}
|
||||||
|
#[bench]
|
||||||
|
fn s_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
map_bench!(b, Map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn h_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
map_bench!(b, HashMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn b_char(b: &mut Bencher)
|
||||||
|
{
|
||||||
|
map_bench!(b, BTreeMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_STRING: &str = r#"
|
||||||
|
君のようなひとになりたいな
|
||||||
|
「僕らしいひと」になりたいな
|
||||||
|
望むならそうすりゃいいけどさ
|
||||||
|
でもそれってほんとにぼくなのかい
|
||||||
|
|
||||||
|
子供騙しな夢ひとつ
|
||||||
|
こんな僕なら死ねばいいのに
|
||||||
|
|
||||||
|
こんな僕が生きてるだけで
|
||||||
|
何万人のひとが悲しんで
|
||||||
|
誰も僕を望まない
|
||||||
|
そんな世界だったらいいのにな
|
||||||
|
|
||||||
|
こんな僕が消えちゃうだけで
|
||||||
|
何億人のひとが喜んで
|
||||||
|
誰も何も憎まないなら
|
||||||
|
そんなうれしいことはないな
|
||||||
|
|
||||||
|
|
||||||
|
明日も僕は夢うつつ
|
||||||
|
このまま僕は消えていいのに
|
||||||
|
|
||||||
|
こんな僕が生きたところで
|
||||||
|
何億人のひとは知らないし
|
||||||
|
誰も僕を望まない
|
||||||
|
そんな世界だったらいいのかな
|
||||||
|
|
||||||
|
こんな僕が消えたところで
|
||||||
|
何億人のひとは変わらない
|
||||||
|
誰も僕を憎まないなら
|
||||||
|
損した事に変わりないな
|
||||||
|
|
||||||
|
最期なんかみんな同じように倒れてゆきます
|
||||||
|
メイドイン 他人 の 「自分自身」崩れてゆきます
|
||||||
|
最期なんかみんな同じように離れてくのに
|
||||||
|
|
||||||
|
こんな僕が生きてるだけで
|
||||||
|
なんで君はそんなに笑うの
|
||||||
|
君がそんな笑顔じゃ
|
||||||
|
悲しくても消えたくても
|
||||||
|
さよならする理由なんてもう
|
||||||
|
無ければいいのに
|
||||||
|
|
||||||
|
|
||||||
|
こんな僕が消えたところで
|
||||||
|
何億人のひとは変わらない
|
||||||
|
だけど僕を止める何かが
|
||||||
|
そんな顔しちゃ笑えないや "#;
|
Loading…
Reference in new issue