UNPKG

@steemit/steem-js

Version:

JavaScript library for the Steem blockchain

165 lines (160 loc) 5.39 kB
"use strict"; var ByteBuffer = require('bytebuffer'); var EC = require('./error_with_cause'); const HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump; class Serializer { constructor(operation_name, types) { this.operation_name = operation_name; this.types = types; if (this.types) this.keys = Object.keys(this.types); Serializer.printDebug = true; } fromByteBuffer(b) { var object = {}; var field = null; try { var iterable = this.keys; for (var i = 0, field; i < iterable.length; i++) { field = iterable[i]; var type = this.types[field]; try { if (HEX_DUMP) { if (type.operation_name) { console.error(type.operation_name); } else { var o1 = b.offset; type.fromByteBuffer(b); var o2 = b.offset; b.offset = o1; //b.reset() var _b = b.copy(o1, o2); console.error(`${this.operation_name}.${field}\t`, _b.toHex()); } } object[field] = type.fromByteBuffer(b); } catch (e) { if (Serializer.printDebug) { console.error(`Error reading ${this.operation_name}.${field} in data:`); b.printDebug(); } throw e; } } } catch (error) { EC.throw(this.operation_name + '.' + field, error); } return object; } appendByteBuffer(b, object) { var field = null; try { var iterable = this.keys; for (var i = 0, field; i < iterable.length; i++) { field = iterable[i]; var type = this.types[field]; type.appendByteBuffer(b, object[field]); } } catch (error) { try { EC.throw(this.operation_name + '.' + field + " = " + JSON.stringify(object[field]), error); } catch (e) { // circular ref EC.throw(this.operation_name + '.' + field + " = " + object[field], error); } } return; } fromObject(serialized_object) { var result = {}; var field = null; try { var iterable = this.keys; for (var i = 0, field; i < iterable.length; i++) { field = iterable[i]; var type = this.types[field]; var value = serialized_object[field]; //DEBUG value = value.resolve if value.resolve //DEBUG console.log('... value',field,value) var object = type.fromObject(value); result[field] = object; } } catch (error) { EC.throw(this.operation_name + '.' + field, error); } return result; } /** @arg {boolean} [debug.use_default = false] - more template friendly @arg {boolean} [debug.annotate = false] - add user-friendly information */ toObject(serialized_object = {}, debug = { use_default: false, annotate: false }) { var result = {}; var field = null; try { if (!this.types) return result; var iterable = this.keys; for (var i = 0, field; i < iterable.length; i++) { field = iterable[i]; var type = this.types[field]; var object = type.toObject(typeof serialized_object !== "undefined" && serialized_object !== null ? serialized_object[field] : undefined, debug); result[field] = object; if (HEX_DUMP) { var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); let has_value = typeof serialized_object !== "undefined" && serialized_object !== null; if (has_value) { let value = serialized_object[field]; if (value) type.appendByteBuffer(b, value); } b = b.copy(0, b.offset); console.error(this.operation_name + '.' + field, b.toHex()); } } } catch (error) { EC.throw(this.operation_name + '.' + field, error); } return result; } /** Sort by the first element in a operation */ compare(a, b) { let first_key = this.keys[0]; let first_type = this.types[first_key]; let valA = a[first_key]; let valB = b[first_key]; if (first_type.compare) return first_type.compare(valA, valB); if (typeof valA === "number" && typeof valB === "number") return valA - valB; let encoding; if (Buffer.isBuffer(valA) && Buffer.isBuffer(valB)) { // A binary string compare does not work. If localeCompare is well supported that could replace HEX. Performanance is very good so comparing HEX works. encoding = "hex"; } let strA = valA.toString(encoding); let strB = valB.toString(encoding); return strA > strB ? 1 : strA < strB ? -1 : 0; } // <helper_functions> fromHex(hex) { var b = ByteBuffer.fromHex(hex, ByteBuffer.LITTLE_ENDIAN); return this.fromByteBuffer(b); } fromBuffer(buffer) { var b = ByteBuffer.fromBinary(buffer.toString("binary"), ByteBuffer.LITTLE_ENDIAN); return this.fromByteBuffer(b); } toHex(object) { // return this.toBuffer(object).toString("hex") var b = this.toByteBuffer(object); return b.toHex(); } toByteBuffer(object) { var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); this.appendByteBuffer(b, object); return b.copy(0, b.offset); } toBuffer(object) { return new Buffer.from(this.toByteBuffer(object).toBinary(), 'binary'); } } module.exports = Serializer;