[Pkg-javascript-commits] [node-binary] 01/03: Imported Upstream version 0.3.0

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sun Mar 1 22:07:03 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository node-binary.

commit 9b3bc2e49871a316cfa2e00c88886617b88932d8
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sun Mar 1 20:19:45 2015 +0100

    Imported Upstream version 0.3.0
---
 .gitignore               |   2 +
 .travis.yml              |   4 +
 README.markdown          | 177 +++++++++++++++++++++
 example/buf.js           |  11 ++
 example/parse.js         |  10 ++
 example/stream.js        |  12 ++
 index.js                 | 397 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/vars.js              |  28 ++++
 package.json             |  38 +++++
 perf/loop.js             |  92 +++++++++++
 perf/small.js            |  80 ++++++++++
 test/bu.js               |  46 ++++++
 test/deferred.js         |  20 +++
 test/dots.js             |  23 +++
 test/eof.js              |  41 +++++
 test/flush.js            |  17 ++
 test/from_buffer.js      |  14 ++
 test/get_buffer.js       |  28 ++++
 test/immediate.js        |  18 +++
 test/interval.js         |  38 +++++
 test/into_buffer.js      |  35 +++++
 test/into_stream.js      |  43 +++++
 test/loop.js             |  44 ++++++
 test/loop_scan.js        |  54 +++++++
 test/lu.js               |  46 ++++++
 test/negbs.js            |  29 ++++
 test/negls.js            |  29 ++++
 test/nested.js           |  35 +++++
 test/not_enough_buf.js   |  17 ++
 test/not_enough_parse.js |  19 +++
 test/parse.js            |  54 +++++++
 test/peek.js             |  40 +++++
 test/pipe.js             |  49 ++++++
 test/posbs.js            |  29 ++++
 test/posls.js            |  29 ++++
 test/scan.js             |  33 ++++
 test/scan_buf.js         |  18 +++
 test/scan_buf_null.js    |  16 ++
 test/skip.js             |  58 +++++++
 test/split.js            |  34 ++++
 40 files changed, 1807 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..93f1361
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..f1d0f13
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.4
+  - 0.6
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..bbeac2e
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,177 @@
+binary
+======
+
+Unpack multibyte binary values from buffers and streams.
+You can specify the endianness and signedness of the fields to be unpacked too.
+
+This module is a cleaner and more complete version of
+[bufferlist](https://github.com/substack/node-bufferlist)'s binary module that
+runs on pre-allocated buffers instead of a linked list.
+
+[![build status](https://secure.travis-ci.org/substack/node-binary.png)](http://travis-ci.org/substack/node-binary)
+
+examples
+========
+
+stream.js
+---------
+
+``` js
+var binary = require('binary');
+
+var ws = binary()
+    .word32lu('x')
+    .word16bs('y')
+    .word16bu('z')
+    .tap(function (vars) {
+        console.dir(vars);
+    })
+;
+process.stdin.pipe(ws);
+process.stdin.resume();
+```
+
+output:
+
+```
+$ node examples/stream.js
+abcdefgh
+{ x: 1684234849, y: 25958, z: 26472 }
+^D
+```
+
+parse.js
+--------
+
+``` js
+var buf = new Buffer([ 97, 98, 99, 100, 101, 102, 0 ]);
+
+var binary = require('binary');
+var vars = binary.parse(buf)
+    .word16ls('ab')
+    .word32bu('cf')
+    .word8('x')
+    .vars
+;
+console.dir(vars);
+```
+
+output:
+
+```
+{ ab: 25185, cf: 1667523942, x: 0 }
+```
+
+methods
+=======
+
+`var binary = require('binary')`
+
+var b = binary()
+----------------
+
+Return a new writable stream `b` that has the chainable methods documented below
+for buffering binary input.
+
+binary.parse(buf)
+-----------------
+
+Parse a static buffer in one pass. Returns a chainable interface with the
+methods below plus a `vars` field to get at the variable stash as the last item
+in a chain.
+
+In parse mode, methods will set their keys to `null` if the buffer isn't big
+enough except `buffer()` and `scan()` which read up up to the end of the buffer
+and stop.
+
+b.word{8,16,32,64}{l,b}{e,u,s}(key)
+-----------------------------------
+
+Parse bytes in the buffer or stream given:
+
+* number of bits
+* endianness ( l : little, b : big ),
+* signedness ( u and e : unsigned, s : signed )
+
+These functions won't start parsing until all previous parser functions have run
+and the data is available.
+
+The result of the parse goes into the variable stash at `key`.
+If `key` has dots (`.`s), it refers to a nested address. If parent container
+values don't exist they will be created automatically, so for instance you can
+assign into `dst.addr` and `dst.port` and the `dst` key in the variable stash
+will be `{ addr : x, port : y }` afterwards.
+
+b.buffer(key, size)
+-------------------
+
+Take `size` bytes directly off the buffer stream, putting the resulting buffer
+slice in the variable stash at `key`. If `size` is a string, use the value at
+`vars[size]`. The key follows the same dotted address rules as the word
+functions.
+
+b.scan(key, buffer)
+-------------------
+
+Search for `buffer` in the stream and store all the intervening data in the
+stash at at `key`, excluding the search buffer. If `buffer` passed as a string,
+it will be converted into a Buffer internally.
+
+For example, to read in a line you can just do:
+
+``` js
+var b = binary()
+    .scan('line', new Buffer('\r\n'))
+    .tap(function (vars) {
+        console.log(vars.line)
+    })
+;
+stream.pipe(b);
+```
+
+b.tap(cb)
+---------
+
+The callback `cb` is provided with the variable stash from all the previous
+actions once they've all finished.
+
+You can nest additional actions onto `this` inside the callback.
+
+b.into(key, cb)
+---------------
+
+Like `.tap()`, except all nested actions will assign into a `key` in the `vars`
+stash.
+
+b.loop(cb)
+----------
+
+Loop, each time calling `cb(end, vars)` for function `end` and the variable
+stash with `this` set to a new chain for nested parsing. The loop terminates
+once `end` is called.
+
+b.flush()
+---------
+
+Clear the variable stash entirely.
+
+installation
+============
+
+To install with [npm](http://github.com/isaacs/npm):
+
+```
+npm install binary
+```
+
+notes
+=====
+
+The word64 functions will only return approximations since javascript uses ieee
+floating point for all number types. Mind the loss of precision.
+
+license
+=======
+
+MIT
+
diff --git a/example/buf.js b/example/buf.js
new file mode 100644
index 0000000..7f5d30b
--- /dev/null
+++ b/example/buf.js
@@ -0,0 +1,11 @@
+var buf = new Buffer([ 97, 98, 99, 100, 101, 102, 0 ]);
+
+var binary = require('binary');
+binary(buf)
+    .word16ls('ab')
+    .word32bu('cf')
+    .word8('x')
+    .tap(function (vars) {
+        console.dir(vars);
+    })
+;
diff --git a/example/parse.js b/example/parse.js
new file mode 100644
index 0000000..b326883
--- /dev/null
+++ b/example/parse.js
@@ -0,0 +1,10 @@
+var buf = new Buffer([ 97, 98, 99, 100, 101, 102, 0 ]);
+
+var binary = require('binary');
+var vars = binary.parse(buf)
+    .word16ls('ab')
+    .word32bu('cf')
+    .word8('x')
+    .vars
+;
+console.dir(vars);
diff --git a/example/stream.js b/example/stream.js
new file mode 100644
index 0000000..28a6f96
--- /dev/null
+++ b/example/stream.js
@@ -0,0 +1,12 @@
+var binary = require('binary');
+
+var ws = binary()
+    .word32lu('x')
+    .word16bs('y')
+    .word16bu('z')
+    .tap(function (vars) {
+        console.dir(vars);
+    })
+;
+process.stdin.pipe(ws);
+process.stdin.resume();
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..bf2ba4b
--- /dev/null
+++ b/index.js
@@ -0,0 +1,397 @@
+var Chainsaw = require('chainsaw');
+var EventEmitter = require('events').EventEmitter;
+var Buffers = require('buffers');
+var Vars = require('./lib/vars.js');
+var Stream = require('stream').Stream;
+
+exports = module.exports = function (bufOrEm, eventName) {
+    if (Buffer.isBuffer(bufOrEm)) {
+        return exports.parse(bufOrEm);
+    }
+    
+    var s = exports.stream();
+    if (bufOrEm && bufOrEm.pipe) {
+        bufOrEm.pipe(s);
+    }
+    else if (bufOrEm) {
+        bufOrEm.on(eventName || 'data', function (buf) {
+            s.write(buf);
+        });
+        
+        bufOrEm.on('end', function () {
+            s.end();
+        });
+    }
+    return s;
+};
+
+exports.stream = function (input) {
+    if (input) return exports.apply(null, arguments);
+    
+    var pending = null;
+    function getBytes (bytes, cb, skip) {
+        pending = {
+            bytes : bytes,
+            skip : skip,
+            cb : function (buf) {
+                pending = null;
+                cb(buf);
+            },
+        };
+        dispatch();
+    }
+    
+    var offset = null;
+    function dispatch () {
+        if (!pending) {
+            if (caughtEnd) done = true;
+            return;
+        }
+        if (typeof pending === 'function') {
+            pending();
+        }
+        else {
+            var bytes = offset + pending.bytes;
+            
+            if (buffers.length >= bytes) {
+                var buf;
+                if (offset == null) {
+                    buf = buffers.splice(0, bytes);
+                    if (!pending.skip) {
+                        buf = buf.slice();
+                    }
+                }
+                else {
+                    if (!pending.skip) {
+                        buf = buffers.slice(offset, bytes);
+                    }
+                    offset = bytes;
+                }
+                
+                if (pending.skip) {
+                    pending.cb();
+                }
+                else {
+                    pending.cb(buf);
+                }
+            }
+        }
+    }
+    
+    function builder (saw) {
+        function next () { if (!done) saw.next() }
+        
+        var self = words(function (bytes, cb) {
+            return function (name) {
+                getBytes(bytes, function (buf) {
+                    vars.set(name, cb(buf));
+                    next();
+                });
+            };
+        });
+        
+        self.tap = function (cb) {
+            saw.nest(cb, vars.store);
+        };
+        
+        self.into = function (key, cb) {
+            if (!vars.get(key)) vars.set(key, {});
+            var parent = vars;
+            vars = Vars(parent.get(key));
+            
+            saw.nest(function () {
+                cb.apply(this, arguments);
+                this.tap(function () {
+                    vars = parent;
+                });
+            }, vars.store);
+        };
+        
+        self.flush = function () {
+            vars.store = {};
+            next();
+        };
+        
+        self.loop = function (cb) {
+            var end = false;
+            
+            saw.nest(false, function loop () {
+                this.vars = vars.store;
+                cb.call(this, function () {
+                    end = true;
+                    next();
+                }, vars.store);
+                this.tap(function () {
+                    if (end) saw.next()
+                    else loop.call(this)
+                }.bind(this));
+            }, vars.store);
+        };
+        
+        self.buffer = function (name, bytes) {
+            if (typeof bytes === 'string') {
+                bytes = vars.get(bytes);
+            }
+            
+            getBytes(bytes, function (buf) {
+                vars.set(name, buf);
+                next();
+            });
+        };
+        
+        self.skip = function (bytes) {
+            if (typeof bytes === 'string') {
+                bytes = vars.get(bytes);
+            }
+            
+            getBytes(bytes, function () {
+                next();
+            });
+        };
+        
+        self.scan = function find (name, search) {
+            if (typeof search === 'string') {
+                search = new Buffer(search);
+            }
+            else if (!Buffer.isBuffer(search)) {
+                throw new Error('search must be a Buffer or a string');
+            }
+            
+            var taken = 0;
+            pending = function () {
+                var pos = buffers.indexOf(search, offset + taken);
+                var i = pos-offset-taken;
+                if (pos !== -1) {
+                    pending = null;
+                    if (offset != null) {
+                        vars.set(
+                            name,
+                            buffers.slice(offset, offset + taken + i)
+                        );
+                        offset += taken + i + search.length;
+                    }
+                    else {
+                        vars.set(
+                            name,
+                            buffers.slice(0, taken + i)
+                        );
+                        buffers.splice(0, taken + i + search.length);
+                    }
+                    next();
+                    dispatch();
+                } else {
+                    i = Math.max(buffers.length - search.length - offset - taken, 0);
+				}
+                taken += i;
+            };
+            dispatch();
+        };
+        
+        self.peek = function (cb) {
+            offset = 0;
+            saw.nest(function () {
+                cb.call(this, vars.store);
+                this.tap(function () {
+                    offset = null;
+                });
+            });
+        };
+        
+        return self;
+    };
+    
+    var stream = Chainsaw.light(builder);
+    stream.writable = true;
+    
+    var buffers = Buffers();
+    
+    stream.write = function (buf) {
+        buffers.push(buf);
+        dispatch();
+    };
+    
+    var vars = Vars();
+    
+    var done = false, caughtEnd = false;
+    stream.end = function () {
+        caughtEnd = true;
+    };
+    
+    stream.pipe = Stream.prototype.pipe;
+    Object.getOwnPropertyNames(EventEmitter.prototype).forEach(function (name) {
+        stream[name] = EventEmitter.prototype[name];
+    });
+    
+    return stream;
+};
+
+exports.parse = function parse (buffer) {
+    var self = words(function (bytes, cb) {
+        return function (name) {
+            if (offset + bytes <= buffer.length) {
+                var buf = buffer.slice(offset, offset + bytes);
+                offset += bytes;
+                vars.set(name, cb(buf));
+            }
+            else {
+                vars.set(name, null);
+            }
+            return self;
+        };
+    });
+    
+    var offset = 0;
+    var vars = Vars();
+    self.vars = vars.store;
+    
+    self.tap = function (cb) {
+        cb.call(self, vars.store);
+        return self;
+    };
+    
+    self.into = function (key, cb) {
+        if (!vars.get(key)) {
+            vars.set(key, {});
+        }
+        var parent = vars;
+        vars = Vars(parent.get(key));
+        cb.call(self, vars.store);
+        vars = parent;
+        return self;
+    };
+    
+    self.loop = function (cb) {
+        var end = false;
+        var ender = function () { end = true };
+        while (end === false) {
+            cb.call(self, ender, vars.store);
+        }
+        return self;
+    };
+    
+    self.buffer = function (name, size) {
+        if (typeof size === 'string') {
+            size = vars.get(size);
+        }
+        var buf = buffer.slice(offset, Math.min(buffer.length, offset + size));
+        offset += size;
+        vars.set(name, buf);
+        
+        return self;
+    };
+    
+    self.skip = function (bytes) {
+        if (typeof bytes === 'string') {
+            bytes = vars.get(bytes);
+        }
+        offset += bytes;
+        
+        return self;
+    };
+    
+    self.scan = function (name, search) {
+        if (typeof search === 'string') {
+            search = new Buffer(search);
+        }
+        else if (!Buffer.isBuffer(search)) {
+            throw new Error('search must be a Buffer or a string');
+        }
+        vars.set(name, null);
+        
+        // simple but slow string search
+        for (var i = 0; i + offset <= buffer.length - search.length + 1; i++) {
+            for (
+                var j = 0;
+                j < search.length && buffer[offset+i+j] === search[j];
+                j++
+            );
+            if (j === search.length) break;
+        }
+        
+        vars.set(name, buffer.slice(offset, offset + i));
+        offset += i + search.length;
+        return self;
+    };
+    
+    self.peek = function (cb) {
+        var was = offset;
+        cb.call(self, vars.store);
+        offset = was;
+        return self;
+    };
+    
+    self.flush = function () {
+        vars.store = {};
+        return self;
+    };
+    
+    self.eof = function () {
+        return offset >= buffer.length;
+    };
+    
+    return self;
+};
+
+// convert byte strings to unsigned little endian numbers
+function decodeLEu (bytes) {
+    var acc = 0;
+    for (var i = 0; i < bytes.length; i++) {
+        acc += Math.pow(256,i) * bytes[i];
+    }
+    return acc;
+}
+
+// convert byte strings to unsigned big endian numbers
+function decodeBEu (bytes) {
+    var acc = 0;
+    for (var i = 0; i < bytes.length; i++) {
+        acc += Math.pow(256, bytes.length - i - 1) * bytes[i];
+    }
+    return acc;
+}
+
+// convert byte strings to signed big endian numbers
+function decodeBEs (bytes) {
+    var val = decodeBEu(bytes);
+    if ((bytes[0] & 0x80) == 0x80) {
+        val -= Math.pow(256, bytes.length);
+    }
+    return val;
+}
+
+// convert byte strings to signed little endian numbers
+function decodeLEs (bytes) {
+    var val = decodeLEu(bytes);
+    if ((bytes[bytes.length - 1] & 0x80) == 0x80) {
+        val -= Math.pow(256, bytes.length);
+    }
+    return val;
+}
+
+function words (decode) {
+    var self = {};
+    
+    [ 1, 2, 4, 8 ].forEach(function (bytes) {
+        var bits = bytes * 8;
+        
+        self['word' + bits + 'le']
+        = self['word' + bits + 'lu']
+        = decode(bytes, decodeLEu);
+        
+        self['word' + bits + 'ls']
+        = decode(bytes, decodeLEs);
+        
+        self['word' + bits + 'be']
+        = self['word' + bits + 'bu']
+        = decode(bytes, decodeBEu);
+        
+        self['word' + bits + 'bs']
+        = decode(bytes, decodeBEs);
+    });
+    
+    // word8be(n) == word8le(n) for all n
+    self.word8 = self.word8u = self.word8be;
+    self.word8s = self.word8bs;
+    
+    return self;
+}
diff --git a/lib/vars.js b/lib/vars.js
new file mode 100644
index 0000000..00d6df6
--- /dev/null
+++ b/lib/vars.js
@@ -0,0 +1,28 @@
+module.exports = function (store) {
+    function getset (name, value) {
+        var node = vars.store;
+        var keys = name.split('.');
+        keys.slice(0,-1).forEach(function (k) {
+            if (node[k] === undefined) node[k] = {};
+            node = node[k]
+        });
+        var key = keys[keys.length - 1];
+        if (arguments.length == 1) {
+            return node[key];
+        }
+        else {
+            return node[key] = value;
+        }
+    }
+    
+    var vars = {
+        get : function (name) {
+            return getset(name);
+        },
+        set : function (name, value) {
+            return getset(name, value);
+        },
+        store : store || {},
+    };
+    return vars;
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c71efb4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,38 @@
+{
+    "name" : "binary",
+    "version" : "0.3.0",
+    "description" : "Unpack multibyte binary values from buffers",
+    "main" : "./index.js",
+    "repository" : {
+        "type" : "git",
+        "url" : "http://github.com/substack/node-binary.git"
+    },
+    "keywords": [
+        "binary",
+        "decode",
+        "endian",
+        "unpack",
+        "signed",
+        "unsigned"
+    ],
+    "author" : {
+        "name" : "James Halliday",
+        "email" : "mail at substack.net",
+        "url" : "http://substack.net"
+    },
+    "dependencies" : {
+        "chainsaw" : "~0.1.0",
+        "buffers" : "~0.1.1"
+    },
+    "devDependencies" : {
+        "seq" : "~0.2.5",
+        "tap" : "~0.2.4"
+    },
+    "scripts" : {
+        "test" : "tap test/*.js"
+    },
+    "license" : "MIT",
+    "engine" : {
+        "node" : ">=0.4.0"
+    }
+}
diff --git a/perf/loop.js b/perf/loop.js
new file mode 100644
index 0000000..bec60a8
--- /dev/null
+++ b/perf/loop.js
@@ -0,0 +1,92 @@
+var Seq = require('seq');
+var Hash = require('hashish');
+var EventEmitter = require('events').EventEmitter;
+
+var Bin = require('binary');
+var Buf = require('bufferlist/binary');
+var BufferList = require('bufferlist');
+
+console.log('loop');
+function emitter () {
+    var em = new EventEmitter;
+    
+    var i = 0;
+    var iv = setInterval(function () {
+        var buf = new Buffer(10000);
+        buf[0] = 0xff;
+        
+        if (++ i >= 2000) {
+            buf[0] = 0;
+            clearInterval(iv);
+        }
+        em.emit('data', buf);
+    }, 1);
+    
+    return em;
+}
+
+Seq()
+    .seq(function () {
+        var next = this.bind({}, null);
+        bufferlist(next);
+    })
+    .seq(function () {
+        var next = this.bind({}, null);
+        binary(next);
+    })
+;
+
+function binary (next) {
+    var em = emitter();
+    var t0 = Date.now();
+    
+    Bin(em)
+        .loop(function (end) {
+            this
+            .word8('x')
+            .word8('y')
+            .word32be('z')
+            .word32le('w')
+            .buffer('buf', 10000 - 10)
+            .tap(function (vars) {
+                if (vars.x === 0) {
+                    var tf = Date.now();
+                    console.log('    binary: ' + (tf - t0) + ' ms');
+                    end();
+                    setTimeout(next, 20);
+                }
+            })
+        })
+    ;
+}
+
+function bufferlist (next) {
+    var em = emitter();
+    var t0 = Date.now();
+    
+    var blist = new BufferList;
+    em.on('data', function (buf) {
+        blist.push(buf);
+    });
+    
+    Buf(blist)
+        .forever(function () {
+            var top = this;
+            this
+            .getWord8('x')
+            .getWord8('y')
+            .getWord32be('z')
+            .getWord32le('w')
+            .getBuffer('buf', 10000 - 10)
+            .tap(function (vars) {
+                if (vars.x === 0) {
+                    var tf = Date.now();
+                    console.log('    bufferlist: ' + (tf - t0) + ' ms');
+                    top.exit();
+                    setTimeout(next, 20);
+                }
+            })
+        })
+        .end()
+    ;
+}
diff --git a/perf/small.js b/perf/small.js
new file mode 100644
index 0000000..2a5ed52
--- /dev/null
+++ b/perf/small.js
@@ -0,0 +1,80 @@
+var Seq = require('seq');
+var Hash = require('hashish');
+
+var Bin = require('binary');
+var Buf = require('bufferlist/binary');
+var BufferList = require('bufferlist');
+var EventEmitter = require('events').EventEmitter;
+
+function binary (buf, cb) {
+    Bin(buf)
+        .word32le('x')
+        .word16be('y')
+        .word16be('z')
+        .word32le('w')
+        .tap(cb)
+    ;
+};
+
+function stream (buf, cb) {
+    var em = new EventEmitter;
+    Bin(em)
+        .word32le('x')
+        .word16be('y')
+        .word16be('z')
+        .word32le('w')
+        .tap(cb)
+    ;
+    em.emit('data', buf);
+};
+
+function parse (buf, cb) {
+    cb(Bin.parse(buf)
+        .word32le('x')
+        .word16be('y')
+        .word16be('z')
+        .word32le('w')
+        .vars
+    );
+};
+
+function bufferlist (buf, cb) {
+    var blist = new BufferList;
+    blist.push(buf);
+    Buf(blist)
+        .getWord32le('x')
+        .getWord16be('y')
+        .getWord16be('z')
+        .getWord32le('w')
+        .tap(cb)
+        .end()
+    ;
+};
+
+
+var buffers = [];
+for (var i = 0; i < 200; i++) {
+    buffers.push(new Buffer(12));
+}
+
+console.log('small');
+Seq(binary, stream, parse, bufferlist)
+    .seqEach(function (f) {
+        var t = this;
+        var t0 = Date.now();
+        Seq()
+            .extend(buffers)
+            .seqEach(function (buf) {
+                f(buf, this.bind(this, null));
+            })
+            .seq(function () {
+                var tf = Date.now();
+                console.log('    ' + f.name + ': ' + (tf - t0));
+                t(null);
+            })
+        ;
+    })
+    .seq(function () {
+        this(null);
+    })
+;
diff --git a/test/bu.js b/test/bu.js
new file mode 100644
index 0000000..d557e3c
--- /dev/null
+++ b/test/bu.js
@@ -0,0 +1,46 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('bu', function (t) {
+    t.plan(8);
+    
+    // note: can't store -12667700813876161 exactly in an ieee float
+    
+    var buf = new Buffer([
+        44, // a == 44
+        2, 43, // b == 555
+        164, 213, 37, 37, // c == 2765432101
+        29, 81, 180, 20, 155, 115, 203, 193, // d == 2112667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8bu('a')
+        .word16bu('b')
+        .word32bu('c')
+        .word64bu('d')
+        .tap(function (vars) {
+            t.same(vars.a, 44);
+            t.same(vars.b, 555);
+            t.same(vars.c, 2765432101);
+            t.ok(
+                Math.abs(vars.d - 2112667700813876161) < 1500
+            );
+        })
+    ;
+    
+    // also check aliases here:
+    binary.parse(buf)
+        .word8be('a')
+        .word16be('b')
+        .word32be('c')
+        .word64be('d')
+        .tap(function (vars) {
+            t.same(vars.a, 44);
+            t.same(vars.b, 555);
+            t.same(vars.c, 2765432101);
+            t.ok(
+                Math.abs(vars.d - 2112667700813876161) < 1500
+            );
+        })
+    ;
+});
diff --git a/test/deferred.js b/test/deferred.js
new file mode 100644
index 0000000..52623f7
--- /dev/null
+++ b/test/deferred.js
@@ -0,0 +1,20 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('deferred', function (t) {
+    t.plan(1);
+    
+    var em = new EventEmitter;
+    binary.stream(em)
+        .word8('a')
+        .word16be('bc')
+        .tap(function (vars) {
+            t.same(vars, { a : 97, bc : 25187 });
+        })
+    ;
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 97, 98, 99 ]));
+    }, 10);
+});
diff --git a/test/dots.js b/test/dots.js
new file mode 100644
index 0000000..f730eb3
--- /dev/null
+++ b/test/dots.js
@@ -0,0 +1,23 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('dots', function (t) {
+    t.plan(1);
+    
+    binary.parse(new Buffer([ 97, 98, 99, 100, 101, 102 ]))
+        .word8('a')
+        .word16be('b.x')
+        .word16be('b.y')
+        .word8('b.z')
+        .tap(function (vars) {
+            t.same(vars, {
+                a : 97,
+                b : {
+                    x : 256 * 98 + 99,
+                    y : 256 * 100 + 101,
+                    z : 102
+                },
+            });
+        })
+    ;
+});
diff --git a/test/eof.js b/test/eof.js
new file mode 100644
index 0000000..e5268ff
--- /dev/null
+++ b/test/eof.js
@@ -0,0 +1,41 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('eof', function (t) {
+    t.plan(4);
+    
+    var stream = new EventEmitter;
+    binary.stream(stream)
+        .buffer('sixone', 5)
+        .peek(function () {
+            this.word32le('len');
+        })
+        .buffer('buf', 'len')
+        .word8('x')
+        .tap(function (vars) {
+            t.same(
+                [].slice.call(vars.sixone),
+                [].slice.call(new Buffer([ 6, 1, 6, 1, 6 ]))
+            );
+            t.same(vars.buf.length, vars.len);
+            t.same(
+                [].slice.call(vars.buf),
+                [ 9, 0, 0, 0, 97, 98, 99, 100, 101 ]
+            );
+            t.same(vars.x, 102);
+        })
+    ;
+    
+    var bufs = [
+        new Buffer([ 6, 1, 6, 1, 6, 9, 0, 0, 0, 97 ]),
+        new Buffer([ 98, 99 ]),
+        new Buffer([ 100, 101, 102 ]),
+    ];
+    
+    bufs.forEach(function (buf) {
+        stream.emit('data', buf);
+    });
+    
+    stream.emit('end');
+});
diff --git a/test/flush.js b/test/flush.js
new file mode 100644
index 0000000..b9c0dde
--- /dev/null
+++ b/test/flush.js
@@ -0,0 +1,17 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('flush', function (t) {
+    t.plan(1);
+    
+    binary.parse(new Buffer([ 97, 98, 99, 100, 101, 102 ]))
+        .word8('a')
+        .word16be('b')
+        .word16be('c')
+        .flush()
+        .word8('d')
+        .tap(function (vars) {
+            t.same(vars, { d : 102 });
+        })
+    ;
+});
diff --git a/test/from_buffer.js b/test/from_buffer.js
new file mode 100644
index 0000000..b5061e7
--- /dev/null
+++ b/test/from_buffer.js
@@ -0,0 +1,14 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('from buffer', function (t) {
+    t.plan(1);
+    
+    binary(new Buffer([ 97, 98, 99 ]))
+        .word8('a')
+        .word16be('bc')
+        .tap(function (vars) {
+            t.same(vars, { a : 97, bc : 25187 });
+        })
+    ;
+});
diff --git a/test/get_buffer.js b/test/get_buffer.js
new file mode 100644
index 0000000..1c62192
--- /dev/null
+++ b/test/get_buffer.js
@@ -0,0 +1,28 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('get buffer', function (t) {
+    t.plan(4);
+    
+    var buf = new Buffer([ 4, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]);
+    binary.parse(buf)
+        .word8('a')
+        .buffer('b', 7)
+        .word16lu('c')
+        .tap(function (vars) {
+            t.equal(vars.a, 4);
+            t.equal(
+                vars.b.toString(), 
+                new Buffer([ 2, 3, 4, 5, 6, 7, 8 ]).toString()
+            );
+            t.equal(vars.c, 2569);
+        })
+        .buffer('d', 'a')
+        .tap(function (vars) {
+            t.equal(
+                vars.d.toString(),
+                new Buffer([ 11, 12, 13, 14 ]).toString()
+            );
+        })
+    ;
+});
diff --git a/test/immediate.js b/test/immediate.js
new file mode 100644
index 0000000..1f0ea77
--- /dev/null
+++ b/test/immediate.js
@@ -0,0 +1,18 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('immediate', function (t) {
+    t.plan(1);
+    
+    var em = new EventEmitter;
+    binary.stream(em, 'moo')
+        .word8('a')
+        .word16be('bc')
+        .tap(function (vars) {
+            t.same(vars, { a : 97, bc : 25187 });
+        })
+    ;
+    
+    em.emit('moo', new Buffer([ 97, 98, 99 ]));
+});
diff --git a/test/interval.js b/test/interval.js
new file mode 100644
index 0000000..b17c0cb
--- /dev/null
+++ b/test/interval.js
@@ -0,0 +1,38 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('interval', function (t) {
+    t.plan(1);
+    
+    var em = new EventEmitter;
+    var i = 0;
+    var iv = setInterval(function () {
+        var buf = new Buffer(1000);
+        buf[0] = 0xff;
+        if (++i >= 1000) {
+            clearInterval(iv);
+            buf[0] = 0;
+        }
+        em.emit('data', buf);
+    }, 1);
+    
+    var loops = 0;
+    binary(em)
+        .loop(function (end) {
+            this
+            .word8('x')
+            .word8('y')
+            .word32be('z')
+            .word32le('w')
+            .buffer('buf', 1000 - 10)
+            .tap(function (vars) {
+                loops ++;
+                if (vars.x == 0) end();
+            })
+        })
+        .tap(function () {
+            t.same(loops, 1000);
+        })
+    ;
+});
diff --git a/test/into_buffer.js b/test/into_buffer.js
new file mode 100644
index 0000000..10d3d4a
--- /dev/null
+++ b/test/into_buffer.js
@@ -0,0 +1,35 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('intoBuffer', function (t) {
+    t.plan(3);
+    var buf = new Buffer([ 1, 2, 3, 4, 5, 6 ])
+    
+    binary.parse(buf)
+        .into('moo', function () {
+            this
+                .word8('x')
+                .word8('y')
+                .word8('z')
+            ;
+        })
+        .tap(function (vars) {
+            t.same(vars, { moo : { x : 1, y : 2, z : 3 } });
+        })
+        .word8('w')
+        .tap(function (vars) {
+            t.same(vars, {
+                moo : { x : 1, y : 2, z : 3 },
+                w : 4,
+            });
+        })
+        .word8('x')
+        .tap(function (vars) {
+            t.same(vars, {
+                moo : { x : 1, y : 2, z : 3 },
+                w : 4,
+                x : 5,
+            });
+        })
+    ;
+});
diff --git a/test/into_stream.js b/test/into_stream.js
new file mode 100644
index 0000000..db77092
--- /dev/null
+++ b/test/into_stream.js
@@ -0,0 +1,43 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('into stream', function (t) {
+    t.plan(3);
+    
+    var digits = [ 1, 2, 3, 4, 5, 6 ];
+    var stream = new EventEmitter;
+    var iv = setInterval(function () {
+        var d = digits.shift();
+        if (d) stream.emit('data', new Buffer([ d ]))
+        else clearInterval(iv)
+    }, 20);
+    
+    binary.stream(stream)
+        .into('moo', function () {
+            this
+                .word8('x')
+                .word8('y')
+                .word8('z')
+            ;
+        })
+        .tap(function (vars) {
+            t.same(vars, { moo : { x : 1, y : 2, z : 3 } });
+        })
+        .word8('w')
+        .tap(function (vars) {
+            t.same(vars, {
+                moo : { x : 1, y : 2, z : 3 },
+                w : 4,
+            });
+        })
+        .word8('x')
+        .tap(function (vars) {
+            t.same(vars, {
+                moo : { x : 1, y : 2, z : 3 },
+                w : 4,
+                x : 5,
+            });
+        })
+    ;
+});
diff --git a/test/loop.js b/test/loop.js
new file mode 100644
index 0000000..74576a9
--- /dev/null
+++ b/test/loop.js
@@ -0,0 +1,44 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('loop', function (t) {
+    t.plan(3 * 2 + 1);
+    
+    var em = new EventEmitter;
+    
+    binary.stream(em)
+        .loop(function (end, vars) {
+            t.strictEqual(vars, this.vars);
+            this
+                .word16lu('a')
+                .word8u('b')
+                .word8s('c')
+                .tap(function (vars_) {
+                    t.strictEqual(vars, vars_);
+                    if (vars.c < 0) end();
+                })
+            ;
+        })
+        .tap(function (vars) {
+            t.same(vars, { a : 1337, b : 55, c : -5 });
+        })
+    ;
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 2, 10, 88 ]));
+    }, 10);
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 100, 3, 6, 242, 30 ]));
+    }, 20);
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 60, 60, 199, 44 ]));
+    }, 30);
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 57, 5 ]));
+    }, 80);
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 55, 251 ]));
+    }, 90);
+});
diff --git a/test/loop_scan.js b/test/loop_scan.js
new file mode 100644
index 0000000..394603a
--- /dev/null
+++ b/test/loop_scan.js
@@ -0,0 +1,54 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('loop scan', function (t) {
+    t.plan(8 + 6 + 2);
+    
+    var em = new EventEmitter;
+    
+    binary.stream(em)
+        .loop(function (end) {
+            var vars_ = this.vars;
+            this
+                .scan('filler', 'BEGINMSG')
+                .buffer('cmd', 3)
+                .word8('num')
+                .tap(function (vars) {
+                    t.strictEqual(vars, vars_);
+                    if (vars.num != 0x02 && vars.num != 0x06) {
+                        t.same(vars.filler.length, 0);
+                    }
+                    if (vars.cmd.toString() == 'end') end();
+                })
+            ;
+        })
+        .tap(function (vars) {
+            t.same(vars.cmd.toString(), 'end');
+			t.same(vars.num, 0x08);
+        })
+    ;
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer(
+            'BEGINMSGcmd\x01'
+            + 'GARBAGEDATAXXXX'
+            + 'BEGINMSGcmd\x02'
+            + 'BEGINMSGcmd\x03'
+        ));
+    }, 10);
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer(
+            'BEGINMSGcmd\x04'
+            + 'BEGINMSGcmd\x05'
+            + 'GARBAGEDATAXXXX'
+            + 'BEGINMSGcmd\x06'
+        ));
+        em.emit('data', new Buffer('BEGINMSGcmd\x07'));
+    }, 20);
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer('BEGINMSGend\x08'));
+    }, 30);
+});
diff --git a/test/lu.js b/test/lu.js
new file mode 100644
index 0000000..8d3e9e7
--- /dev/null
+++ b/test/lu.js
@@ -0,0 +1,46 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('lu', function (t) {
+    t.plan(8);
+    
+    // note: can't store -12667700813876161 exactly in an ieee float
+    
+    var buf = new Buffer([
+        44, // a == 44
+        43, 2, // b == 555
+        37, 37, 213, 164, // c == 2765432101
+        193, 203, 115, 155, 20, 180, 81, 29, // d == 2112667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8lu('a')
+        .word16lu('b')
+        .word32lu('c')
+        .word64lu('d')
+        .tap(function (vars) {
+            t.same(vars.a, 44);
+            t.same(vars.b, 555);
+            t.same(vars.c, 2765432101);
+            t.ok(
+                Math.abs(vars.d - 2112667700813876161) < 1500
+            );
+        })
+    ;
+    
+    // also check aliases here:
+    binary.parse(buf)
+        .word8le('a')
+        .word16le('b')
+        .word32le('c')
+        .word64le('d')
+        .tap(function (vars) {
+            t.same(vars.a, 44);
+            t.same(vars.b, 555);
+            t.same(vars.c, 2765432101);
+            t.ok(
+                Math.abs(vars.d - 2112667700813876161) < 1500
+            );
+        })
+    ;
+});
diff --git a/test/negbs.js b/test/negbs.js
new file mode 100644
index 0000000..dd23a9a
--- /dev/null
+++ b/test/negbs.js
@@ -0,0 +1,29 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('negbs', function (t) {
+    t.plan(4);
+    // note: can't store -12667700813876161 exactly in an ieee float
+    
+    var buf = new Buffer([
+        226, // a == -30
+        246, 219, // b == -2341
+        255, 243, 245, 236, // c == -789012
+        255, 210, 254, 203, 16, 222, 52, 63, // d == -12667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8bs('a')
+        .word16bs('b')
+        .word32bs('c')
+        .word64bs('d')
+        .tap(function (vars) {
+            t.same(vars.a, -30);
+            t.same(vars.b, -2341);
+            t.same(vars.c, -789012);
+            t.ok(
+                Math.abs(vars.d - -12667700813876161) < 1500
+            );
+        })
+    ;
+});
diff --git a/test/negls.js b/test/negls.js
new file mode 100644
index 0000000..2a229f4
--- /dev/null
+++ b/test/negls.js
@@ -0,0 +1,29 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('negls', function (t) {
+    t.plan(4);
+    // note: can't store -12667700813876161 exactly in an ieee float
+    
+    var buf = new Buffer([
+        226, // a == -30
+        219, 246, // b == -2341
+        236, 245, 243, 255, // c == -789012
+        63, 52, 222, 16, 203, 254, 210, 255, // d == -12667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8ls('a')
+        .word16ls('b')
+        .word32ls('c')
+        .word64ls('d')
+        .tap(function (vars) {
+            t.same(vars.a, -30);
+            t.same(vars.b, -2341);
+            t.same(vars.c, -789012);
+            t.ok(
+                Math.abs(vars.d - -12667700813876161) < 1000
+            );
+        })
+    ;
+});
diff --git a/test/nested.js b/test/nested.js
new file mode 100644
index 0000000..869d51c
--- /dev/null
+++ b/test/nested.js
@@ -0,0 +1,35 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('nested', function (t) {
+    t.plan(3);
+    var insideDone = false;
+    
+    var em = new EventEmitter;
+    binary.stream(em)
+        .word16be('ab')
+        .tap(function () {
+            this
+                .word8('c')
+                .word8('d')
+                .tap(function () {
+                    insideDone = true;
+                })
+            ;
+        })
+        .tap(function (vars) {
+            t.ok(insideDone);
+            t.same(vars.c, 'c'.charCodeAt(0));
+            t.same(vars.d, 'd'.charCodeAt(0));
+            
+        })
+    ;
+    
+    var strs = [ 'abc', 'def', 'hi', 'jkl' ];
+    var iv = setInterval(function () {
+        var s = strs.shift();
+        if (s) em.emit('data', new Buffer(s));
+        else clearInterval(iv);
+    }, 50);
+});
diff --git a/test/not_enough_buf.js b/test/not_enough_buf.js
new file mode 100644
index 0000000..bbf8fff
--- /dev/null
+++ b/test/not_enough_buf.js
@@ -0,0 +1,17 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('not enough buf', function (t) {
+    t.plan(3);
+    
+    var vars = binary(new Buffer([1,2,3,4]))
+        .word8('a')
+        .buffer('b', 10)
+        .word8('c')
+        .vars
+    ;
+    
+    t.same(vars.a, 1);
+    t.equal(vars.b.toString(), new Buffer([2,3,4]).toString());
+    t.strictEqual(vars.c, null);
+});
diff --git a/test/not_enough_parse.js b/test/not_enough_parse.js
new file mode 100644
index 0000000..f9a32e2
--- /dev/null
+++ b/test/not_enough_parse.js
@@ -0,0 +1,19 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('not enough parse', function (t) {
+    t.plan(4);
+    
+    var vars = binary(new Buffer([1,2]))
+        .word8('a')
+        .word8('b')
+        .word8('c')
+        .word8('d')
+        .vars
+    ;
+    
+    t.same(vars.a, 1);
+    t.same(vars.b, 2);
+    t.strictEqual(vars.c, null);
+    t.strictEqual(vars.d, null);
+});
diff --git a/test/parse.js b/test/parse.js
new file mode 100644
index 0000000..fbc9f5b
--- /dev/null
+++ b/test/parse.js
@@ -0,0 +1,54 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('parse', function (t) {
+    t.plan(6);
+    var res = binary.parse(new Buffer([ 97, 98, 99, 99, 99, 99, 1, 2, 3 ]))
+        .word8('a')
+        .word16be('bc')
+        .skip(3)
+        .buffer('def', 3)
+        .tap(function (vars) {
+            t.equal(vars.a, 97);
+            t.equal(vars.bc, 25187);
+            t.same(
+                [].slice.call(vars.def),
+                [].slice.call(new Buffer([ 1, 2, 3]))
+            );
+        })
+        .vars
+    ;
+    t.equal(res.a, 97);
+    t.equal(res.bc, 25187);
+    t.same(
+        [].slice.call(res.def),
+        [].slice.call(new Buffer([ 1, 2, 3 ]))
+    );
+});
+
+test('loop', function (t) {
+    t.plan(2);
+    var res = binary.parse(new Buffer([ 97, 98, 99, 4, 5, 2, -3, 9 ]))
+        .word8('a')
+        .word16be('bc')
+        .loop(function (end) {
+            var x = this.word8s('x').vars.x;
+            if (x < 0) end();
+        })
+        .tap(function (vars) {
+            t.same(vars, {
+                a : 97,
+                bc : 25187,
+                x : -3,
+            });
+        })
+        .word8('y')
+        .vars
+    ;
+    t.same(res, {
+        a : 97,
+        bc : 25187,
+        x : -3,
+        y : 9,
+    });
+});
diff --git a/test/peek.js b/test/peek.js
new file mode 100644
index 0000000..00109d3
--- /dev/null
+++ b/test/peek.js
@@ -0,0 +1,40 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('peek', function (t) {
+    t.plan(4);
+    var bufs = [
+        new Buffer([ 6, 1, 6, 1, 6, 9, 0, 0, 0, 97 ]),
+        new Buffer([ 98, 99 ]),
+        new Buffer([ 100, 101, 102 ]),
+    ];
+    
+    var stream = new EventEmitter;
+    var iv = setInterval(function () {
+        var buf = bufs.shift();
+        if (buf) stream.emit('data', buf)
+        else clearInterval(iv)
+    }, 20);
+    
+    binary.stream(stream)
+        .buffer('sixone', 5)
+        .peek(function () {
+            this.word32le('len');
+        })
+        .buffer('buf', 'len')
+        .word8('x')
+        .tap(function (vars) {
+            t.same(
+                [].slice.call(vars.sixone),
+                [].slice.call(new Buffer([ 6, 1, 6, 1, 6 ]))
+            );
+            t.same(vars.buf.length, vars.len);
+            t.same(
+                [].slice.call(vars.buf),
+                [ 9, 0, 0, 0, 97, 98, 99, 100, 101 ]
+            );
+            t.same(vars.x, 102);
+        })
+    ;
+});
diff --git a/test/pipe.js b/test/pipe.js
new file mode 100644
index 0000000..7c260cd
--- /dev/null
+++ b/test/pipe.js
@@ -0,0 +1,49 @@
+var binary = require('../');
+var test = require('tap').test;
+var Stream = require('stream').Stream;
+
+test('loop', function (t) {
+    t.plan(3 * 2 + 1);
+    
+    var rs = new Stream;
+    rs.readable = true;
+    
+    var ws = binary()
+        .loop(function (end, vars) {
+            t.strictEqual(vars, this.vars);
+            this
+                .word16lu('a')
+                .word8u('b')
+                .word8s('c')
+                .tap(function (vars_) {
+                    t.strictEqual(vars, vars_);
+                    if (vars.c < 0) end();
+                })
+            ;
+        })
+        .tap(function (vars) {
+            t.same(vars, { a : 1337, b : 55, c : -5 });
+        })
+    ;
+    rs.pipe(ws);
+    
+    setTimeout(function () {
+        rs.emit('data', new Buffer([ 2, 10, 88 ]));
+    }, 10);
+    setTimeout(function () {
+        rs.emit('data', new Buffer([ 100, 3, 6, 242, 30 ]));
+    }, 20);
+    setTimeout(function () {
+        rs.emit('data', new Buffer([ 60, 60, 199, 44 ]));
+    }, 30);
+    
+    setTimeout(function () {
+        rs.emit('data', new Buffer([ 57, 5 ]));
+    }, 80);
+    setTimeout(function () {
+        rs.emit('data', new Buffer([ 55, 251 ]));
+    }, 90);
+    setTimeout(function () {
+        rs.emit('end');
+    }, 100);
+});
diff --git a/test/posbs.js b/test/posbs.js
new file mode 100644
index 0000000..0642948
--- /dev/null
+++ b/test/posbs.js
@@ -0,0 +1,29 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('posbs', function (t) {
+    t.plan(4);
+    // note: can't store 12667700813876161 exactly in an ieee float
+    
+    var buf = new Buffer([
+        30, // a == -30
+        9, 37, // b == -2341
+        0, 12, 10, 20, // c == -789012
+        0, 45, 1, 52, 239, 33, 203, 193, // d == 12667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8bs('a')
+        .word16bs('b')
+        .word32bs('c')
+        .word64bs('d')
+        .tap(function (vars) {
+            t.same(vars.a, 30);
+            t.same(vars.b, 2341);
+            t.same(vars.c, 789012);
+            t.ok(
+                Math.abs(vars.d - 12667700813876161) < 1000
+            );
+        })
+    ;
+});
diff --git a/test/posls.js b/test/posls.js
new file mode 100644
index 0000000..2b8f208
--- /dev/null
+++ b/test/posls.js
@@ -0,0 +1,29 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('posls', function (t) {
+    t.plan(4);
+    
+    // note: can't store 12667700813876161 exactly in an ieee float
+    var buf = new Buffer([
+        30, // a == -30
+        37, 9, // b == -2341
+        20, 10, 12, 0, // c == -789012
+        193, 203, 33, 239, 52, 1, 45, 0, // d == 12667700813876161
+    ]);
+    
+    binary.parse(buf)
+        .word8ls('a')
+        .word16ls('b')
+        .word32ls('c')
+        .word64ls('d')
+        .tap(function (vars) {
+            t.same(vars.a, 30);
+            t.same(vars.b, 2341);
+            t.same(vars.c, 789012);
+            t.ok(
+                Math.abs(vars.d - 12667700813876161) < 1000
+            );
+        })
+    ;
+});
diff --git a/test/scan.js b/test/scan.js
new file mode 100644
index 0000000..6acf2b2
--- /dev/null
+++ b/test/scan.js
@@ -0,0 +1,33 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('scan', function (t) {
+    t.plan(4);
+    
+    var em = new EventEmitter;
+    binary(em)
+        .word8('a')
+        .scan('l1', new Buffer('\r\n'))
+        .scan('l2', '\r\n')
+        .word8('z')
+        .tap(function (vars) {
+            t.same(vars.a, 99);
+            t.same(vars.l1.toString(), 'foo bar');
+            t.same(vars.l2.toString(), 'baz');
+            t.same(vars.z, 42);
+        })
+    ;
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer([99,0x66,0x6f,0x6f,0x20]));
+    }, 20);
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer('bar\r'));
+    }, 40);
+    
+    setTimeout(function () {
+        em.emit('data', new Buffer('\nbaz\r\n*'));
+    }, 60);
+});
diff --git a/test/scan_buf.js b/test/scan_buf.js
new file mode 100644
index 0000000..5e975c8
--- /dev/null
+++ b/test/scan_buf.js
@@ -0,0 +1,18 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('scan buf', function (t) {
+    t.plan(4);
+    
+    var vars = binary(new Buffer('\x63foo bar\r\nbaz\r\n*'))
+        .word8('a')
+        .scan('l1', new Buffer('\r\n'))
+        .scan('l2', '\r\n')
+        .word8('z')
+        .vars
+    ;
+    t.same(vars.a, 99);
+    t.same(vars.z, 42);
+    t.same(vars.l1.toString(), 'foo bar');
+    t.same(vars.l2.toString(), 'baz');
+});
diff --git a/test/scan_buf_null.js b/test/scan_buf_null.js
new file mode 100644
index 0000000..96d9767
--- /dev/null
+++ b/test/scan_buf_null.js
@@ -0,0 +1,16 @@
+var binary = require('../');
+var test = require('tap').test;
+
+test('scan buf null', function (t) {
+    t.plan(3);
+    var vars = binary(new Buffer('\x63foo bar baz'))
+        .word8('a')
+        .scan('b', '\r\n')
+        .word8('c')
+        .vars
+    ;
+    
+    t.same(vars.a, 99);
+    t.same(vars.b.toString(), 'foo bar baz');
+    t.strictEqual(vars.c, null);
+});
diff --git a/test/skip.js b/test/skip.js
new file mode 100644
index 0000000..6a26051
--- /dev/null
+++ b/test/skip.js
@@ -0,0 +1,58 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+var seq = require('seq');
+
+test('skip', function (t) {
+    t.plan(7);
+    var em = new EventEmitter;
+    var state = 0;
+    
+    binary(em)
+        .word16lu('a')
+        .tap(function () { state = 1 })
+        .skip(7)
+        .tap(function () { state = 2 })
+        .word8('b')
+        .tap(function () { state = 3 })
+        .tap(function (vars) {
+            t.same(state, 3);
+            t.same(vars, {
+                a : 2569,
+                b : 8,
+            });
+        })
+    ;
+    
+    seq()
+        .seq(setTimeout, seq, 20)
+        .seq(function () {
+            t.same(state, 0);
+            em.emit('data', new Buffer([ 9 ]));
+            this(null);
+        })
+        .seq(setTimeout, seq, 5)
+        .seq(function () {
+            t.same(state, 0);
+            em.emit('data', new Buffer([ 10, 1, 2 ]));
+            this(null);
+        })
+        .seq(setTimeout, seq, 30)
+        .seq(function () {
+            t.same(state, 1);
+            em.emit('data', new Buffer([ 3, 4, 5 ]));
+            this(null);
+        })
+        .seq(setTimeout, seq, 15)
+        .seq(function () {
+            t.same(state, 1);
+            em.emit('data', new Buffer([ 6, 7 ]));
+            this(null);
+        })
+        .seq(function () {
+            t.same(state, 2);
+            em.emit('data', new Buffer([ 8 ]));
+            this(null);
+        })
+    ;
+});
diff --git a/test/split.js b/test/split.js
new file mode 100644
index 0000000..cb9dffc
--- /dev/null
+++ b/test/split.js
@@ -0,0 +1,34 @@
+var binary = require('../');
+var test = require('tap').test;
+var EventEmitter = require('events').EventEmitter;
+
+test('split', function (t) {
+    t.plan(1);
+    
+    var em = new EventEmitter;
+    binary.stream(em)
+        .word8('a')
+        .word16be('bc')
+        .word32ls('x')
+        .word32bs('y')
+        .tap(function (vars) {
+            t.same(vars, {
+                a : 97,
+                bc : 25187,
+                x : 621609828,
+                y : 621609828,
+            });
+        })
+    ;
+    
+    em.emit('data', new Buffer([ 97, 98 ]));
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 99, 100 ]));
+    }, 25);
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 3, 13, 37, 37 ]));
+    }, 30);
+    setTimeout(function () {
+        em.emit('data', new Buffer([ 13, 3, 100 ]));
+    }, 40);
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-binary.git



More information about the Pkg-javascript-commits mailing list