UNPKG

@ton/core

Version:

Core TypeScript library that implements low level primitives for TON blockchain.

229 lines (198 loc) 5.3 kB
/** * 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; } } }