@nxtedition/rocksdb 10.2.0 → 10.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.cc +107 -83
- package/index.js +43 -23
- package/iterator.js +28 -16
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
- package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
- package/util.js +39 -0
package/binding.cc
CHANGED
|
@@ -435,16 +435,12 @@ struct Iterator final : public BaseIterator {
|
|
|
435
435
|
const std::optional<std::string>& gt,
|
|
436
436
|
const std::optional<std::string>& gte,
|
|
437
437
|
const bool fillCache,
|
|
438
|
-
const Encoding keyEncoding,
|
|
439
|
-
const Encoding valueEncoding,
|
|
440
438
|
const size_t highWaterMarkBytes,
|
|
441
439
|
std::shared_ptr<const rocksdb::Snapshot> snapshot,
|
|
442
440
|
bool tailing = false)
|
|
443
441
|
: BaseIterator(database, column, reverse, lt, lte, gt, gte, limit, fillCache, snapshot, tailing),
|
|
444
442
|
keys_(keys),
|
|
445
443
|
values_(values),
|
|
446
|
-
keyEncoding_(keyEncoding),
|
|
447
|
-
valueEncoding_(valueEncoding),
|
|
448
444
|
highWaterMarkBytes_(highWaterMarkBytes) {}
|
|
449
445
|
|
|
450
446
|
void Seek(const rocksdb::Slice& target) override {
|
|
@@ -454,8 +450,6 @@ struct Iterator final : public BaseIterator {
|
|
|
454
450
|
|
|
455
451
|
const bool keys_;
|
|
456
452
|
const bool values_;
|
|
457
|
-
const Encoding keyEncoding_;
|
|
458
|
-
const Encoding valueEncoding_;
|
|
459
453
|
const size_t highWaterMarkBytes_;
|
|
460
454
|
bool first_ = true;
|
|
461
455
|
};
|
|
@@ -957,8 +951,8 @@ NAPI_METHOD(db_get_many) {
|
|
|
957
951
|
Database* database;
|
|
958
952
|
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
959
953
|
|
|
960
|
-
uint32_t
|
|
961
|
-
NAPI_STATUS_THROWS(napi_get_array_length(env, argv[1], &
|
|
954
|
+
uint32_t count;
|
|
955
|
+
NAPI_STATUS_THROWS(napi_get_array_length(env, argv[1], &count));
|
|
962
956
|
|
|
963
957
|
const auto options = argv[2];
|
|
964
958
|
|
|
@@ -968,9 +962,6 @@ NAPI_METHOD(db_get_many) {
|
|
|
968
962
|
bool ignoreRangeDeletions = false;
|
|
969
963
|
NAPI_STATUS_THROWS(GetProperty(env, options, "ignoreRangeDeletions", ignoreRangeDeletions));
|
|
970
964
|
|
|
971
|
-
Encoding valueEncoding = Encoding::String;
|
|
972
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "valueEncoding", valueEncoding));
|
|
973
|
-
|
|
974
965
|
rocksdb::ColumnFamilyHandle* column = database->db->DefaultColumnFamily();
|
|
975
966
|
NAPI_STATUS_THROWS(GetProperty(env, options, "column", column));
|
|
976
967
|
|
|
@@ -984,18 +975,17 @@ NAPI_METHOD(db_get_many) {
|
|
|
984
975
|
snapshot.reset(database->db->GetSnapshot(), [=](const auto ptr) { database->db->ReleaseSnapshot(ptr); });
|
|
985
976
|
}
|
|
986
977
|
|
|
987
|
-
std::vector<rocksdb::PinnableSlice> keys{
|
|
978
|
+
std::vector<rocksdb::PinnableSlice> keys{count};
|
|
988
979
|
|
|
989
|
-
for (uint32_t n = 0; n <
|
|
980
|
+
for (uint32_t n = 0; n < count; n++) {
|
|
990
981
|
napi_value element;
|
|
991
982
|
NAPI_STATUS_THROWS(napi_get_element(env, argv[1], n, &element));
|
|
992
983
|
NAPI_STATUS_THROWS(GetValue(env, element, keys[n]));
|
|
993
984
|
}
|
|
994
985
|
|
|
995
986
|
struct State {
|
|
996
|
-
std::vector<
|
|
997
|
-
std::vector<
|
|
998
|
-
std::vector<rocksdb::Slice> keys;
|
|
987
|
+
std::vector<uint8_t> data;
|
|
988
|
+
std::vector<int32_t> sizes;
|
|
999
989
|
};
|
|
1000
990
|
|
|
1001
991
|
runAsync<State>(
|
|
@@ -1008,41 +998,61 @@ NAPI_METHOD(db_get_many) {
|
|
|
1008
998
|
readOptions.ignore_range_deletions = ignoreRangeDeletions;
|
|
1009
999
|
readOptions.optimize_multiget_for_io = true;
|
|
1010
1000
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1001
|
+
std::vector<rocksdb::Status> statuses{count};
|
|
1002
|
+
std::vector<rocksdb::PinnableSlice> values{count};
|
|
1003
|
+
std::vector<rocksdb::Slice> keys2{count};
|
|
1014
1004
|
|
|
1015
|
-
for (auto n = 0; n <
|
|
1016
|
-
|
|
1005
|
+
for (auto n = 0; n < count; n++) {
|
|
1006
|
+
keys2[n] = keys[n];
|
|
1017
1007
|
}
|
|
1018
1008
|
|
|
1019
|
-
database->db->MultiGet(readOptions, column,
|
|
1020
|
-
state.statuses.data());
|
|
1009
|
+
database->db->MultiGet(readOptions, column, count, keys2.data(), values.data(), statuses.data());
|
|
1021
1010
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1011
|
+
auto size = 0;
|
|
1012
|
+
for (auto n = 0; n < count; n++) {
|
|
1013
|
+
const auto valueSize = values[n].size();
|
|
1014
|
+
size += valueSize & 0x7 ? (valueSize | 0x7) + 1 : valueSize;
|
|
1015
|
+
}
|
|
1026
1016
|
|
|
1027
|
-
|
|
1017
|
+
state.data.reserve(size);
|
|
1028
1018
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1019
|
+
auto push = [&](rocksdb::Slice* slice){
|
|
1020
|
+
if (slice) {
|
|
1021
|
+
state.sizes.push_back(static_cast<int32_t>(slice->size()));
|
|
1022
|
+
std::copy_n(slice->data(), slice->size(), std::back_inserter(state.data));
|
|
1032
1023
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1024
|
+
if (state.data.size() & 0x7) {
|
|
1025
|
+
state.data.resize((state.data.size() | 0x7) + 1);
|
|
1026
|
+
}
|
|
1036
1027
|
} else {
|
|
1037
|
-
|
|
1038
|
-
NAPI_STATUS_RETURN(Convert(env, &value, valueEncoding, element));
|
|
1028
|
+
state.sizes.push_back(-1);
|
|
1039
1029
|
}
|
|
1040
|
-
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
for (auto n = 0; n < count; n++) {
|
|
1033
|
+
push(statuses[n].ok() ? &values[n] : nullptr);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
return rocksdb::Status::OK();
|
|
1037
|
+
},
|
|
1038
|
+
[=](auto& state, auto env, auto& argv) {
|
|
1039
|
+
argv.resize(3);
|
|
1040
|
+
|
|
1041
|
+
if (state.sizes.size() > 0) {
|
|
1042
|
+
auto sizes = std::make_unique<std::vector<int32_t>>(std::move(state.sizes));
|
|
1043
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, sizes->size() * 4, sizes->data(), Finalize<std::vector<int32_t>>, sizes.get(), &argv[1]));
|
|
1044
|
+
sizes.release();
|
|
1045
|
+
} else {
|
|
1046
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[1]));
|
|
1041
1047
|
}
|
|
1042
1048
|
|
|
1043
|
-
state.
|
|
1044
|
-
|
|
1045
|
-
|
|
1049
|
+
if (state.data.size() > 0) {
|
|
1050
|
+
auto data = std::make_unique<std::vector<uint8_t>>(std::move(state.data));
|
|
1051
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, data->size(), data->data(), Finalize<std::vector<uint8_t>>, data.get(), &argv[2]));
|
|
1052
|
+
data.release();
|
|
1053
|
+
} else {
|
|
1054
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[2]));
|
|
1055
|
+
}
|
|
1046
1056
|
|
|
1047
1057
|
return napi_ok;
|
|
1048
1058
|
});
|
|
@@ -1208,12 +1218,6 @@ NAPI_METHOD(iterator_init) {
|
|
|
1208
1218
|
bool fillCache = false;
|
|
1209
1219
|
NAPI_STATUS_THROWS(GetProperty(env, options, "fillCache", fillCache));
|
|
1210
1220
|
|
|
1211
|
-
Encoding keyEncoding = Encoding::String;
|
|
1212
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "keyEncoding", keyEncoding));
|
|
1213
|
-
|
|
1214
|
-
Encoding valueEncoding = Encoding::String;
|
|
1215
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "valueEncoding", valueEncoding));
|
|
1216
|
-
|
|
1217
1221
|
int32_t limit = -1;
|
|
1218
1222
|
NAPI_STATUS_THROWS(GetProperty(env, options, "limit", limit));
|
|
1219
1223
|
|
|
@@ -1244,7 +1248,7 @@ NAPI_METHOD(iterator_init) {
|
|
|
1244
1248
|
}
|
|
1245
1249
|
|
|
1246
1250
|
auto iterator = std::unique_ptr<Iterator>(new Iterator(database, column, reverse, keys, values, limit, lt, lte, gt,
|
|
1247
|
-
gte, fillCache,
|
|
1251
|
+
gte, fillCache, highWaterMarkBytes,
|
|
1248
1252
|
snapshot, tailing));
|
|
1249
1253
|
|
|
1250
1254
|
napi_value result;
|
|
@@ -1285,13 +1289,14 @@ NAPI_METHOD(iterator_nextv) {
|
|
|
1285
1289
|
Iterator* iterator;
|
|
1286
1290
|
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
|
|
1287
1291
|
|
|
1288
|
-
uint32_t
|
|
1289
|
-
NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &
|
|
1292
|
+
uint32_t count;
|
|
1293
|
+
NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &count));
|
|
1290
1294
|
|
|
1291
1295
|
auto callback = argv[2];
|
|
1292
1296
|
|
|
1293
1297
|
struct State {
|
|
1294
|
-
std::vector<
|
|
1298
|
+
std::vector<uint8_t> data;
|
|
1299
|
+
std::vector<int32_t> sizes;
|
|
1295
1300
|
bool finished = false;
|
|
1296
1301
|
};
|
|
1297
1302
|
|
|
@@ -1302,61 +1307,80 @@ NAPI_METHOD(iterator_nextv) {
|
|
|
1302
1307
|
iterator->SeekToRange();
|
|
1303
1308
|
}
|
|
1304
1309
|
|
|
1305
|
-
state.
|
|
1306
|
-
|
|
1310
|
+
state.sizes.reserve(count * 2);
|
|
1311
|
+
state.data.reserve(iterator->highWaterMarkBytes_);
|
|
1312
|
+
|
|
1313
|
+
auto bytesRead = 0;
|
|
1314
|
+
|
|
1315
|
+
auto push = [&](const std::optional<rocksdb::Slice>& slice){
|
|
1316
|
+
if (slice) {
|
|
1317
|
+
state.sizes.push_back(static_cast<int32_t>(slice->size()));
|
|
1318
|
+
std::copy_n(slice->data(), slice->size(), std::back_inserter(state.data));
|
|
1307
1319
|
|
|
1320
|
+
if (state.data.size() & 0x7) {
|
|
1321
|
+
state.data.resize((state.data.size() | 0x7) + 1);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
bytesRead += slice->size();
|
|
1325
|
+
} else {
|
|
1326
|
+
state.sizes.push_back(-1);
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
auto status = rocksdb::Status::OK();
|
|
1308
1331
|
while (true) {
|
|
1309
|
-
if (!iterator->first_)
|
|
1332
|
+
if (!iterator->first_) {
|
|
1310
1333
|
iterator->Next();
|
|
1311
|
-
else
|
|
1334
|
+
} else {
|
|
1312
1335
|
iterator->first_ = false;
|
|
1336
|
+
}
|
|
1313
1337
|
|
|
1314
|
-
if (!iterator->Valid() || !iterator->Increment())
|
|
1338
|
+
if (!iterator->Valid() || !iterator->Increment()) {
|
|
1339
|
+
status = iterator->Status();
|
|
1340
|
+
state.finished = true;
|
|
1315
1341
|
break;
|
|
1316
|
-
|
|
1317
|
-
auto k = rocksdb::PinnableSlice();
|
|
1318
|
-
auto v = rocksdb::PinnableSlice();
|
|
1342
|
+
}
|
|
1319
1343
|
|
|
1320
1344
|
if (iterator->keys_ && iterator->values_) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1345
|
+
push(iterator->CurrentKey());
|
|
1346
|
+
push(iterator->CurrentValue());
|
|
1323
1347
|
} else if (iterator->keys_) {
|
|
1324
|
-
|
|
1348
|
+
push(iterator->CurrentKey());
|
|
1349
|
+
push(std::nullopt);
|
|
1325
1350
|
} else if (iterator->values_) {
|
|
1326
|
-
|
|
1351
|
+
push(std::nullopt);
|
|
1352
|
+
push(iterator->CurrentValue());
|
|
1327
1353
|
}
|
|
1328
1354
|
|
|
1329
|
-
bytesRead
|
|
1330
|
-
|
|
1331
|
-
state.cache.push_back(std::move(v));
|
|
1332
|
-
|
|
1333
|
-
if (bytesRead > iterator->highWaterMarkBytes_ || state.cache.size() / 2 >= size) {
|
|
1355
|
+
if (bytesRead > iterator->highWaterMarkBytes_ || state.sizes.size() / 2 >= count) {
|
|
1356
|
+
status = rocksdb::Status::OK();
|
|
1334
1357
|
state.finished = false;
|
|
1335
|
-
|
|
1358
|
+
break;
|
|
1336
1359
|
}
|
|
1337
1360
|
}
|
|
1338
1361
|
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
return iterator->Status();
|
|
1362
|
+
return status;
|
|
1342
1363
|
},
|
|
1343
1364
|
[=](auto& state, auto env, auto& argv) {
|
|
1344
|
-
argv.resize(
|
|
1345
|
-
|
|
1346
|
-
NAPI_STATUS_RETURN(napi_create_array_with_length(env, state.cache.size(), &argv[1]));
|
|
1347
|
-
|
|
1348
|
-
for (size_t n = 0; n < state.cache.size(); n += 2) {
|
|
1349
|
-
napi_value key;
|
|
1350
|
-
napi_value val;
|
|
1365
|
+
argv.resize(4);
|
|
1351
1366
|
|
|
1352
|
-
|
|
1353
|
-
|
|
1367
|
+
if (state.sizes.size() > 0) {
|
|
1368
|
+
auto sizes = std::make_unique<std::vector<int32_t>>(std::move(state.sizes));
|
|
1369
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, sizes->size() * 4, sizes->data(), Finalize<std::vector<int32_t>>, sizes.get(), &argv[1]));
|
|
1370
|
+
sizes.release();
|
|
1371
|
+
} else {
|
|
1372
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[1]));
|
|
1373
|
+
}
|
|
1354
1374
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1375
|
+
if (state.data.size() > 0) {
|
|
1376
|
+
auto data = std::make_unique<std::vector<uint8_t>>(std::move(state.data));
|
|
1377
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, data->size(), data->data(), Finalize<std::vector<uint8_t>>, data.get(), &argv[2]));
|
|
1378
|
+
data.release();
|
|
1379
|
+
} else {
|
|
1380
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[2]));
|
|
1357
1381
|
}
|
|
1358
1382
|
|
|
1359
|
-
NAPI_STATUS_RETURN(napi_get_boolean(env, state.finished, &argv[
|
|
1383
|
+
NAPI_STATUS_RETURN(napi_get_boolean(env, state.finished, &argv[3]));
|
|
1360
1384
|
|
|
1361
1385
|
return napi_ok;
|
|
1362
1386
|
});
|
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const { ChainedBatch } = require('./chained-batch')
|
|
|
8
8
|
const { Iterator } = require('./iterator')
|
|
9
9
|
const fs = require('node:fs')
|
|
10
10
|
const assert = require('node:assert')
|
|
11
|
+
const { handleNextv } = require('./util')
|
|
11
12
|
|
|
12
13
|
const kContext = Symbol('context')
|
|
13
14
|
const kColumns = Symbol('columns')
|
|
@@ -148,16 +149,37 @@ class RocksLevel extends AbstractLevel {
|
|
|
148
149
|
_getMany (keys, options, callback) {
|
|
149
150
|
callback = fromCallback(callback, kPromise)
|
|
150
151
|
|
|
151
|
-
const {
|
|
152
|
-
|
|
153
|
-
if (keyEncoding !== 'buffer') {
|
|
154
|
-
keys = keys.map(key => typeof key === 'string' ? Buffer.from(key) : key)
|
|
155
|
-
}
|
|
156
|
-
|
|
152
|
+
const { valueEncoding } = options ?? EMPTY
|
|
157
153
|
try {
|
|
158
154
|
this[kRef]()
|
|
159
|
-
binding.db_get_many(this[kContext], keys, options ?? EMPTY, (err,
|
|
160
|
-
|
|
155
|
+
binding.db_get_many(this[kContext], keys, options ?? EMPTY, (err, sizes, data) => {
|
|
156
|
+
if (err) {
|
|
157
|
+
callback(err)
|
|
158
|
+
} else {
|
|
159
|
+
data ??= Buffer.alloc(0)
|
|
160
|
+
sizes ??= Buffer.alloc(0)
|
|
161
|
+
const val = []
|
|
162
|
+
let offset = 0
|
|
163
|
+
const sizes32 = new Int32Array(sizes.buffer, sizes.byteOffset, sizes.byteLength / 4)
|
|
164
|
+
for (const size of sizes32) {
|
|
165
|
+
if (size < 0) {
|
|
166
|
+
val.push(undefined)
|
|
167
|
+
} else {
|
|
168
|
+
if (!valueEncoding || valueEncoding === 'buffer') {
|
|
169
|
+
val.push(data.subarray(offset, offset + size))
|
|
170
|
+
} else if (valueEncoding === 'slice') {
|
|
171
|
+
val.push({ buffer: data, byteOffset: offset, byteLength: size })
|
|
172
|
+
} else {
|
|
173
|
+
val.push(data.toString(valueEncoding, offset, offset + size))
|
|
174
|
+
}
|
|
175
|
+
offset += size
|
|
176
|
+
if (offset & 0x7) {
|
|
177
|
+
offset = (offset | 0x7) + 1
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
callback(null, val)
|
|
182
|
+
}
|
|
161
183
|
this[kUnref]()
|
|
162
184
|
})
|
|
163
185
|
} catch (err) {
|
|
@@ -217,14 +239,10 @@ class RocksLevel extends AbstractLevel {
|
|
|
217
239
|
return new ChainedBatch(this, this[kContext], (batch, context, options, callback) => {
|
|
218
240
|
try {
|
|
219
241
|
this[kRef]()
|
|
220
|
-
|
|
242
|
+
binding.batch_write(this[kContext], context, options, (err) => {
|
|
221
243
|
this[kUnref]()
|
|
222
244
|
callback(err)
|
|
223
245
|
})
|
|
224
|
-
if (sync) {
|
|
225
|
-
this[kUnref]()
|
|
226
|
-
process.nextTick(callback, null)
|
|
227
|
-
}
|
|
228
246
|
} catch (err) {
|
|
229
247
|
process.nextTick(callback, err)
|
|
230
248
|
}
|
|
@@ -244,7 +262,7 @@ class RocksLevel extends AbstractLevel {
|
|
|
244
262
|
assert(false)
|
|
245
263
|
}
|
|
246
264
|
}
|
|
247
|
-
batch.
|
|
265
|
+
batch._write(options, callback)
|
|
248
266
|
|
|
249
267
|
return callback[kPromise]
|
|
250
268
|
}
|
|
@@ -282,15 +300,17 @@ class RocksLevel extends AbstractLevel {
|
|
|
282
300
|
const context = binding.iterator_init(this[kContext], options ?? {})
|
|
283
301
|
try {
|
|
284
302
|
this[kRef]()
|
|
285
|
-
return await new Promise((resolve, reject) => binding.iterator_nextv(context, options.limit, (err,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
303
|
+
return await new Promise((resolve, reject) => binding.iterator_nextv(context, options.limit, (err, sizes, buffer, finished) => {
|
|
304
|
+
handleNextv(err, sizes, buffer, finished, options, (err, rows, finished) => {
|
|
305
|
+
if (err) {
|
|
306
|
+
reject(err)
|
|
307
|
+
} else {
|
|
308
|
+
resolve({
|
|
309
|
+
rows,
|
|
310
|
+
finished
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
})
|
|
294
314
|
}))
|
|
295
315
|
} finally {
|
|
296
316
|
binding.iterator_close(context)
|
package/iterator.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { fromCallback } = require('catering')
|
|
4
4
|
const { AbstractIterator } = require('abstract-level')
|
|
5
|
+
const { handleNextv } = require('./util')
|
|
5
6
|
|
|
6
7
|
const binding = require('./binding')
|
|
7
8
|
|
|
@@ -14,6 +15,7 @@ const kPosition = Symbol('position')
|
|
|
14
15
|
const kHandleNext = Symbol('handleNext')
|
|
15
16
|
const kHandleNextv = Symbol('handleNextv')
|
|
16
17
|
const kCallback = Symbol('callback')
|
|
18
|
+
const kOptions = Symbol('options')
|
|
17
19
|
const empty = []
|
|
18
20
|
|
|
19
21
|
const registry = new FinalizationRegistry((context) => {
|
|
@@ -27,6 +29,7 @@ class Iterator extends AbstractIterator {
|
|
|
27
29
|
this[kContext] = binding.iterator_init(context, options)
|
|
28
30
|
registry.register(this, this[kContext], this[kContext])
|
|
29
31
|
|
|
32
|
+
this[kOptions] = { ...options }
|
|
30
33
|
this[kHandleNext] = this[kHandleNext].bind(this)
|
|
31
34
|
this[kHandleNextv] = this[kHandleNextv].bind(this)
|
|
32
35
|
this[kCallback] = null
|
|
@@ -73,15 +76,19 @@ class Iterator extends AbstractIterator {
|
|
|
73
76
|
return this
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
[kHandleNext] (err,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
[kHandleNext] (err, sizes, buffer, finished) {
|
|
80
|
+
handleNextv(err, sizes, buffer, finished, this[kOptions], (err, items, finished) => {
|
|
81
|
+
const callback = this[kCallback]
|
|
82
|
+
if (err) {
|
|
83
|
+
return callback(err)
|
|
84
|
+
}
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
this[kCache] = items
|
|
87
|
+
this[kFinished] = finished
|
|
88
|
+
this[kPosition] = 0
|
|
83
89
|
|
|
84
|
-
|
|
90
|
+
this._next(callback)
|
|
91
|
+
})
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
_nextv (size, options, callback) {
|
|
@@ -98,17 +105,22 @@ class Iterator extends AbstractIterator {
|
|
|
98
105
|
return callback[kPromise]
|
|
99
106
|
}
|
|
100
107
|
|
|
101
|
-
[kHandleNextv] (err,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
[kHandleNextv] (err, sizes, buffer, finished) {
|
|
109
|
+
handleNextv(err, sizes, buffer, finished, this[kOptions], (err, items, finished) => {
|
|
110
|
+
const callback = this[kCallback]
|
|
111
|
+
if (err) {
|
|
112
|
+
return callback(err)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this[kFinished] = finished
|
|
105
116
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
const entries = []
|
|
118
|
+
for (let n = 0; n < items.length; n += 2) {
|
|
119
|
+
entries.push([items[n + 0], items[n + 1]])
|
|
120
|
+
}
|
|
110
121
|
|
|
111
|
-
|
|
122
|
+
callback(null, entries)
|
|
123
|
+
})
|
|
112
124
|
}
|
|
113
125
|
|
|
114
126
|
_close (callback) {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
package/util.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function handleNextv (err, sizes, buffer, finished, options, callback) {
|
|
4
|
+
if (err) {
|
|
5
|
+
callback(err)
|
|
6
|
+
} else {
|
|
7
|
+
buffer ??= Buffer.alloc(0)
|
|
8
|
+
sizes ??= Buffer.alloc(0)
|
|
9
|
+
|
|
10
|
+
const { keyEncoding, valueEncoding } = options ?? {}
|
|
11
|
+
|
|
12
|
+
const rows = []
|
|
13
|
+
let offset = 0
|
|
14
|
+
const sizes32 = new Int32Array(sizes.buffer, sizes.byteOffset, sizes.byteLength / 4)
|
|
15
|
+
for (let n = 0; n < sizes32.length; n++) {
|
|
16
|
+
const size = sizes32[n]
|
|
17
|
+
const encoding = n & 1 ? valueEncoding : keyEncoding
|
|
18
|
+
if (size < 0) {
|
|
19
|
+
rows.push(undefined)
|
|
20
|
+
} else {
|
|
21
|
+
if (!encoding || encoding === 'buffer') {
|
|
22
|
+
rows.push(buffer.subarray(offset, offset + size))
|
|
23
|
+
} else if (encoding === 'slice') {
|
|
24
|
+
rows.push({ buffer, byteOffset: offset, byteLength: size })
|
|
25
|
+
} else {
|
|
26
|
+
rows.push(buffer.toString(encoding, offset, offset + size))
|
|
27
|
+
}
|
|
28
|
+
offset += size
|
|
29
|
+
if (offset & 0x7) {
|
|
30
|
+
offset = (offset | 0x7) + 1
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
callback(null, rows, finished)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.handleNextv = handleNextv
|