blob: eee85c8ddcbb03d6986fc96fdbb71202816e6e35 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*global escape: true */
/**
* @fileoverview Definition of RawVomReader.
* @private
*/
module.exports = RawVomReader;
var BigInt = require('../vdl/big-int.js');
var BinaryReader = require('./binary-reader.js');
var ByteUtil = require('../vdl/byte-util.js');
/**
* RawVomReader reads VOM primitive values (numbers, strings, bools) from a
* provided Uint8Array.
* @private
* @param {Uint8Array} arr The array to read from.
* @constructor
*/
function RawVomReader(arr) {
this._reader = new BinaryReader(arr);
}
/**
* Reads a BigUint.
* @return {BigUint} The BigUint that was read.
*/
RawVomReader.prototype.readBigUint = function() {
var firstByte = this._reader.readByte();
if (firstByte <= 0x7f) {
if (firstByte === 0) {
return new BigInt(0, new Uint8Array(0));
}
return new BigInt(1, new Uint8Array([firstByte]));
}
var numBytes = 0x100 - firstByte;
if (numBytes > 8 || numBytes < 1) {
throw new Error('Invalid size ' + numBytes);
}
var uintBytes = this._reader.readByteArray(numBytes);
return new BigInt(1, uintBytes);
};
/**
* Returns a control byte if the next byte is a control byte.
* @returns {Number} a control byte if there is one, null if there is no
* control byte
*/
RawVomReader.prototype.tryReadControlByte = function() {
var firstByte = this.peekByte();
if (firstByte === null) {
return null;
}
if (firstByte > 0x7f && firstByte <= 0xef) {
return this.readByte();
}
return null;
};
/**
* Reads a BigInt.
* @return {BigInt} The BigInt that was read.
*/
RawVomReader.prototype.readBigInt = function() {
var uint = this.readBigUint();
var bytes = uint.getUintBytes();
var sign;
if (uint.getSign() === 0) {
sign = 0;
} else if (bytes.length > 0 && (bytes[bytes.length - 1] & 0x01) !== 0) {
sign = -1;
} else {
sign = 1;
}
bytes = ByteUtil.shiftRightOne(bytes);
if (sign === -1) {
bytes = ByteUtil.increment(bytes);
}
return new BigInt(sign, bytes);
};
/**
* Reads a unsigned integer as a native JavaScript number.
* @return {number} The uint that was read.
*/
RawVomReader.prototype.readUint = function() {
return this.readBigUint().toNativeNumber();
};
/**
* Reads a integer as a native JavaScript number.
* @return {number} The int that was read.
*/
RawVomReader.prototype.readInt = function() {
return this.readBigInt().toNativeNumber();
};
/**
* Reads a float as a native JavaScript number.
* @return {number} The float that was read.
*/
RawVomReader.prototype.readFloat = function() {
var uintBytes = this.readBigUint().getUintBytes();
var arr = new Uint8Array(8);
arr.set(uintBytes, arr.length - uintBytes.length);
var view = new DataView(arr.buffer);
return view.getFloat64(0, true);
};
/**
* Reads a string.
* @return {string} The string that was read.
*/
RawVomReader.prototype.readString = function() {
var length = this.readUint();
var str = '';
for (var i = 0; i < length; i++) {
str += String.fromCharCode(this._reader.readByte());
}
return decodeURIComponent(escape(str));
};
/**
* Reads a boolean.
* @return {boolean} The boolean that was read.
*/
RawVomReader.prototype.readBool = function() {
var b = this._reader.readByte();
if (b === 1) {
return true;
} else if (b === 0) {
return false;
}
throw new Error('Invalid boolean byte ' + b);
};
/**
* Reads a single VOM byte.
* @return {byte} The byte that was read.
*/
RawVomReader.prototype.readByte = function() {
return this._reader.readByte();
};
/**
* Reads a single VOM byte without advancing the reader
* @return {byte} The byte that was read.
*/
RawVomReader.prototype.peekByte = function() {
return this._reader.peekByte();
};
/**
* Reads raw bytes.
* @param {number} amt The number of bytes to read.
* @return {Uint8Array} The bytes that were read.
*/
RawVomReader.prototype._readRawBytes = function(amt) {
return this._reader.readByteArray(amt);
};