// Default stream and parsers for Uint8TypedArray data type export const buildStream = uint8Data => ({ data: uint8Data, pos: 0 }) export const readByte = () => stream => { return stream.data[stream.pos++] } export const peekByte = (offset = 0) => stream => { return stream.data[stream.pos + offset] } export const readBytes = length => stream => { return stream.data.subarray(stream.pos, (stream.pos += length)) } export const peekBytes = length => stream => { return stream.data.subarray(stream.pos, stream.pos + length) } export const readString = length => stream => { return Array.from(readBytes(length)(stream)) .map(value => String.fromCharCode(value)) .join('') } export const readUnsigned = littleEndian => stream => { const bytes = readBytes(2)(stream) return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1] } export const readArray = (byteSize, totalOrFunc) => ( stream, result, parent ) => { const total = typeof totalOrFunc === 'function' ? totalOrFunc(stream, result, parent) : totalOrFunc const parser = readBytes(byteSize) const arr = new Array(total) for (var i = 0; i < total; i++) { arr[i] = parser(stream) } return arr } const subBitsTotal = (bits, startIndex, length) => { var result = 0 for (var i = 0; i < length; i++) { result += bits[startIndex + i] && 2 ** (length - i - 1) } return result } export const readBits = schema => stream => { const byte = readByte()(stream) // convert the byte to bit array const bits = new Array(8) for (var i = 0; i < 8; i++) { bits[7 - i] = !!(byte & (1 << i)) } // convert the bit array to values based on the schema return Object.keys(schema).reduce((res, key) => { const def = schema[key] if (def.length) { res[key] = subBitsTotal(bits, def.index, def.length) } else { res[key] = bits[def.index] } return res }, {}) }