@ton3/liteclient
Version:
TON Blockchain LiteClient
122 lines (87 loc) • 2.92 kB
text/typescript
import { bytesToUint } from './utils'
import { Utils } from 'ton3-core'
import { TLBoolean } from '../types/boolean'
export class StreamReader {
private offset = 0
private readonly buffer: ArrayBuffer
private readonly view: DataView
constructor (buffer: Buffer | Uint8Array) {
const temp = new Uint8Array(buffer.byteLength)
if (Buffer.isBuffer(buffer)) {
buffer.copy(temp, 0, 0, buffer.byteLength)
} else {
temp.set(buffer)
}
this.buffer = temp.buffer
this.view = new DataView(this.buffer)
}
readBytes (): Uint8Array {
let length = this.readUint8()
let lengthSize = 1
if (length === 0xfe) {
// Read 3 bytes number in little-endian order
length = bytesToUint(new Uint8Array(this.buffer.slice(this.offset, this.offset + 3)).reverse())
this.offset += 3
lengthSize += 3
}
const buffer = this.readBuffer(length)
// Padding
this.offset += 4 - (((lengthSize + length) % 4) || 4)
return new Uint8Array(buffer)
}
public readBuffer (length: number): Uint8Array {
const value = this.buffer.slice(this.offset, this.offset + length)
this.offset += length
return new Uint8Array(value)
}
public readBool (): boolean {
const result = this.readUint32LE()
if (result === TLBoolean.TRUE) {
return true
}
if (result === TLBoolean.FALSE) {
return false
}
throw new Error('Cannot parse boolean - unexpected value reached.')
}
public readUint8 (): number {
const value = this.view.getUint8(this.offset)
this.offset += 1
return value
}
public readInt32LE (): number {
const value = this.view.getInt32(this.offset, true)
this.offset += 4
return value
}
public readUint32LE (): number {
const value = this.view.getUint32(this.offset, true)
this.offset += 4
return value
}
public readInt64LE (): bigint {
const value = this.readUint64LE()
const sign = 1n << 63n
return value >= sign ? value - sign * 2n : value
}
public readUint64LE (): bigint {
return BigInt(this.readUint32LE()) | (BigInt(this.readUint32LE()) << 32n)
}
public readVector<T> (reader: (bufferReader: StreamReader) => T): T[] {
const length = this.readUint32LE()
const result = []
for (let i = 0; i < length; i++) {
result.push(reader(this))
}
return result
}
public readString (): string {
return Utils.Helpers.bytesToString(this.tail)
}
public get position () {
return this.offset
}
public get tail (): Uint8Array {
return new Uint8Array(this.buffer.slice(this.offset))
}
}