@ton/core
Version:
Core TypeScript library that implements low level primitives for TON blockchain.
216 lines (184 loc) • 5.11 kB
text/typescript
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { TupleItem } from "./tuple";
export class TupleReader {
private readonly items: TupleItem[];
constructor(items: TupleItem[]) {
this.items = [...items];
}
get remaining() {
return this.items.length;
}
peek() {
if (this.items.length === 0) {
throw Error('EOF');
}
return this.items[0];
}
pop() {
if (this.items.length === 0) {
throw Error('EOF');
}
let res = this.items[0];
this.items.splice(0, 1);
return res;
}
skip(num: number = 1) {
for (let i = 0; i < num; i++) {
this.pop();
}
return this;
}
readBigNumber() {
let popped = this.pop();
if (popped.type !== 'int') {
throw Error('Not a number');
}
return popped.value;
}
readBigNumberOpt() {
let popped = this.pop();
if (popped.type === 'null') {
return null;
}
if (popped.type !== 'int') {
throw Error('Not a number');
}
return popped.value;
}
readNumber() {
return Number(this.readBigNumber());
}
readNumberOpt() {
let r = this.readBigNumberOpt();
if (r !== null) {
return Number(r);
} else {
return null;
}
}
readBoolean() {
let res = this.readNumber();
return res === 0 ? false : true;
}
readBooleanOpt() {
let res = this.readNumberOpt();
if (res !== null) {
return res === 0 ? false : true;
} else {
return null;
}
}
readAddress() {
let r = this.readCell().beginParse().loadAddress();
if (r !== null) {
return r;
} else {
throw Error('Not an address');
}
}
readAddressOpt() {
let r = this.readCellOpt();
if (r !== null) {
return r.beginParse().loadMaybeAddress();
} else {
return null;
}
}
readCell() {
let popped = this.pop();
if (popped.type !== 'cell' && popped.type !== 'slice' && popped.type !== 'builder') {
throw Error('Not a cell: ' + popped.type);
}
return popped.cell;
}
readCellOpt() {
let popped = this.pop();
if (popped.type === 'null') {
return null;
}
if (popped.type !== 'cell' && popped.type !== 'slice' && popped.type !== 'builder') {
throw Error('Not a cell');
}
return popped.cell;
}
readTuple() {
let popped = this.pop();
if (popped.type !== 'tuple') {
throw Error('Not a tuple');
}
return new TupleReader(popped.items);
}
readTupleOpt() {
let popped = this.pop();
if (popped.type === 'null') {
return null;
}
if (popped.type !== 'tuple') {
throw Error('Not a tuple');
}
return new TupleReader(popped.items);
}
private static readLispList(reader: TupleReader | null) {
const result: TupleItem[] = [];
let tail = reader;
while (tail !== null) {
var head = tail.pop();
if (tail.items.length === 0 || (tail.items[0].type !== 'tuple' && tail.items[0].type !== 'null')) {
throw Error('Lisp list consists only from (any, tuple) elements and ends with null');
}
tail = tail.readTupleOpt();
result.push(head);
}
return result;
}
readLispListDirect(): TupleItem[] {
if (this.items.length === 1 && this.items[0].type === 'null') {
return [];
}
return TupleReader.readLispList(this);
}
readLispList() {
return TupleReader.readLispList(this.readTupleOpt());
}
readBuffer() {
let s = this.readCell().beginParse();
if (s.remainingRefs !== 0) {
throw Error('Not a buffer');
}
if (s.remainingBits % 8 !== 0) {
throw Error('Not a buffer');
}
return s.loadBuffer(s.remainingBits / 8);
}
readBufferOpt() {
let r = this.readCellOpt();
if (r !== null) {
let s = r.beginParse();
if (s.remainingRefs !== 0 || s.remainingBits % 8 !== 0) {
throw Error('Not a buffer');
}
return s.loadBuffer(s.remainingBits / 8);
} else {
return null;
}
}
readString() {
let s = this.readCell().beginParse();
return s.loadStringTail();
}
readStringOpt() {
let r = this.readCellOpt();
if (r !== null) {
let s = r.beginParse();
return s.loadStringTail();
} else {
return null;
}
}
}