@steemit/steem-js
Version:
JavaScript library for the Steem blockchain
165 lines (160 loc) • 5.39 kB
JavaScript
"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;