Created
August 8, 2017 22:40
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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