1
1
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
2
3
- use std:: cell:: RefCell ;
3
+ use std:: cell:: UnsafeCell ;
4
4
use std:: collections:: HashMap ;
5
5
6
6
/// A hash map that supports inserting data while holding references to
@@ -9,8 +9,8 @@ use std::collections::HashMap;
9
9
/// previously inserted to key will cause a panic.
10
10
pub struct AdditiveOnlyMap < K , V > {
11
11
// store the values in a box to ensure the references are always stored
12
- // in the same place
13
- data : RefCell < HashMap < K , Box < V > > > ,
12
+ // in the same place. Uses an UnsafeCell for faster performance.
13
+ data : UnsafeCell < HashMap < K , Box < V > > > ,
14
14
}
15
15
16
16
impl < K , V > Default for AdditiveOnlyMap < K , V > {
@@ -25,29 +25,32 @@ impl<K, V> AdditiveOnlyMap<K, V> {
25
25
#[ cfg( test) ]
26
26
pub fn with_capacity ( capacity : usize ) -> Self {
27
27
Self {
28
- data : RefCell :: new ( HashMap :: with_capacity ( capacity) ) ,
28
+ data : UnsafeCell :: new ( HashMap :: with_capacity ( capacity) ) ,
29
29
}
30
30
}
31
31
32
32
pub fn len ( & self ) -> usize {
33
- self . data . borrow ( ) . len ( )
33
+ let data = unsafe { & * self . data . get ( ) } ;
34
+ data. len ( )
34
35
}
35
36
}
36
37
37
38
impl < K : Eq + std:: hash:: Hash , V > AdditiveOnlyMap < K , V > {
39
+ pub fn contains_key ( & self , key : & K ) -> bool {
40
+ let data = unsafe { & * self . data . get ( ) } ;
41
+ data. contains_key ( key)
42
+ }
43
+
38
44
pub fn insert ( & self , key : K , value : V ) {
45
+ let data = unsafe { & mut * self . data . get ( ) } ;
39
46
// assert that we never replace any data
40
- assert ! ( self
41
- . data
42
- . borrow_mut( )
43
- . insert( key, Box :: new( value) )
44
- . is_none( ) ) ;
47
+ assert ! ( data. insert( key, Box :: new( value) ) . is_none( ) ) ;
45
48
}
46
49
47
50
pub fn get < ' a > ( & ' a self , key : & K ) -> Option < & ' a V > {
48
- // this is ok because we never remove from the map
49
51
unsafe {
50
- let data = self . data . borrow ( ) ;
52
+ let data = & * self . data . get ( ) ;
53
+ // this is ok because we never remove from the map
51
54
data
52
55
. get ( key)
53
56
. map ( |value_box| value_box. as_ref ( ) as * const V )
@@ -76,5 +79,7 @@ mod test {
76
79
assert_eq ! ( data. value, 987 ) ;
77
80
assert_eq ! ( map. get( & 0 ) . unwrap( ) . value, 987 ) ;
78
81
assert_eq ! ( map. get( & 99 ) . unwrap( ) . value, 99 ) ;
82
+ assert ! ( map. contains_key( & 99 ) ) ;
83
+ assert ! ( !map. contains_key( & 100 ) ) ;
79
84
}
80
85
}
0 commit comments