-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
158 lines (127 loc) · 3.95 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
'use strict'
const { AbstractLevel, AbstractSnapshot } = require('abstract-level')
const ModuleError = require('module-error')
const createRBT = require('functional-red-black-tree')
const { MemoryEntryIterator } = require('./lib/iterator')
const { MemoryKeyIterator, MemoryValueIterator } = require('./lib/iterator')
const { MemoryClearIterator } = require('./lib/iterator')
const compare = require('./lib/compare')
const isRangeOption = require('./lib/is-range-option')
const kTree = Symbol('tree')
class MemoryLevel extends AbstractLevel {
#tree
constructor (location, options) {
// Take a dummy location argument to align with other implementations
if (typeof location === 'object' && location !== null) {
options = location
}
let { storeEncoding, ...forward } = options || {}
storeEncoding = storeEncoding || 'buffer'
// Our compare() function supports Buffer, Uint8Array and strings
if (!['buffer', 'view', 'utf8'].includes(storeEncoding)) {
throw new ModuleError("The storeEncoding option must be 'buffer', 'view' or 'utf8'", {
code: 'LEVEL_ENCODING_NOT_SUPPORTED'
})
}
super({
seek: true,
explicitSnapshots: true,
permanence: false,
createIfMissing: false,
errorIfExists: false,
has: true,
encodings: { [storeEncoding]: true },
signals: {
// Would have no value here because the operations are synchronous
iterators: false
}
}, forward)
this.#tree = createRBT(compare)
}
async _put (key, value, options) {
const it = this.#tree.find(key)
if (it.valid) {
this.#tree = it.update(value)
} else {
this.#tree = this.#tree.insert(key, value)
}
}
async _get (key, options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return tree.get(key)
}
async _getMany (keys, options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return keys.map(get, tree)
}
async _has (key, options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return tree.get(key) !== undefined
}
async _hasMany (keys, options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return keys.map(has, tree)
}
async _del (key, options) {
this.#tree = this.#tree.remove(key)
}
async _batch (operations, options) {
let tree = this.#tree
for (const op of operations) {
const key = op.key
const it = tree.find(key)
if (op.type === 'put') {
tree = it.valid ? it.update(op.value) : tree.insert(key, op.value)
} else {
tree = it.remove()
}
}
this.#tree = tree
}
async _clear (options) {
if (options.limit === -1 && !Object.keys(options).some(isRangeOption) && options.snapshot == null) {
// Delete everything by creating a new empty tree.
this.#tree = createRBT(compare)
return
}
const tree = options.snapshot?.[kTree] ?? this.#tree
const iterator = new MemoryClearIterator(this, tree, options)
try {
await iterator.visit(this.#clearKey)
} finally {
await iterator.close()
}
}
#clearKey = (key) => {
// Must also include changes made in parallel to clear()
this.#tree = this.#tree.remove(key)
}
_iterator (options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return new MemoryEntryIterator(this, tree, options)
}
_keys (options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return new MemoryKeyIterator(this, tree, options)
}
_values (options) {
const tree = options.snapshot?.[kTree] ?? this.#tree
return new MemoryValueIterator(this, tree, options)
}
_snapshot (options) {
return new MemorySnapshot(this.#tree, options)
}
}
class MemorySnapshot extends AbstractSnapshot {
constructor (tree, options) {
super(options)
this[kTree] = tree
}
}
exports.MemoryLevel = MemoryLevel
function get (key) {
return this.get(key)
}
function has (key) {
return this.get(key) !== undefined
}