madeline-ton
Version:
Pure JS client-side implementation of the Telegram TON blockchain protocol
198 lines (164 loc) • 5.21 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _stream = _interopRequireDefault(require("../TL/stream"));
var _tools = require("../tools");
var BitStream =
/*#__PURE__*/
function () {
/**
* Construct stream
* @param {ArrayBuffer} aBuf Buffer
*/
function BitStream(aBuf) {
(0, _classCallCheck2["default"])(this, BitStream);
this.pos = 0; // In bits
this.aBuf = aBuf || new ArrayBuffer(128); // Max length for cells
this.bBuf = new Uint8Array(this.aBuf);
this.refs = [];
this.refIdx = 0;
}
/**
* Write bits to stream
* @param {number|Uint8Array} n Number to write
* @param {number} length Bit length of field
*/
(0, _createClass2["default"])(BitStream, [{
key: "writeBits",
value: function writeBits(n, length) {
var byteLength = Math.ceil(length / 8);
if (!(n instanceof Uint8Array)) {
if (!_stream["default"].bigEndian) {
n = _stream["default"].switcheroo(n);
}
n = new Uint8Array(new Uint32Array([n]).buffer).subarray(-byteLength);
}
var inputShift = 8 - (length & 7);
length += inputShift;
for (var bitPos = inputShift; bitPos < length; bitPos++, this.pos++) {
//console.log(n, bitPos, bitPos >> 3, bitPos & 7, n[bitPos >> 3], (n[bitPos >> 3] >> (8 - ((bitPos & 7) + 1))) & 1)
this.bBuf[this.pos >> 3] |= (n[bitPos >> 3] >> 8 - ((bitPos & 7) + 1) & 1) << 8 - ((this.pos & 7) + 1);
}
return this;
}
/**
* Read bits from stream
* @param {number} length Number of bits to read
* @param {bool} toInt Whether to convert result to a javascript integer if length <= 32
* @returns {Uint8Array} Bitstring
*/
}, {
key: "readBits",
value: function readBits(length) {
var toInt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var result = new Uint8Array(Math.ceil(length / 8));
var inputShift = (0, _tools.posMod)(-(length & 7), 8);
length += inputShift;
for (var bitPos = inputShift; bitPos < length; bitPos++, this.pos++) {
//console.log(this.bBuf, bitPos, bitPos >> 3, bitPos & 7, this.bBuf[bitPos >> 3], (this.bBuf[bitPos >> 3] >> (8 - ((bitPos & 7) + 1))) & 1)
result[bitPos >> 3] |= (this.bBuf[this.pos >> 3] >> 8 - ((this.pos & 7) + 1) & 1) << 8 - ((bitPos & 7) + 1);
}
if (toInt) {
length = result.length;
switch (length) {
case 1:
return result[0];
case 2:
return new Uint16Array(_stream["default"].bigEndian ? result.buffer : result.reverse().buffer)[0];
case 3:
var tmp = new Uint8Array(4);
tmp.set(result, 1);
result = tmp;
case 4:
return new Uint32Array(_stream["default"].bigEndian ? result.buffer : result.reverse().buffer)[0];
}
}
return result;
}
/**
* Prepare buffer for serialization adding N more bits of free space
* Shouldn't be used much, if at all
*
* @param {number} more bits to add
* @returns Stream
*/
}, {
key: "prepareLength",
value: function prepareLength(more) {
if (!more) return this;
this.aBuf = transfer(this.aBuf, this.aBuf.byteLength + Math.ceil(more / 8));
this.bBuf = new Uint8Array(this.aBuf);
return this;
}
/**
* Push reference
* @param {Uint8Array} buffer Serialized cell buffer
* @returns BitStream
*/
}, {
key: "pushRef",
value: function pushRef(buffer) {
if (this.refIdx === 4) {
throw new Error("Trying to add too many references!");
}
this.refs[this.refIdx++] = buffer;
return this;
}
/**
* Load reference, returning slice
* @returns {BitStream} Slice
*/
}, {
key: "loadRefSlice",
value: function loadRefSlice() {
return new BitStream(this.refs[this.refIdx++]);
}
/**
* Load reference
* @returns {Uint8Array} Cell
*/
}, {
key: "loadRef",
value: function loadRef() {
return this.refs[this.refIdx++];
}
/**
* Preload reference
* @returns {Uint8Array} Cell
*/
}, {
key: "preloadRef",
value: function preloadRef() {
return this.refs[this.refIdx];
}
/**
* Skip reference
*/
}, {
key: "skipRef",
value: function skipRef() {
if (this.refIdx === 4) {
throw new Error("Trying to add too many references!");
}
this.refIdx++;
}
/**
* Skip bits
* @param {number} length Bits to skip
*/
}, {
key: "skip",
value: function skip(length) {
this.pos += length;
}
}]);
return BitStream;
}();
BitStream.bigEndian = _stream["default"].bigEndian;
var _default = BitStream;
exports["default"] = _default;