UNPKG

obniz

Version:

obniz sdk for javascript

274 lines (239 loc) 6.72 kB
class JsonBinaryConverter { static convertFromBinaryToJson(schema, binary) { let types = { hex: this.hexFromBinary.bind(this), uuid: this.uuidFromBinary.bind(this), number: this.numberFromBinary.bind(this), 'signed number': this.signedNumberFromBinary.bind(this), int: this.numberFromBinary.bind(this), char: this.numberFromBinary.bind(this), enum: this.enumFromBinary.bind(this), dataArray: this.dataArrayFromBinary.bind(this), }; let json = {}; let count = 0; for (let i = 0; i < schema.length; i++) { let data = binary.slice( count, schema[i].length ? count + schema[i].length : undefined ); json[schema[i].name] = types[schema[i].type](data, schema[i]); if (schema[i].length) { count += schema[i].length; } else { break; } } return json; } static hexFromBinary(data, schema) { let str = ''; for (let i = 0; i < data.length; i++) { if (schema.endianness && schema.endianness === 'little') { str = ('00' + data[i].toString(16)).slice(-2) + str; } else { str = str + ('00' + data[i].toString(16)).slice(-2); } } return str; } static uuidFromBinary(data) { let len = data[0] * 16 + data[1]; if (len === 0) { return null; } let uuidData = data.slice(2); let str = ''; for (let i = 0; i < len; i++) { str = ('00' + uuidData[i].toString(16)).slice(-2) + str; } return str; } static signedNumberFromBinary(data) { //big adian let val = data[0] & 0x7f; for (let i = 1; i < data.length; i++) { val = val * 256 + data[i]; } if ((data[0] & 0x80) !== 0) { val = val - Math.pow(2, data.length * 8 - 1); } return val; } static numberFromBinary(data) { //big adian let val = 0; for (let i = 0; i < data.length; i++) { val = val * 256 + data[i]; } return val; } static keyForVal(enumvals, val) { return Object.keys(enumvals).filter(function(k) { return enumvals[k] === val; })[0]; } static enumFromBinary(data, schema) { let enumVals = schema.enum; let val = this.numberFromBinary(data); if (schema.flags === true) { let temp = []; for (let key of Object.keys(enumVals)) { let flag = enumVals[key] & val; if (flag) { temp.push(key); } } val = temp; } else { let tmp = this.keyForVal(enumVals, val); if (tmp) { val = tmp; } } return val; } static dataArrayFromBinary(data) { let arr = new Array(data.length); for (let i = 0; i < data.length; i++) { arr[i] = data[i]; } return arr; } static createSendBuffer(schema, data) { let array = []; for (let i = 0; i < schema.length; i++) { let schemaRow = schema[i]; let row = undefined; if (Array.isArray(schemaRow)) { for (let key in schemaRow) { let customSchemaRow = Object.assign({}, schemaRow[key], { required: true, }); row = this.analyzeSchema(data, customSchemaRow); if (row) { break; } } } else { row = this.analyzeSchema(data, schemaRow); } Array.prototype.push.apply(array, row); } return new Uint8Array(array); } static analyzeSchema(allData, schemaRow) { let types = { hex: this.hexToBinary.bind(this), uuid: this.uuidToBinary.bind(this), int: this.intToBinary.bind(this), char: this.charToBinary.bind(this), dataArray: this.dataArrayToBinary.bind(this), enum: this.enumToBinary.bind(this), string: this.stringToBinary.bind(this), text: this.stringToBinary.bind(this), flag: this.flagToBinary.bind(this), }; let val = undefined; if (schemaRow.path) { val = this.getProperty(allData, schemaRow.path); } if (val === undefined && schemaRow.required) { return null; } if (val === undefined && schemaRow.default) { val = schemaRow.default; } let row = types[schemaRow.type](val, schemaRow); if (schemaRow.length && row.length !== schemaRow.length) { console.log('JSON->BINARY SCHEMA ERROR: (', val, ')', schemaRow); } return row; } static getProperty(object, path) { if (path === '' || path === undefined) { return object; } if (typeof path === 'string') path = path.split('.'); if (!Array.isArray(path)) path = [path]; let index = 0, length = path.length; while (index < length) { object = object[path[index++]]; if (object === undefined) { return undefined; } } return index && index === length ? object : undefined; } static hexToBinary(data, schema) { let array = []; let hex = data.toLowerCase().replace(/[^0-9abcdef]/g, ''); for (let i = 0; i < hex.length / 2; i++) { array[i] = parseInt(hex[i * 2] + hex[i * 2 + 1], 16); } if (schema && schema.endianness && schema.endianness === 'little') { array.reverse(); } return array; } static intToBinary(data) { let array = []; array[0] = (data >> (8 * 3)) & 0xff; array[1] = (data >> (8 * 2)) & 0xff; array[2] = (data >> (8 * 1)) & 0xff; array[3] = (data >> (8 * 0)) & 0xff; return array; } static charToBinary(data) { let array = []; array[0] = data & 0xff; return array; } static dataArrayToBinary(data) { if (!Array.isArray(data)) { data = [data]; } return data; } static uuidToBinary(data) { let uuid = this.hexToBinary(data); uuid.reverse(); //big endianness -> little endianness; let length = uuid.length; let array = []; array[0] = (length >> (8 * 1)) & 0xff; array[1] = (length >> (8 * 0)) & 0xff; Array.prototype.push.apply(array, uuid); for (let i = array.length; i < 16 + 2; i++) { array[i] = 0; } return array; } static enumToBinary(data, schema) { let array = []; array.push(schema.enum[data]); return array; } static flagToBinary(data, schema) { if (!Array.isArray(data)) { data = [data]; } let flags = schema.flags; let value = 0; for (let key in flags) { if (data.includes(flags[key])) { value += parseInt(key); } } let array = []; let length = schema.length || 1; for (let i = length - 1; i >= 0; i--) { array.push((value >> (i * 8)) & 0xff); } return array; } static stringToBinary(data) { return new Uint8Array(Buffer(data, 'utf8')); } } module.exports = JsonBinaryConverter;