libnexa-ts
Version:
A pure and powerful Nexa SDK library.
186 lines (161 loc) • 4.6 kB
text/typescript
import type { BufferWriterOptions } from "../common/interfaces";
import type BN from "../crypto/bn.extension";
import BufferUtils from "../utils/buffer.utils";
import ValidationUtils from "../utils/validation.utils";
export default class BufferWriter {
private bufs: Uint8Array[];
private bufLen: number;
constructor(obj?: BufferWriterOptions) {
this.bufs = [];
this.bufLen = 0;
if (obj) {
this.set(obj);
}
}
public set(obj: BufferWriterOptions): this {
this.bufs = obj.bufs || this.bufs;
this.bufLen = this.bufs.reduce((prev, buf) => prev + buf.length, 0);
return this;
}
public toBuffer(): Uint8Array {
return this.concat();
}
public concat(): Uint8Array {
return BufferUtils.concat(this.bufs, this.bufLen);
}
public write(buf: Uint8Array): this {
ValidationUtils.validateArgument(BufferUtils.isBuffer(buf), "buf");
this.bufs.push(buf);
this.bufLen += buf.length;
return this;
}
public writeReverse(buf: Uint8Array): this {
ValidationUtils.validateArgument(BufferUtils.isBuffer(buf), "buf");
this.bufs.push(BufferUtils.reverse(buf));
this.bufLen += buf.length;
return this;
}
public writeUInt8(n: number): this {
const buf = new Uint8Array(1);
new DataView(buf.buffer).setUint8(0, n);
this.write(buf);
return this;
}
public writeUInt16BE(n: number): this {
const buf = new Uint8Array(2);
new DataView(buf.buffer).setUint16(0, n);
this.write(buf);
return this;
}
public writeUInt16LE(n: number): this {
const buf = new Uint8Array(2);
new DataView(buf.buffer).setUint16(0, n, true);
this.write(buf);
return this;
}
public writeUInt32BE(n: number): this {
const buf = new Uint8Array(4);
new DataView(buf.buffer).setUint32(0, n);
this.write(buf);
return this;
}
public writeInt32LE(n: number): this {
const buf = new Uint8Array(4);
new DataView(buf.buffer).setInt32(0, n, true);
this.write(buf);
return this;
}
public writeUInt32LE(n: number): this {
const buf = new Uint8Array(4);
new DataView(buf.buffer).setUint32(0, n, true);
this.write(buf);
return this;
}
public writeUInt64BEBN(bn: BN): this {
let buf = bn.toByteArray({size: 8});
this.write(buf);
return this;
}
public writeUInt64LEBN(bn: BN): this {
let buf = bn.toByteArray({size: 8});
this.writeReverse(buf);
return this;
}
public writeVarintNum(n: number): this {
let buf = BufferWriter.varintBufNum(n);
this.write(buf);
return this;
}
public writeVarintBN(bn: BN): this {
let buf = BufferWriter.varintBufBN(bn);
this.write(buf);
return this;
}
public writeVarLengthBuf(buf: Uint8Array): this {
ValidationUtils.validateArgument(BufferUtils.isBuffer(buf), "buf");
this.writeVarintNum(buf.length);
this.write(buf);
return this;
}
public writeCoreVarintNum(n: number): this {
let tmp = [];
let len = 0;
while (true)
{
tmp.push((n & 0x7F) | (len ? 0x80 : 0x00));
if (n <= 0x7F)
break;
n = (n >> 7) - 1;
len++;
}
this.write(Uint8Array.from(tmp).reverse());
return this;
}
public static varintBufNum(n: number): Uint8Array {
let buf = undefined;
if (n < 253) {
buf = new Uint8Array(1);
buf[0] = n & 0xff;
} else if (n < 0x10000) {
buf = new Uint8Array(1 + 2);
const view = new DataView(buf.buffer);
buf[0] = 253;
view.setUint16(1, n, true);
} else if (n < 0x100000000) {
buf = new Uint8Array(1 + 4);
const view = new DataView(buf.buffer);
buf[0] = 254;
view.setUint32(1, n, true);
} else {
buf = new Uint8Array(1 + 8);
const view = new DataView(buf.buffer);
buf[0] = 255;
view.setBigUint64(1, BigInt(n), true);
}
return buf;
}
public static varintBufBN(bn: BN): Uint8Array {
let buf = undefined;
let n = bn.toNumber();
if (n < 253) {
buf = new Uint8Array(1);
buf[0] = n & 0xff;
} else if (n < 0x10000) {
buf = new Uint8Array(1 + 2);
const view = new DataView(buf.buffer);
buf[0] = 253;
view.setUint16(1, n, true);
} else if (n < 0x100000000) {
buf = new Uint8Array(1 + 4);
const view = new DataView(buf.buffer);
buf[0] = 254;
view.setUint32(1, n, true);
} else {
buf = new Uint8Array(1 + 8);
const view = new DataView(buf.buffer);
buf[0] = 255;
view.setBigUint64(1, bn.toBigInt(), true);
}
return buf;
}
}