@@ -46,9 +46,9 @@ export class BloomFilter {
46
46
private readonly sizeInInteger : Integer ;
47
47
48
48
constructor (
49
- private readonly bitmap : Uint8Array ,
50
- padding : number ,
51
- private readonly hashCount : number
49
+ private readonly _bitmap : Uint8Array ,
50
+ readonly padding : number ,
51
+ readonly hashCount : number
52
52
) {
53
53
if ( padding < 0 || padding >= 8 ) {
54
54
throw new BloomFilterError ( `Invalid padding: ${ padding } ` ) ;
@@ -58,12 +58,12 @@ export class BloomFilter {
58
58
throw new BloomFilterError ( `Invalid hash count: ${ hashCount } ` ) ;
59
59
}
60
60
61
- if ( bitmap . length > 0 && this . hashCount === 0 ) {
61
+ if ( _bitmap . length > 0 && this . hashCount === 0 ) {
62
62
// Only empty bloom filter can have 0 hash count.
63
63
throw new BloomFilterError ( `Invalid hash count: ${ hashCount } ` ) ;
64
64
}
65
65
66
- if ( bitmap . length === 0 ) {
66
+ if ( _bitmap . length === 0 ) {
67
67
// Empty bloom filter should have 0 padding.
68
68
if ( padding !== 0 ) {
69
69
throw new BloomFilterError (
@@ -72,11 +72,15 @@ export class BloomFilter {
72
72
}
73
73
}
74
74
75
- this . size = bitmap . length * 8 - padding ;
75
+ this . size = _bitmap . length * 8 - padding ;
76
76
// Set the size in Integer to avoid repeated calculation in mightContain().
77
77
this . sizeInInteger = Integer . fromNumber ( this . size ) ;
78
78
}
79
79
80
+ getBitMap ( ) : Uint8Array {
81
+ return new Uint8Array ( this . _bitmap ) ;
82
+ }
83
+
80
84
// Calculate the ith hash value based on the hashed 64bit integers,
81
85
// and calculate its corresponding bit index in the bitmap to be checked.
82
86
private getBitIndex ( num1 : Integer , num2 : Integer , index : number ) : number {
@@ -92,7 +96,7 @@ export class BloomFilter {
92
96
// Return whether the bit on the given index in the bitmap is set to 1.
93
97
private isBitSet ( index : number ) : boolean {
94
98
// To retrieve bit n, calculate: (bitmap[n / 8] & (0x01 << (n % 8))).
95
- const byte = this . bitmap [ Math . floor ( index / 8 ) ] ;
99
+ const byte = this . _bitmap [ Math . floor ( index / 8 ) ] ;
96
100
const offset = index % 8 ;
97
101
return ( byte & ( 0x01 << offset ) ) !== 0 ;
98
102
}
@@ -114,23 +118,40 @@ export class BloomFilter {
114
118
}
115
119
return true ;
116
120
}
121
+
122
+ /** Create bloom filter input for testing purposes only. */
123
+ static create (
124
+ numOfBits : number ,
125
+ hashCount : number ,
126
+ contains : string [ ]
127
+ ) : BloomFilter {
128
+ const padding = numOfBits % 8 === 0 ? 0 : 8 - ( numOfBits % 8 ) ;
129
+ const bitmap = new Uint8Array ( Math . ceil ( numOfBits / 8 ) ) ;
130
+ const bloomFilter = new BloomFilter ( bitmap , padding , hashCount ) ;
131
+ contains . forEach ( item => bloomFilter . insert ( item ) ) ;
132
+ return bloomFilter ;
133
+ }
134
+
135
+ private insert ( value : string ) : void {
136
+ if ( this . size === 0 || value === '' ) {
137
+ return ;
138
+ }
139
+
140
+ const md5HashedValue = getMd5HashValue ( value ) ;
141
+ const [ hash1 , hash2 ] = get64BitUints ( md5HashedValue ) ;
142
+ for ( let i = 0 ; i < this . hashCount ; i ++ ) {
143
+ const index = this . getBitIndex ( hash1 , hash2 , i ) ;
144
+ this . setBit ( index ) ;
145
+ }
146
+ }
147
+
148
+ private setBit ( index : number ) : void {
149
+ const indexOfByte = Math . floor ( index / 8 ) ;
150
+ const offset = index % 8 ;
151
+ this . _bitmap [ indexOfByte ] |= 0x01 << offset ;
152
+ }
117
153
}
118
154
119
155
export class BloomFilterError extends Error {
120
- /** The custom name for all FirebaseErrors. */
121
156
readonly name : string = 'BloomFilterError' ;
122
-
123
- /** @hideconstructor */
124
- constructor (
125
- /**
126
- * A custom error description.
127
- */
128
- readonly message : string
129
- ) {
130
- super ( message ) ;
131
- // HACK: We write a toString property directly because Error is not a real
132
- // class and so inheritance does not work correctly. We could alternatively
133
- // do the same "back-door inheritance" trick that FirebaseError does.
134
- this . toString = ( ) => `${ this . name } }: ${ this . message } ` ;
135
- }
136
157
}
0 commit comments