Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@creationix
Created August 8, 2017 22:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save creationix/c415b7583f4a71237fd216517960939c to your computer and use it in GitHub Desktop.
Save creationix/c415b7583f4a71237fd216517960939c to your computer and use it in GitHub Desktop.
A simple abstract-random-access implementation using indexed DB that takes advantage of hypercore's behavior or consistent boundaries/offsets.
/* eslint-env browser */
var Buffer = require('buffer').Buffer
var name = 'dat'
function withStore (type, block, callback) {
var req = indexedDB.open(name + '-db', 1)
req.onerror = () => callback(req.error)
req.onupgradeneeded = () => req.result.createObjectStore(name)
req.onsuccess = () => {
var tx = req.result.transaction(name, type)
tx.oncomplete = () => callback()
tx.onerror = () => callback(tx.error)
block(tx.objectStore(name))
}
}
function get (key, callback) {
var req
return withStore('readonly', function (store) {
req = store.get(key)
}, function (err) {
if (err) return callback(err)
return callback(null, req.result)
})
}
function set (key, value, callback) {
return withStore('readwrite', function (store) {
store.put(value, key)
}, callback)
}
exports.storage = function storage (filename) {
var size
return { read, write, open, close, end, unlink }
function key (start) {
return `${filename}[${start}]`
}
function getSize (callback) {
if (size !== undefined) return callback()
return get(filename, function (err, newSize) {
if (err) return callback(err)
size = newSize
if (size === undefined) {
return callback(new Error('No such file: ' + filename))
}
return callback()
})
}
function setSize (val, callback) {
if (val <= size) return callback()
size = val
return set(filename, size, callback)
}
function read (start, length, callback) {
// console.log('read', filename, start, length)
return getSize(onSize)
function onSize (err) {
if (err) return callback(err)
if (end > size) {
return callback(new Error('Read Range error'))
}
return get(key(start), onData)
}
function onData (err, array) {
if (err) return callback(err)
if (!array) {
return callback(new Error('read invalid range'))
}
if (length !== array.length) {
return callback(new Error('Length mismatch'))
}
return callback(null, array && Buffer(array))
}
}
function write (start, data, callback) {
// console.log('write', filename, start)
return setSize(start + data.length, onSize)
function onSize (err) {
if (err) return callback(err)
return set(key(start), data, callback)
}
}
function open (...args) {
console.error('TODO: Implement open', filename, ...args)
}
function close (...args) {
console.error('TODO: Implement close', filename, ...args)
}
function end (...args) {
console.error('TODO: Implement end', filename, ...args)
}
function unlink (...args) {
console.error('TODO: Implement unlink', filename, ...args)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment