Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

Commit b442455

Browse files
authored
Drop support of key types other than string and Buffer (#191)
1 parent 87fcea4 commit b442455

File tree

4 files changed

+78
-29
lines changed

4 files changed

+78
-29
lines changed

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -40,31 +40,32 @@ Your data is discarded when the process ends or you release a reference to the s
4040

4141
## Data types
4242

43-
Unlike [`leveldown`], `memdown` does not stringify keys or values. This means that in addition to Buffers, you can store any JS type without the need for [`encoding-down`]. For keys for example, you could use Buffers or strings, which sort lexicographically, or numbers, even Dates, which sort naturally. The only exceptions are `null` and `undefined`. Keys and values of that type are rejected.
43+
Keys can be strings or Buffers. Any other key type will be irreversibly stringified. Unlike [`leveldown`] though, `memdown` does not stringify values. This means that in addition to Buffers, you can store any JS value without the need for [`encoding-down`]. The only exceptions are `null` and `undefined`. Keys and values of that type are rejected.
4444

4545
```js
4646
const db = levelup(memdown())
4747

48-
db.put(12, true, (err) => {
48+
db.put('example', 123, (err) => {
4949
if (err) throw err
5050

5151
db.createReadStream({
5252
keyAsBuffer: false,
5353
valueAsBuffer: false
5454
}).on('data', (entry) => {
55-
console.log(typeof entry.key) // 'number'
56-
console.log(typeof entry.value) // 'boolean'
55+
console.log(typeof entry.key) // 'string'
56+
console.log(typeof entry.value) // 'number'
5757
})
5858
})
5959
```
6060

61-
If you desire normalization for keys and values (e.g. to stringify numbers), wrap `memdown` with [`encoding-down`]. Alternatively install [`level-mem`] which conveniently bundles [`levelup`], `memdown` and [`encoding-down`]. Such an approach is also recommended if you want to achieve universal (isomorphic) behavior. For example, you could have [`leveldown`] in a backend and `memdown` in the frontend.
61+
If you desire normalization for values (e.g. to stringify numbers), wrap `memdown` with [`encoding-down`]. Alternatively install [`level-mem`] which conveniently bundles [`levelup`], `memdown` and [`encoding-down`]. Such an approach is also recommended if you want to achieve universal (isomorphic) behavior. For example, you could have [`leveldown`] in a backend and `memdown` in the frontend.
6262

6363
```js
6464
const encode = require('encoding-down')
6565
const db = levelup(encode(memdown()))
6666

67-
db.put(12, true, (err) => {
67+
// The default value encoding is utf8, which stringifies input.
68+
db.put('example', 123, (err) => {
6869
if (err) throw err
6970

7071
db.createReadStream({

UPGRADING.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the [`CHANGELOG`][changelog].
44

5+
## v5 (unreleased)
6+
7+
Support of keys other than strings and Buffers has been dropped. Internally `memdown` now stores keys as Buffers which solves a number of compatibility issues ([#186](https://github.com/Level/memdown/issues/186)). If you pass in a key that isn't a string or Buffer, it will be irreversibly stringified.
8+
59
## v4
610

711
This is an upgrade to `abstract-leveldown@6` which solves long-standing issues around serialization and type support.

memdown.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var Buffer = require('safe-buffer').Buffer
1010
var setImmediate = require('./immediate')
1111
var NONE = {}
1212

13+
// TODO (perf): replace ltgt.compare with a simpler, buffer-only comparator
1314
function gt (value) {
1415
return ltgt.compare(value, this._upperBound) > 0
1516
}
@@ -97,8 +98,8 @@ MemIterator.prototype._next = function (callback) {
9798

9899
if (!this._test(key)) return setImmediate(callback)
99100

100-
if (this.keyAsBuffer && !Buffer.isBuffer(key)) {
101-
key = Buffer.from(String(key))
101+
if (!this.keyAsBuffer) {
102+
key = key.toString()
102103
}
103104

104105
if (this.valueAsBuffer && !Buffer.isBuffer(value)) {
@@ -167,7 +168,7 @@ MemDOWN.prototype._open = function (options, callback) {
167168
}
168169

169170
MemDOWN.prototype._serializeKey = function (key) {
170-
return key
171+
return Buffer.isBuffer(key) ? key : Buffer.from(String(key))
171172
}
172173

173174
MemDOWN.prototype._serializeValue = function (value) {

test.js

+63-20
Original file line numberDiff line numberDiff line change
@@ -364,46 +364,89 @@ test('put multiple times', function (t) {
364364
})
365365
})
366366

367-
test('number keys', function (t) {
367+
test('put key as string, get as buffer and vice versa', function (t) {
368+
t.plan(7)
369+
370+
var db = testCommon.factory()
371+
372+
db.open(function (err) {
373+
t.ifError(err, 'no error from open')
374+
375+
db.put('a', 'a', function (err) {
376+
t.ifError(err, 'no put error')
377+
378+
db.get(Buffer.from('a'), { asBuffer: false }, function (err, value) {
379+
t.ifError(err, 'no get error')
380+
t.is(value, 'a', 'got value')
381+
})
382+
})
383+
384+
db.put(Buffer.from('b'), 'b', function (err) {
385+
t.ifError(err, 'no put error')
386+
387+
db.get('b', { asBuffer: false }, function (err, value) {
388+
t.ifError(err, 'no get error')
389+
t.is(value, 'b', 'got value')
390+
})
391+
})
392+
})
393+
})
394+
395+
test('put key as string, iterate as buffer', function (t) {
368396
t.plan(4)
369397

370398
var db = testCommon.factory()
371-
var numbers = [-Infinity, 0, 2, 12, +Infinity]
372-
var buffers = numbers.map(stringBuffer)
373399

374-
db.open(noop)
375-
db.batch(numbers.map(putKey), noop)
400+
db.open(function (err) {
401+
t.ifError(err, 'no error from open')
376402

377-
var iterator1 = db.iterator({ keyAsBuffer: false })
378-
var iterator2 = db.iterator({ keyAsBuffer: true })
403+
db.put('a', 'a', function (err) {
404+
t.ifError(err, 'no put error')
379405

380-
concat(iterator1, function (err, entries) {
381-
t.ifError(err, 'no iterator error')
382-
t.same(entries.map(getKey), numbers, 'sorts naturally')
406+
concat(db.iterator({ keyAsBuffer: true, valueAsBuffer: false }), function (err, entries) {
407+
t.ifError(err, 'no concat error')
408+
t.same(entries, [{ key: Buffer.from('a'), value: 'a' }])
409+
})
410+
})
383411
})
412+
})
384413

385-
concat(iterator2, function (err, entries) {
386-
t.ifError(err, 'no iterator error')
387-
t.same(entries.map(getKey), buffers, 'buffer input is stringified')
414+
test('put key as buffer, iterate as string', function (t) {
415+
t.plan(4)
416+
417+
var db = testCommon.factory()
418+
419+
db.open(function (err) {
420+
t.ifError(err, 'no error from open')
421+
422+
db.put(Buffer.from('a'), 'a', function (err) {
423+
t.ifError(err, 'no put error')
424+
425+
concat(db.iterator({ keyAsBuffer: false, valueAsBuffer: false }), function (err, entries) {
426+
t.ifError(err, 'no concat error')
427+
t.same(entries, [{ key: 'a', value: 'a' }])
428+
})
429+
})
388430
})
389431
})
390432

391-
test('date keys', function (t) {
433+
test('number keys', function (t) {
392434
t.plan(4)
393435

394436
var db = testCommon.factory()
395-
var dates = [new Date(0), new Date(1)]
396-
var buffers = dates.map(stringBuffer)
437+
var numbers = [-Infinity, 0, 12, 2, +Infinity]
438+
var strings = numbers.map(String)
439+
var buffers = numbers.map(stringBuffer)
397440

398441
db.open(noop)
399-
db.batch(dates.map(putKey), noop)
442+
db.batch(numbers.map(putKey), noop)
400443

401-
var iterator = db.iterator({ keyAsBuffer: false })
444+
var iterator1 = db.iterator({ keyAsBuffer: false })
402445
var iterator2 = db.iterator({ keyAsBuffer: true })
403446

404-
concat(iterator, function (err, entries) {
447+
concat(iterator1, function (err, entries) {
405448
t.ifError(err, 'no iterator error')
406-
t.same(entries.map(getKey), dates, 'sorts naturally')
449+
t.same(entries.map(getKey), strings, 'sorts lexicographically')
407450
})
408451

409452
concat(iterator2, function (err, entries) {

0 commit comments

Comments
 (0)