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

Drop support of key types other than string and Buffer #191

Merged
merged 3 commits into from
Aug 17, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,32 @@ Your data is discarded when the process ends or you release a reference to the s

## Data types

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.
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.

```js
const db = levelup(memdown())

db.put(12, true, (err) => {
db.put('example', 123, (err) => {
if (err) throw err

db.createReadStream({
keyAsBuffer: false,
valueAsBuffer: false
}).on('data', (entry) => {
console.log(typeof entry.key) // 'number'
console.log(typeof entry.value) // 'boolean'
console.log(typeof entry.key) // 'string'
console.log(typeof entry.value) // 'number'
})
})
```

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.
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.

```js
const encode = require('encoding-down')
const db = levelup(encode(memdown()))

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

db.createReadStream({
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

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].

## v5 (unreleased)

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.

## v4

This is an upgrade to `abstract-leveldown@6` which solves long-standing issues around serialization and type support.
Expand Down
7 changes: 4 additions & 3 deletions memdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var Buffer = require('safe-buffer').Buffer
var setImmediate = require('./immediate')
var NONE = {}

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

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

if (this.keyAsBuffer && !Buffer.isBuffer(key)) {
key = Buffer.from(String(key))
if (!this.keyAsBuffer) {
key = key.toString()
}

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

MemDOWN.prototype._serializeKey = function (key) {
return key
return Buffer.isBuffer(key) ? key : Buffer.from(String(key))
}

MemDOWN.prototype._serializeValue = function (value) {
Expand Down
29 changes: 3 additions & 26 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ test('number keys', function (t) {
t.plan(4)

var db = testCommon.factory()
var numbers = [-Infinity, 0, 2, 12, +Infinity]
var numbers = [-Infinity, 0, 12, 2, +Infinity]
var strings = numbers.map(String)
var buffers = numbers.map(stringBuffer)

db.open(noop)
Expand All @@ -379,31 +380,7 @@ test('number keys', function (t) {

concat(iterator1, function (err, entries) {
t.ifError(err, 'no iterator error')
t.same(entries.map(getKey), numbers, 'sorts naturally')
})

concat(iterator2, function (err, entries) {
t.ifError(err, 'no iterator error')
t.same(entries.map(getKey), buffers, 'buffer input is stringified')
})
})

test('date keys', function (t) {
t.plan(4)

var db = testCommon.factory()
var dates = [new Date(0), new Date(1)]
var buffers = dates.map(stringBuffer)

db.open(noop)
db.batch(dates.map(putKey), noop)

var iterator = db.iterator({ keyAsBuffer: false })
var iterator2 = db.iterator({ keyAsBuffer: true })

concat(iterator, function (err, entries) {
t.ifError(err, 'no iterator error')
t.same(entries.map(getKey), dates, 'sorts naturally')
t.same(entries.map(getKey), strings, 'sorts lexicographically')
})

concat(iterator2, function (err, entries) {
Expand Down