import ByteStream from './ByteStream' function DataParser(data) { this.stream = new ByteStream(data); // the final parsed object from the data this.output = {}; } DataParser.prototype.parse = function(schema) { // the top level schema is just the top level parts array this.parseParts(this.output, schema); return this.output; }; // parse a set of hierarchy parts providing the parent object, and the subschema DataParser.prototype.parseParts = function(obj, schema) { for (var i = 0; i < schema.length; i++) { var part = schema[i]; this.parsePart(obj, part); } }; DataParser.prototype.parsePart = function(obj, part) { var name = part.label; var value; // make sure the part meets any parse requirements if (part.requires && !part.requires(this.stream, this.output, obj)) { return; } if (part.loop) { // create a parse loop over the parts var items = []; while (part.loop(this.stream)) { var item = {}; this.parseParts(item, part.parts); items.push(item); } obj[name] = items; } else if (part.parts) { // process any child parts value = {}; this.parseParts(value, part.parts); obj[name] = value; } else if (part.parser) { // parse the value using a parser value = part.parser(this.stream, this.output, obj); if (!part.skip) { obj[name] = value; } } else if (part.bits) { // convert the next byte to a set of bit fields obj[name] = this.parseBits(part.bits); } }; // combine bits to calculate value function bitsToNum(bitArray) { return bitArray.reduce(function(s, n) { return s * 2 + n; }, 0); } // parse a byte as a bit set (flags and values) DataParser.prototype.parseBits = function(details) { var out = {}; var bits = this.stream.readBitArray(); for (var key in details) { var item = details[key]; if (item.length) { // convert the bit set to value out[key] = bitsToNum(bits.slice(item.index, item.index + item.length)); } else { out[key] = bits[item.index]; } } return out; }; export default DataParser