@nxtedition/rocksdb 10.2.0 → 10.2.2
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 +116 -76
- package/index.js +41 -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 +37 -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<std::optional<size_t>> sizes;
|
|
999
989
|
};
|
|
1000
990
|
|
|
1001
991
|
runAsync<State>(
|
|
@@ -1008,41 +998,69 @@ 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
|
-
|
|
1009
|
+
database->db->MultiGet(readOptions, column, count, keys2.data(), values.data(), statuses.data());
|
|
1010
|
+
|
|
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
|
+
}
|
|
1016
|
+
|
|
1017
|
+
state.data.reserve(size);
|
|
1018
|
+
|
|
1019
|
+
auto push = [&](rocksdb::Slice* slice){
|
|
1020
|
+
if (slice) {
|
|
1021
|
+
state.sizes.push_back(slice->size());
|
|
1022
|
+
std::copy_n(slice->data(), slice->size(), std::back_inserter(state.data));
|
|
1023
|
+
|
|
1024
|
+
if (state.data.size() & 0x7) {
|
|
1025
|
+
state.data.resize((state.data.size() | 0x7) + 1);
|
|
1026
|
+
}
|
|
1027
|
+
} else {
|
|
1028
|
+
state.sizes.push_back(std::nullopt);
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
for (auto n = 0; n < count; n++) {
|
|
1033
|
+
push(statuses[n].ok() ? &values[n] : nullptr);
|
|
1034
|
+
}
|
|
1021
1035
|
|
|
1022
1036
|
return rocksdb::Status::OK();
|
|
1023
1037
|
},
|
|
1024
1038
|
[=](auto& state, auto env, auto& argv) {
|
|
1025
|
-
argv.resize(
|
|
1039
|
+
argv.resize(3);
|
|
1026
1040
|
|
|
1027
|
-
|
|
1041
|
+
const auto count = state.sizes.size();
|
|
1028
1042
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1043
|
+
NAPI_STATUS_RETURN(napi_create_array_with_length(env, count, &argv[1]));
|
|
1044
|
+
|
|
1045
|
+
for (uint32_t idx = 0; idx < count; idx++) {
|
|
1046
|
+
const auto& maybeSize = state.sizes[idx];
|
|
1032
1047
|
|
|
1033
1048
|
napi_value element;
|
|
1034
|
-
if (
|
|
1035
|
-
NAPI_STATUS_RETURN(
|
|
1049
|
+
if (maybeSize) {
|
|
1050
|
+
NAPI_STATUS_RETURN(napi_create_uint32(env, *maybeSize, &element));
|
|
1036
1051
|
} else {
|
|
1037
|
-
|
|
1038
|
-
NAPI_STATUS_RETURN(Convert(env, &value, valueEncoding, element));
|
|
1052
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &element));
|
|
1039
1053
|
}
|
|
1040
1054
|
NAPI_STATUS_RETURN(napi_set_element(env, argv[1], idx, element));
|
|
1041
1055
|
}
|
|
1042
1056
|
|
|
1043
|
-
state.
|
|
1044
|
-
|
|
1045
|
-
|
|
1057
|
+
if (state.data.size() > 0) {
|
|
1058
|
+
auto data = std::make_unique<std::vector<uint8_t>>(std::move(state.data));
|
|
1059
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, data->size(), data->data(), Finalize<std::vector<uint8_t>>, data.get(), &argv[2]));
|
|
1060
|
+
data.release();
|
|
1061
|
+
} else {
|
|
1062
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[2]));
|
|
1063
|
+
}
|
|
1046
1064
|
|
|
1047
1065
|
return napi_ok;
|
|
1048
1066
|
});
|
|
@@ -1208,12 +1226,6 @@ NAPI_METHOD(iterator_init) {
|
|
|
1208
1226
|
bool fillCache = false;
|
|
1209
1227
|
NAPI_STATUS_THROWS(GetProperty(env, options, "fillCache", fillCache));
|
|
1210
1228
|
|
|
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
1229
|
int32_t limit = -1;
|
|
1218
1230
|
NAPI_STATUS_THROWS(GetProperty(env, options, "limit", limit));
|
|
1219
1231
|
|
|
@@ -1244,7 +1256,7 @@ NAPI_METHOD(iterator_init) {
|
|
|
1244
1256
|
}
|
|
1245
1257
|
|
|
1246
1258
|
auto iterator = std::unique_ptr<Iterator>(new Iterator(database, column, reverse, keys, values, limit, lt, lte, gt,
|
|
1247
|
-
gte, fillCache,
|
|
1259
|
+
gte, fillCache, highWaterMarkBytes,
|
|
1248
1260
|
snapshot, tailing));
|
|
1249
1261
|
|
|
1250
1262
|
napi_value result;
|
|
@@ -1285,13 +1297,14 @@ NAPI_METHOD(iterator_nextv) {
|
|
|
1285
1297
|
Iterator* iterator;
|
|
1286
1298
|
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
|
|
1287
1299
|
|
|
1288
|
-
uint32_t
|
|
1289
|
-
NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &
|
|
1300
|
+
uint32_t count;
|
|
1301
|
+
NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &count));
|
|
1290
1302
|
|
|
1291
1303
|
auto callback = argv[2];
|
|
1292
1304
|
|
|
1293
1305
|
struct State {
|
|
1294
|
-
std::vector<
|
|
1306
|
+
std::vector<uint8_t> data;
|
|
1307
|
+
std::vector<std::optional<size_t>> sizes;
|
|
1295
1308
|
bool finished = false;
|
|
1296
1309
|
};
|
|
1297
1310
|
|
|
@@ -1302,61 +1315,88 @@ NAPI_METHOD(iterator_nextv) {
|
|
|
1302
1315
|
iterator->SeekToRange();
|
|
1303
1316
|
}
|
|
1304
1317
|
|
|
1305
|
-
state.
|
|
1306
|
-
|
|
1318
|
+
state.sizes.reserve(count * 2);
|
|
1319
|
+
state.data.reserve(iterator->highWaterMarkBytes_);
|
|
1320
|
+
|
|
1321
|
+
auto bytesRead = 0;
|
|
1322
|
+
|
|
1323
|
+
auto push = [&](const std::optional<rocksdb::Slice>& slice){
|
|
1324
|
+
if (slice) {
|
|
1325
|
+
state.sizes.push_back(slice->size());
|
|
1326
|
+
std::copy_n(slice->data(), slice->size(), std::back_inserter(state.data));
|
|
1307
1327
|
|
|
1328
|
+
if (state.data.size() & 0x7) {
|
|
1329
|
+
state.data.resize((state.data.size() | 0x7) + 1);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
bytesRead += slice->size();
|
|
1333
|
+
} else {
|
|
1334
|
+
state.sizes.push_back(std::nullopt);
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1338
|
+
auto status = rocksdb::Status::OK();
|
|
1308
1339
|
while (true) {
|
|
1309
|
-
if (!iterator->first_)
|
|
1340
|
+
if (!iterator->first_) {
|
|
1310
1341
|
iterator->Next();
|
|
1311
|
-
else
|
|
1342
|
+
} else {
|
|
1312
1343
|
iterator->first_ = false;
|
|
1344
|
+
}
|
|
1313
1345
|
|
|
1314
|
-
if (!iterator->Valid() || !iterator->Increment())
|
|
1346
|
+
if (!iterator->Valid() || !iterator->Increment()) {
|
|
1347
|
+
status = iterator->Status();
|
|
1348
|
+
state.finished = true;
|
|
1315
1349
|
break;
|
|
1316
|
-
|
|
1317
|
-
auto k = rocksdb::PinnableSlice();
|
|
1318
|
-
auto v = rocksdb::PinnableSlice();
|
|
1350
|
+
}
|
|
1319
1351
|
|
|
1320
1352
|
if (iterator->keys_ && iterator->values_) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1353
|
+
push(iterator->CurrentKey());
|
|
1354
|
+
push(iterator->CurrentValue());
|
|
1323
1355
|
} else if (iterator->keys_) {
|
|
1324
|
-
|
|
1356
|
+
push(iterator->CurrentKey());
|
|
1357
|
+
push(std::nullopt);
|
|
1325
1358
|
} else if (iterator->values_) {
|
|
1326
|
-
|
|
1359
|
+
push(std::nullopt);
|
|
1360
|
+
push(iterator->CurrentValue());
|
|
1327
1361
|
}
|
|
1328
1362
|
|
|
1329
|
-
bytesRead
|
|
1330
|
-
|
|
1331
|
-
state.cache.push_back(std::move(v));
|
|
1332
|
-
|
|
1333
|
-
if (bytesRead > iterator->highWaterMarkBytes_ || state.cache.size() / 2 >= size) {
|
|
1363
|
+
if (bytesRead > iterator->highWaterMarkBytes_ || state.sizes.size() / 2 >= count) {
|
|
1364
|
+
status = rocksdb::Status::OK();
|
|
1334
1365
|
state.finished = false;
|
|
1335
|
-
|
|
1366
|
+
break;
|
|
1336
1367
|
}
|
|
1337
1368
|
}
|
|
1338
1369
|
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
return iterator->Status();
|
|
1370
|
+
return status;
|
|
1342
1371
|
},
|
|
1343
1372
|
[=](auto& state, auto env, auto& argv) {
|
|
1344
|
-
argv.resize(
|
|
1373
|
+
argv.resize(4);
|
|
1374
|
+
|
|
1375
|
+
const auto count = state.sizes.size();
|
|
1345
1376
|
|
|
1346
|
-
NAPI_STATUS_RETURN(napi_create_array_with_length(env,
|
|
1377
|
+
NAPI_STATUS_RETURN(napi_create_array_with_length(env, count, &argv[1]));
|
|
1347
1378
|
|
|
1348
|
-
for (
|
|
1349
|
-
|
|
1350
|
-
napi_value val;
|
|
1379
|
+
for (uint32_t idx = 0; idx < count; idx++) {
|
|
1380
|
+
const auto& maybeSize = state.sizes[idx];
|
|
1351
1381
|
|
|
1352
|
-
|
|
1353
|
-
|
|
1382
|
+
napi_value element;
|
|
1383
|
+
if (maybeSize) {
|
|
1384
|
+
NAPI_STATUS_RETURN(napi_create_uint32(env, *maybeSize, &element));
|
|
1385
|
+
} else {
|
|
1386
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &element));
|
|
1387
|
+
}
|
|
1388
|
+
NAPI_STATUS_RETURN(napi_set_element(env, argv[1], idx, element));
|
|
1389
|
+
}
|
|
1354
1390
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1391
|
+
if (state.data.size() > 0) {
|
|
1392
|
+
auto data = std::make_unique<std::vector<uint8_t>>(std::move(state.data));
|
|
1393
|
+
NAPI_STATUS_RETURN(napi_create_external_buffer(env, data->size(), data->data(), Finalize<std::vector<uint8_t>>, data.get(), &argv[2]));
|
|
1394
|
+
data.release();
|
|
1395
|
+
} else {
|
|
1396
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &argv[2]));
|
|
1357
1397
|
}
|
|
1358
1398
|
|
|
1359
|
-
NAPI_STATUS_RETURN(napi_get_boolean(env, state.finished, &argv[
|
|
1399
|
+
NAPI_STATUS_RETURN(napi_get_boolean(env, state.finished, &argv[3]));
|
|
1360
1400
|
|
|
1361
1401
|
return napi_ok;
|
|
1362
1402
|
});
|
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,35 @@ 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, buffer) => {
|
|
156
|
+
if (err) {
|
|
157
|
+
callback(err)
|
|
158
|
+
} else {
|
|
159
|
+
buffer ??= Buffer.alloc(0)
|
|
160
|
+
const val = []
|
|
161
|
+
let offset = 0
|
|
162
|
+
for (const size of sizes) {
|
|
163
|
+
if (size == null) {
|
|
164
|
+
val.push(undefined)
|
|
165
|
+
} else {
|
|
166
|
+
if (!valueEncoding || valueEncoding === 'buffer') {
|
|
167
|
+
val.push(buffer.subarray(offset, offset + size))
|
|
168
|
+
} else if (valueEncoding === 'slice') {
|
|
169
|
+
val.push({ buffer, byteOffset: offset, byteLength: size })
|
|
170
|
+
} else {
|
|
171
|
+
val.push(buffer.toString(valueEncoding, offset, offset + size))
|
|
172
|
+
}
|
|
173
|
+
offset += size
|
|
174
|
+
if (offset & 0x7) {
|
|
175
|
+
offset = (offset | 0x7) + 1
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
callback(null, val)
|
|
180
|
+
}
|
|
161
181
|
this[kUnref]()
|
|
162
182
|
})
|
|
163
183
|
} catch (err) {
|
|
@@ -217,14 +237,10 @@ class RocksLevel extends AbstractLevel {
|
|
|
217
237
|
return new ChainedBatch(this, this[kContext], (batch, context, options, callback) => {
|
|
218
238
|
try {
|
|
219
239
|
this[kRef]()
|
|
220
|
-
|
|
240
|
+
binding.batch_write(this[kContext], context, options, (err) => {
|
|
221
241
|
this[kUnref]()
|
|
222
242
|
callback(err)
|
|
223
243
|
})
|
|
224
|
-
if (sync) {
|
|
225
|
-
this[kUnref]()
|
|
226
|
-
process.nextTick(callback, null)
|
|
227
|
-
}
|
|
228
244
|
} catch (err) {
|
|
229
245
|
process.nextTick(callback, err)
|
|
230
246
|
}
|
|
@@ -244,7 +260,7 @@ class RocksLevel extends AbstractLevel {
|
|
|
244
260
|
assert(false)
|
|
245
261
|
}
|
|
246
262
|
}
|
|
247
|
-
batch.
|
|
263
|
+
batch._write(options, callback)
|
|
248
264
|
|
|
249
265
|
return callback[kPromise]
|
|
250
266
|
}
|
|
@@ -282,15 +298,17 @@ class RocksLevel extends AbstractLevel {
|
|
|
282
298
|
const context = binding.iterator_init(this[kContext], options ?? {})
|
|
283
299
|
try {
|
|
284
300
|
this[kRef]()
|
|
285
|
-
return await new Promise((resolve, reject) => binding.iterator_nextv(context, options.limit, (err,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
301
|
+
return await new Promise((resolve, reject) => binding.iterator_nextv(context, options.limit, (err, sizes, buffer, finished) => {
|
|
302
|
+
handleNextv(err, sizes, buffer, finished, options, (err, rows, finished) => {
|
|
303
|
+
if (err) {
|
|
304
|
+
reject(err)
|
|
305
|
+
} else {
|
|
306
|
+
resolve({
|
|
307
|
+
rows,
|
|
308
|
+
finished
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
})
|
|
294
312
|
}))
|
|
295
313
|
} finally {
|
|
296
314
|
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,37 @@
|
|
|
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
|
+
|
|
9
|
+
const { keyEncoding, valueEncoding } = options ?? {}
|
|
10
|
+
|
|
11
|
+
const rows = []
|
|
12
|
+
let offset = 0
|
|
13
|
+
for (let n = 0; n < sizes.length; n++) {
|
|
14
|
+
const size = sizes[n]
|
|
15
|
+
const encoding = n & 1 ? valueEncoding : keyEncoding
|
|
16
|
+
if (size == null) {
|
|
17
|
+
rows.push(undefined)
|
|
18
|
+
} else {
|
|
19
|
+
if (!encoding || encoding === 'buffer') {
|
|
20
|
+
rows.push(buffer.subarray(offset, offset + size))
|
|
21
|
+
} else if (encoding === 'slice') {
|
|
22
|
+
rows.push({ buffer, byteOffset: offset, byteLength: size })
|
|
23
|
+
} else {
|
|
24
|
+
rows.push(buffer.toString(encoding, offset, offset + size))
|
|
25
|
+
}
|
|
26
|
+
offset += size
|
|
27
|
+
if (offset & 0x7) {
|
|
28
|
+
offset = (offset | 0x7) + 1
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
callback(null, rows, finished)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports.handleNextv = handleNextv
|