Skip to content

Commit

Permalink
support binary keys and values
Browse files Browse the repository at this point in the history
Binary keys are not natively supported in IndexedDB (only proposed
for IndexedDB Second Edition). If keyEncoding is binary than keys
are converted to an Array. Binary values are natively supported via
Uint8Array that are automatically converted to Buffers.
  • Loading branch information
Tim Kuijsten committed Feb 15, 2016
1 parent a7a018a commit 2a69f86
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
29 changes: 28 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ Level.prototype._open = function(options, callback) {
}

Level.prototype._get = function(key, options, callback) {
options = xtend(this._idbOpts, options)

var origKey = key

// support binary keys for any iterable type via array (ArrayBuffers as keys are only supported in IndexedDB Second Edition)
if (options.keyEncoding === 'binary' && !Array.isArray(key)) key = Array.prototype.slice.call(key)

var tx = this._db.transaction(this._idbOpts.storeName)
var req = tx.objectStore(this._idbOpts.storeName).openCursor(IDBKeyRange.only(key))

Expand All @@ -92,6 +99,11 @@ Level.prototype._get = function(key, options, callback) {
var cursor = req.result
if (cursor) {
var value = cursor.value

// automatically convert Uint8Array values to Buffer
if (value instanceof Uint8Array) value = new Buffer(value)
if (options.valueEncoding === 'binary' && !Buffer.isBuffer(value)) value = new Buffer(value)

if (options.asBuffer && !Buffer.isBuffer(value)) {
if (value == null) value = new Buffer(0)
else if (typeof value === 'string') value = new Buffer(value) // defaults to utf8, should the encoding be utf16? (DOMString)
Expand All @@ -101,7 +113,7 @@ Level.prototype._get = function(key, options, callback) {
else if (value instanceof Uint8Array) value = new Buffer(value)
else return void callback(new TypeError('can\'t coerce `' + value.constructor.name + '` into a Buffer'))
}
return void callback(null, value, key)
return void callback(null, value, origKey)
} else {
// 'NotFound' error, consistent with LevelDOWN API
return void callback(new Error('NotFound'))
Expand All @@ -110,6 +122,11 @@ Level.prototype._get = function(key, options, callback) {
}

Level.prototype._del = function(key, options, callback) {
options = xtend(this._idbOpts, options)

// support binary keys for any iterable type via array (ArrayBuffers as keys are only supported in IndexedDB Second Edition)
if (options.keyEncoding === 'binary' && !Array.isArray(key)) key = Array.prototype.slice.call(key)

var mode = 'readwrite'
if (options.sync === true) {
mode = 'readwriteflush' // only supported in Firefox (with "dom.indexedDB.experimental" pref set to true)
Expand All @@ -127,6 +144,11 @@ Level.prototype._del = function(key, options, callback) {
}

Level.prototype._put = function(key, value, options, callback) {
options = xtend(this._idbOpts, options)

// support binary keys for any iterable type via array (ArrayBuffers as keys are only supported in IndexedDB Second Edition)
if (options.keyEncoding === 'binary' && !Array.isArray(key)) key = Array.prototype.slice.call(key)

var mode = 'readwrite'
if (options.sync === true) {
mode = 'readwriteflush' // only supported in Firefox (with "dom.indexedDB.experimental" pref set to true)
Expand Down Expand Up @@ -167,6 +189,11 @@ Level.prototype._batch = function(array, options, callback) {
}

array.forEach(function(currentOp) {
var opts = xtend(options, currentOp)

// support binary keys for any iterable type via array (ArrayBuffers as keys are only supported in IndexedDB Second Edition)
if (opts.keyEncoding === 'binary' && !Array.isArray(currentOp.key)) currentOp.key = Array.prototype.slice.call(currentOp.key)

if (currentOp.type === 'del') {
store.delete(currentOp.key)
} else {
Expand Down
14 changes: 14 additions & 0 deletions iterator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var util = require('util')
var AbstractIterator = require('abstract-leveldown').AbstractIterator
var ltgt = require('ltgt')
var xtend = require('xtend')

module.exports = Iterator

Expand Down Expand Up @@ -52,6 +53,14 @@ Iterator.prototype._startCursor = function(options) {

var direction = options.reverse ? 'prev': 'next'

options = xtend(this._idbOpts, options)

// support binary keys for any iterable type via array (ArrayBuffers as keys are only supported in IndexedDB Second Edition)
if (lower)
if (options.keyEncoding === 'binary' && !Array.isArray(lower)) lower = Array.prototype.slice.call(lower)
if (upper)
if (options.keyEncoding === 'binary' && !Array.isArray(upper)) upper = Array.prototype.slice.call(upper)

// if this is not the first iteration, use lastIteratedKey
if (this._lastIteratedKey) {
if (direction === 'next') {
Expand Down Expand Up @@ -108,6 +117,11 @@ Iterator.prototype._startCursor = function(options) {

self._lastIteratedKey = key

// automatically convert Uint8Array values to Buffer
if (value instanceof Uint8Array) value = new Buffer(value)
if (options.keyEncoding === 'binary' && Array.isArray(key)) key = new Buffer(key)
if (options.valueEncoding === 'binary' && !Buffer.isBuffer(value)) value = new Buffer(value)

if (options.keyAsBuffer && !Buffer.isBuffer(key)) {
if (key == null) key = new Buffer(0)
else if (typeof key === 'string') key = new Buffer(key) // defaults to utf8, should the encoding be utf16? (DOMString)
Expand Down

0 comments on commit 2a69f86

Please sign in to comment.