You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
4.0 KiB

5 years ago
bytewise-core
=============
Binary serialization of arbitrarily complex structures that sort element-wise
[![build status](https://travis-ci.org/deanlandolt/bytewise-core.svg?branch=master)](https://travis-ci.org/deanlandolt/bytewise-core)
Allows efficient comparison of a variety of useful data structures in a way that respects the sort order defined by [typewise](https://github.com/deanlandolt/typewise).
This library defines a total order for well-structured keyspaces in key value stores. The ordering is a superset of the sorting algorithm defined by [IndexedDB](http://www.w3.org/TR/IndexedDB/#key-construct) and the one defined by [CouchDB](http://wiki.apache.org/couchdb/View_collation). This serialization makes it easy to take advantage of the benefits of structured indexing in systems with fast but naïve binary indexing (key/value databases).
## Order of Supported Structures
This package is a barebones kernel of [bytewise](https://github.com/deanlandolt/bytewise), containing only the structures most often used to create structured keyspaces.
This is the top level order of the various structures that may be encoded:
* `null`
* `false`
* `true`
* `Number` (numeric)
* `Date` (time-wise)
* `Buffer`, `Uint8Array` (bit-wise)
* `String` (character-wise)
* `Array` (element-wise)
* `undefined`
Structured types like `Array` may recursively contain any other supported structures.
## Usage
`encode` serializes any supported type and returns a `Buffer`, or throws if an
unsupported structure is provided.
```js
var assert = require('assert')
var bytewise = require('./')
var encode = bytewise.encode
// Numbers are stored in 9 bytes -- 1 byte for the type tag and an 8 byte float
assert.equal(encode(12345).toString('hex'), '4240c81c8000000000')
// Negative numbers are stored as positive numbers, but with a lower type tag and their bits inverted
assert.equal(encode(-12345).toString('hex'), '41bf37e37fffffffff')
// The `toString` method of `Buffer` values returned by `encode` is augmented
// to use "hex" encoding by default. This ensures bytewise encoding still
// works when bytewise keys are accidentally coerced to strings.
assert.equal(encode(-12345) + '', '41bf37e37fffffffff')
// All numbers, integer or floating point, are stored as IEEE 754 doubles
assert.equal(encode(1.2345) + '', '423ff3c083126e978d')
assert.equal(encode(-1.2345) + '', '41c00c3f7ced916872')
// Serialization does not preserve the sign bit, so 0 is indistinguishable from -0
assert.equal(encode(-0) + '', '420000000000000000')
assert.equal(encode(0) + '', '420000000000000000')
// Strings are encoded as utf8, prefixed with their type tag (0x70, or the "p" character)
assert.equal(encode('foo').toString('utf8'), 'pfoo')
assert.equal(encode('föo').toString('utf8'), 'pföo')
// Arrays are just a series of values, separated by and terminated with a null byte
assert.equal(encode([ 'foo', 'bar' ]) + '', 'a070666f6f00706261720000')
// Items in arrays are delimited by null bytes, and a final end byte marks the end of the array
assert.equal(encode([ 'foo' ]).toString('binary'), '\xa0pfoo\x00\x00')
// Complex types like arrays can be arbitrarily nested, and fixed-sized types don't require a terminating byte
assert.equal(encode([ [ 'foo', 10 ], 'bar' ]) + '', 'a0a070666f6f0042402400000000000000706261720000')
```
`decode` parses a buffer and returns the structured data.
```js
var decode = bytewise.decode
var key = 'a0a070666f6f0042402400000000000000706261720000'
// Decode takes a buffer and decodes a bytewise value
assert.deepEqual(decode(new Buffer(key, 'hex')), [ [ 'foo', 10 ], 'bar' ])
// String input can be decoded, defaulting to hex
assert.deepEqual(decode(key), [ [ 'foo', 10 ], 'bar' ])
// An alternate string encoding can be provided when initializing bytewise
// TODO
```
## Use Cases
Take a look at the [bytewise](https://github.com/deanlandolt/bytewise#use-cases) library for an idea of what kind of stuff this could be useful for.
## Issues
Issues should be reported [here](https://github.com/deanlandolt/bytewise/issues).
## License
[MIT](http://deanlandolt.mit-license.org/)