From 9e7ff1f32615fc7b2ba0a768fd48e749f091048d Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Wed, 12 Jun 2024 16:46:20 +0200 Subject: [PATCH] adding support for bytestream writing (#30) * adding support for bytestream writing * formatting --- bun.lockb | Bin 226614 -> 226614 bytes package.json | 6 +- src/byteStream.test.ts | 113 +++++++++++++++++++ src/byteStream.ts | 246 +++++++++++++++++++++++++++++++++++++++++ src/common.test.ts | 3 +- src/common.ts | 20 +--- src/errors.ts | 33 ++++++ src/payload.ts | 66 +---------- src/responseError.ts | 2 +- 9 files changed, 406 insertions(+), 83 deletions(-) create mode 100644 src/byteStream.test.ts create mode 100644 src/byteStream.ts create mode 100644 src/errors.ts diff --git a/bun.lockb b/bun.lockb index da4ddfd27a109ce63abbb95f1c9ff1f98ecbf44f..6762f2a2046db2c3d2b6095166ac8b58c6ab730f 100755 GIT binary patch delta 1425 zcmdn?ig(*9-U)gNpEqCG_p|Ek_Sl}LW7D?AFx8&9rciYMaaj{v%8pJ}t92Xwngm1- z%w=FuVPI%51Jd$9dIgY{*!)!Bw1C7)*}EsMZgTy`bf>LmMyGM!#M_>Xn=U4_Z$622`J66 z48r$-(3?A!@dyiYFfcG^u`)0)0cjl|&9Hgt&hr9Tgj-J?$aGl48YkNt?dhc_^MDtx7f;D?jwr55Dn!6@If`RMTX5~K>8(EdN zxjer6H>EkqvuCHYCb?Y>nVwt6C{bU)eQ>XrM(!$(qOKLk!=$zrFZYUl zaQyCS&RIMzf6ka`Gk2UV+oZT?strovD`$jqr{B=tpX3pJt)G#Bfsx@K z|34tj4e~w|u*{eISJrdk_+zfukw(U5%-%5jj*P?sJ-;*lzt;TH5s1C( zwMTh!{%5f-v-~Rhk~6p!-YhHD4?Db3d6AA$j@0StrQTQ8-G0ra^*3jGW>p1}^LUY+ zm$sRyI;1MwH~4$U((u@OP2bh`29+)sSvbMh&cx#InL717xdm}^bR?ng5)3OJ?Ct4vSOHRcTWb z+anhLKdb5Y;Z#xR*NqcuyOwYKsBxh-qQGFax!TR=278WuM{*uNvh$7{)HSxr`uZd# zUC$=&O)5*w%a8-_);h@Zy$d`a*S6?^Zd|T#2A8m;xYe|P;PX4##FalZXVf2TmcKvw zzs2?sF<++FHZV#!^d4{iC?TuyBy^6P#0#le8$YRtNmeXfaqv28;hH$9$pYUTKHErK zQ*Ov%Ioq=DaoxQ`QLEPR9X|YSZtJaNqv?&J+pjh-YENTS*v=@<6wJt|wmnpWNu7;V z2AITUw>Qc$l{2zA0KK5hy8WL#lNu{0C=aLrvD$WBRVHgO*EV2k-~svzlrliU&jrN! zKn)=AuRt1j7Hma?3hBDr#J0plA1ngKa&s( zST61WlNf}haD+*c(RliXgG`dsKkj3a2dOlf-g1bk7AOi*#s<=$XE42B0#JqbZYFUi zpxJ%$6S9cB8JHvMxZv%>ZXI?QXFfRYpQnJuRa6fmnm*e27hGMME+?gC1$-Z delta 1392 zcmdn?ig(*9-U)gN%jEL4&vX8r^;EDlR@t)jOL$&!u|?(K0*C)=J>x?6`)u@U5}3>( zAhG#{zzKoLFBBv;pHLL=ogATWu$d#j$8_=)B@<5Rr3?%q3=9qIlP@ZnbLIniZgAdK zATJKao7}OK2c%>22`J6648r$-(3?A!@dyhtF)%QwumTAv&9Qmu&hr9Tgj-J?$aHw4 zU~qbR;AUwXo6^ho?kFA2ueb0_{cz~W#SnjvIZNMY3cUr!|)@@FnlG5nDsdK`tiElT?viiw} zSs&zTD7tW!p@G+HO~DW0rT&ZB!?#@t5ppxVGokYPcFA88r{~r&O4RS1Y0dlkwZo?G zdo}Ni#YOjbbHAU}^u?~F%zT;RwYQU=sws(2TlQknsgN0$g9=sr{+-D>7h#sYJanVg zgXh~mt(IkEU|?kU$NvvVbAy5b3Ro7u6|P=BZFyFvX74i{Rl5ZK%#b;W0TWH1gjP?M zZvJLrpuo28@Si!75)*vZHe6mBIK}vP!qW9Y6^GX~s?Cmw+MPFDwjSubr+c*Yjy4AD z{@T7O{q13~r&q84?VUAKsyk!V8b;NE9KkcGn#Wi8A2;v5{P3emMzqplG5z)TRaQJ* zcy+y`X4z6sB9^(*GDMYG(wiJteJd^fx){$`iNwR_U^vmocai7%}^_Kx@e-Mji4x8qme zoq0#1Q||xsX_Fl_t#iHO1n%pu$nKn2%aQS;c7xm&kEa>p$)%cmvzNxj?uzzbR&f!@ zdHl%Eo2K^n)t!l3PIw<@TgRKK`S0m=krUp`3%;zGFZ`ym{k`mVDPOn4+cI5c21W^oaO6;W%CpJ*y11aCri%yWSyZH+vd)4=C4!Q|Liu-=zqN1uQo7hPh*tZ z&M3|l%*d#*Jye28osCr%nAGLAH_9=UGqR}y*$#}`|H(6{v2rQ_Ich+xv0Yb{$y!Vf z6y%^(!2`rxK->mQ9r-{%mxEKw^g3%MDPE8~NDfR-Uu(@I&&W0XtTmIgC`cDbHAp58 zNP|q{+5Xp>Nt039NY8+w6KI+wFr%j3wBHn}Yw?tWG0t4i&}h1&Ez>JT!|ghDOd-u; z59cs2C;%1Z$$j2`^@fTi6C+qn-+m@B7BI{1D3c_k(ew=mnIxHkrcQ6z%_K8zH5KBHxW0IM!ag<3ERmJwQqfEcjrYqfGQrJF0hk1xy)P;F9D@2rvFc8=AHg7msu1pW-?tin^}Pg7(!sZ`wN&AA$t9R Slwl#WD}<-MeO@8+3}yhIegAO) diff --git a/package.json b/package.json index 405f8cb..d55b653 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jest": "29.5.12", "@types/node": "^20.14.2", - "@typescript-eslint/eslint-plugin": "^7.12.0", - "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", "eslint": "^9.4.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^39.0.0", @@ -52,7 +52,7 @@ "eslint-plugin-promise": "^6.2.0", "eslint-plugin-tsdoc": "^0.3.0", "eslint-plugin-unused-imports": "^4.0.0", - "prettier": "^3.3.1", + "prettier": "^3.3.2", "ts-jest": "^29.1.4", "ts-node": "^10.9.2", "typescript": "^5.4.5" diff --git a/src/byteStream.test.ts b/src/byteStream.test.ts new file mode 100644 index 0000000..63b2ae8 --- /dev/null +++ b/src/byteStream.test.ts @@ -0,0 +1,113 @@ +/****************************************************************************** + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +import { Buffer } from 'buffer' + +import { ByteStream } from './byteStream' +import { LedgerError } from './consts' +import { ResponseError } from './responseError' + +describe('ByteStream', () => { + let byteStream: ByteStream + + beforeEach(() => { + byteStream = new ByteStream(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05])) + }) + + test('getCompleteBuffer should return a complete buffer', () => { + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05])) + }) + + test('getAvailableBuffer should return the available buffer after some bytes are read', () => { + byteStream.readBytes(3) + expect(byteStream.getAvailableBuffer()).toEqual(Buffer.from([0x04, 0x05])) + }) + + test('readBytes should return the correct bytes and increase offset', () => { + const readBuffer = byteStream.readBytes(2) + expect(readBuffer).toEqual(Buffer.from([0x01, 0x02])) + expect(byteStream.readBytes(1)).toEqual(Buffer.from([0x03])) + }) + + test('skipBytes should increase the offset correctly', () => { + byteStream.skipBytes(2) + expect(byteStream.readBytes(1)).toEqual(Buffer.from([0x03])) + }) + + test('resetOffset should reset the offset to zero', () => { + byteStream.readBytes(3) + byteStream.resetOffset() + expect(byteStream.readBytes(2)).toEqual(Buffer.from([0x01, 0x02])) + }) + + test('readBytes should throw an error when reading beyond the buffer length', () => { + expect(() => byteStream.readBytes(10)).toThrow(new ResponseError(LedgerError.UnknownError, 'Attempt to read beyond buffer length')) + }) + + test('skipBytes should throw an error when skipping beyond the buffer length', () => { + expect(() => byteStream.skipBytes(10)).toThrow(new ResponseError(LedgerError.UnknownError, 'Attempt to skip beyond buffer length')) + }) + + test('appendUint8 should correctly append a byte to the buffer', () => { + byteStream.appendUint8(0x06) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])) + }) + + test('appendUint16 should correctly append a two-byte integer to the buffer', () => { + byteStream.appendUint16(0x0708) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x08, 0x07])) + }) + + test('appendUint32 should correctly append a four-byte integer to the buffer', () => { + byteStream.appendUint32(0x090a0b0c) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x0c, 0x0b, 0x0a, 0x09])) + }) + + test('appendUint64 should correctly append an eight-byte integer to the buffer', () => { + byteStream = new ByteStream() + byteStream.appendUint64(BigInt('0x0102030405060708')) + expect(byteStream.readBytes(8)).toEqual(Buffer.from([8, 7, 6, 5, 4, 3, 2, 1])) + }) + + test('readBytesAt should return the correct bytes from a given offset', () => { + const readBuffer = byteStream.readBytesAt(2, 1) + expect(readBuffer).toEqual(Buffer.from([0x02, 0x03])) + }) + + test('readBytesAt should throw an error when reading beyond the buffer length', () => { + expect(() => byteStream.readBytesAt(10, 1)).toThrow(new ResponseError(LedgerError.UnknownError, 'Attempt to read beyond buffer length')) + }) + + test('insertBytesAt should correctly insert bytes at a given offset', () => { + byteStream.insertBytesAt(Buffer.from([0x06, 0x07]), 2) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x06, 0x07, 0x03, 0x04, 0x05])) + }) + + test('insertBytesAt should expand the buffer if necessary', () => { + byteStream.insertBytesAt(Buffer.from([0x08, 0x09]), 10) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09])) + }) + + test('writeBytesAt should correctly write bytes at a given offset and advance the write offset', () => { + byteStream.writeBytesAt(Buffer.from([0x0a, 0x0b]), 1) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x0a, 0x0b, 0x04, 0x05])) + expect(byteStream.readBytes(5)).toEqual(Buffer.from([0x01, 0x0a, 0x0b, 0x04, 0x05])) + }) + + test('writeBytesAt should expand the buffer if necessary', () => { + byteStream.writeBytesAt(Buffer.from([0x0c, 0x0d]), 10) + expect(byteStream.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0d])) + }) +}) diff --git a/src/byteStream.ts b/src/byteStream.ts new file mode 100644 index 0000000..649d9a2 --- /dev/null +++ b/src/byteStream.ts @@ -0,0 +1,246 @@ +/****************************************************************************** + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +import { LedgerError } from './consts' +import { ResponseError } from './responseError' + +/** + * Class representing a byte stream for reading and writing data. + */ +export class ByteStream { + private readOffset = 0 + private writeOffset = 0 + protected internalBuffer: Buffer + + constructor(buffer?: Buffer) { + this.internalBuffer = buffer ? Buffer.from(buffer) : Buffer.alloc(0) + this.readOffset = 0 + this.writeOffset = this.internalBuffer.length + } + + /** + * Writes a single byte (Uint8) to the buffer at the current write offset, then advances the write offset. + * If the write offset is at the buffer's end, the buffer is expanded. + * @param value The byte to write. + */ + appendUint8(value: number) { + const byteBuffer = Buffer.from([value]) + this.appendBytes(byteBuffer) + } + + /** + * Writes a two-byte unsigned integer (Uint16) to the buffer at the current write offset in little-endian format, then advances the write offset. + * If the write offset is at the buffer's end, the buffer is expanded. + * @param value The two-byte unsigned integer to write. + */ + appendUint16(value: number) { + const byteBuffer = Buffer.alloc(2) + byteBuffer.writeUInt16LE(value, 0) + this.appendBytes(byteBuffer) + } + + /** + * Writes a four-byte unsigned integer (Uint32) to the buffer at the current write offset in little-endian format, then advances the write offset. + * If the write offset is at the buffer's end, the buffer is expanded. + * @param value The four-byte unsigned integer to write. + */ + appendUint32(value: number) { + const byteBuffer = Buffer.alloc(4) + byteBuffer.writeUInt32LE(value, 0) + this.appendBytes(byteBuffer) + } + + /** + * Writes an eight-byte unsigned integer (Uint64) to the buffer at the current write offset in little-endian format, then advances the write offset. + * If the write offset is at the buffer's end, the buffer is expanded. + * @param value The eight-byte unsigned integer to write. + */ + appendUint64(value: bigint) { + const byteBuffer = Buffer.alloc(8) + byteBuffer.writeBigUInt64LE(value, 0) + this.appendBytes(byteBuffer) + } + + /** + * Reads a specified number of bytes from the current read offset, then advances the read offset. + * @param length The number of bytes to read. + * @returns A buffer containing the read bytes. + * @throws Error if attempting to read beyond the buffer length. + */ + readBytes(length: number): Buffer { + if (this.readOffset + length > this.internalBuffer.length) { + throw new ResponseError(LedgerError.UnknownError, 'Attempt to read beyond buffer length') + } + const response = this.internalBuffer.subarray(this.readOffset, this.readOffset + length) + this.readOffset += length + return response + } + + /** + * Reads a specified number of bytes from a given offset without changing the current read offset. + * @param length The number of bytes to read. + * @param offset The offset from which to read the bytes. + * @returns A buffer containing the read bytes. + * @throws Error if attempting to read beyond the buffer length. + */ + readBytesAt(length: number, offset: number): Buffer { + if (offset + length > this.internalBuffer.length) { + throw new ResponseError(LedgerError.UnknownError, 'Attempt to read beyond buffer length') + } + return this.internalBuffer.subarray(offset, offset + length) + } + + /** + * Writes data to the buffer at the current write offset, then advances the write offset. + * If the data exceeds the buffer length, the buffer is expanded. + * @param data The data to write. + */ + appendBytes(data: Buffer) { + if (this.writeOffset + data.length > this.internalBuffer.length) { + const newBuffer = Buffer.alloc(this.writeOffset + data.length) + this.internalBuffer.copy(newBuffer, 0, 0, this.writeOffset) + this.internalBuffer = newBuffer + } + data.copy(this.internalBuffer, this.writeOffset) + this.writeOffset += data.length + } + + /** + * Inserts data into the buffer at the specified offset without changing the current write offset. + * Expands the buffer if necessary. + * @param data The data to insert. + * @param offset The offset at which to insert the data. + */ + insertBytesAt(data: Buffer, offset: number) { + if (offset > this.internalBuffer.length) { + const padding = Buffer.alloc(offset - this.internalBuffer.length, 0) + this.internalBuffer = Buffer.concat([this.internalBuffer, padding, data]) + } else { + const before = this.internalBuffer.subarray(0, offset) + const after = this.internalBuffer.subarray(offset) + this.internalBuffer = Buffer.concat([before, data, after]) + } + } + + /** + * Writes data to the buffer at the specified offset and advances the write offset from that point. + * Expands the buffer if the data exceeds the buffer length. + * @param data The data to write. + * @param offset The offset at which to write the data. + */ + writeBytesAt(data: Buffer, offset: number) { + if (offset + data.length > this.internalBuffer.length) { + const newBuffer = Buffer.alloc(offset + data.length) + this.internalBuffer.copy(newBuffer, 0, 0, offset) + this.internalBuffer = newBuffer + } + data.copy(this.internalBuffer, offset) + this.writeOffset = offset + data.length + } + + /** + * Advances the current read offset by a specified number of bytes. + * @param length The number of bytes to skip. + * @throws Error if attempting to skip beyond the buffer length. + */ + skipBytes(length: number) { + if (this.readOffset + length > this.internalBuffer.length) { + throw new ResponseError(LedgerError.UnknownError, 'Attempt to skip beyond buffer length') + } + this.readOffset += length + } + + clear() { + this.internalBuffer = Buffer.alloc(0) + this.readOffset = 0 + this.writeOffset = 0 + } + + /** + * Resets the current read and write offsets to zero. + */ + resetOffset() { + this.readOffset = 0 + this.writeOffset = 0 + } + + /** + * Returns a new buffer containing all bytes of the internal buffer. + */ + getCompleteBuffer(): Buffer { + return Buffer.from(this.internalBuffer) + } + + /** + * Returns a new buffer containing the bytes from the current read offset to the end of the internal buffer. + */ + getAvailableBuffer(): Buffer { + return Buffer.from(this.internalBuffer.subarray(this.readOffset)) + } + + /** + * Returns the remaining length of the buffer from the current read offset. + * @returns The remaining length of the buffer. + */ + length(): number { + return this.internalBuffer.length - this.readOffset + } + + /** + * Returns the total capacity of the internal buffer, irrespective of the current read or write offset. + * @returns The total length of the internal buffer. + */ + capacity(): number { + return this.internalBuffer.length + } + + /** + * Returns the current read offset. + * @returns The current read offset. + */ + getReadOffset(): number { + return this.readOffset + } + + /** + * Returns the current write offset. + * @returns The current write offset. + */ + getWriteOffset(): number { + return this.writeOffset + } + + /** + * Sets the read offset to a specified value. + * @param offset The new read offset. + */ + setReadOffset(offset: number) { + if (offset < 0 || offset > this.internalBuffer.length) { + throw new ResponseError(LedgerError.UnknownError, 'Invalid read offset') + } + this.readOffset = offset + } + + /** + * Sets the write offset to a specified value. + * @param offset The new write offset. + */ + setWriteOffset(offset: number) { + if (offset < 0 || offset > this.internalBuffer.length) { + throw new ResponseError(LedgerError.UnknownError, 'Invalid write offset') + } + this.writeOffset = offset + } +} diff --git a/src/common.test.ts b/src/common.test.ts index 4ba2b59..450469e 100644 --- a/src/common.test.ts +++ b/src/common.test.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. *****************************************************************************/ -import { errorCodeToString, processErrorResponse } from './common' +import { processErrorResponse } from './common' import { LedgerError } from './consts' +import { errorCodeToString } from './errors' import { ResponseError } from './responseError' describe('errorCodeToString', () => { diff --git a/src/common.ts b/src/common.ts index 5aa2afd..2a030df 100644 --- a/src/common.ts +++ b/src/common.ts @@ -13,27 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. *****************************************************************************/ -import { ERROR_DESCRIPTION_OVERRIDE, LedgerError } from './consts' +import { LedgerError } from './consts' +import { errorCodeToString } from './errors' import { ResponsePayload } from './payload' import { ResponseError } from './responseError' -/** - * Converts a Ledger error code to a human-readable string. - * - * @param returnCode - The Ledger error code to convert. - * @returns A string describing the error code. - */ -export function errorCodeToString(returnCode: LedgerError): string { - const returnCodeStr = returnCode.toString(16).toUpperCase() - let errDescription = `Unknown Return Code: 0x${returnCodeStr}` - - if (returnCode in ERROR_DESCRIPTION_OVERRIDE) { - errDescription = ERROR_DESCRIPTION_OVERRIDE[returnCode] - } - - return errDescription -} - /** * Checks if a value is a dictionary (i.e., a plain object). * diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 0000000..6511c8e --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,33 @@ +/****************************************************************************** + * (c) 2018 - 2024 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +import { ERROR_DESCRIPTION_OVERRIDE, LedgerError } from './consts' + +/** + * Converts a Ledger error code to a human-readable string. + * + * @param returnCode - The Ledger error code to convert. + * @returns A string describing the error code. + */ +export function errorCodeToString(returnCode: LedgerError): string { + const returnCodeStr = returnCode.toString(16).toUpperCase() + let errDescription = `Unknown Return Code: 0x${returnCodeStr}` + + if (returnCode in ERROR_DESCRIPTION_OVERRIDE) { + errDescription = ERROR_DESCRIPTION_OVERRIDE[returnCode] + } + + return errDescription +} diff --git a/src/payload.ts b/src/payload.ts index faf8d76..6914136 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -13,67 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. *****************************************************************************/ -import { LedgerError } from './consts' -import { ResponseError } from './responseError' - -export class ResponsePayload { - private offset = 0 - private readonly internalBuffer: Buffer +import { ByteStream } from './byteStream' +/** + * Class representing a payload response for reading data. + */ +export class ResponsePayload extends ByteStream { constructor(payload: Buffer) { - this.internalBuffer = payload - this.offset = 0 - } - - /** - * Returns a new buffer containing all bytes of the original payload. - */ - getCompleteBuffer(): Buffer { - return Buffer.from(this.internalBuffer) - } - - /** - * Returns a new buffer containing the bytes from the current offset to the end of the payload. - */ - getAvailableBuffer(): Buffer { - return Buffer.from(this.internalBuffer.subarray(this.offset)) - } - - length(): number { - return this.internalBuffer.length - this.offset - } - - /** - * Reads a specified number of bytes from the current offset, then advances the offset. - * @param length The number of bytes to read. - * @returns A buffer containing the read bytes. - * @throws Error if attempting to read beyond the buffer length. - */ - readBytes(length: number): Buffer { - if (this.offset + length > this.internalBuffer.length) { - throw new ResponseError(LedgerError.UnknownError, 'Attempt to read beyond buffer length') - } - const response = this.internalBuffer.subarray(this.offset, this.offset + length) - this.skipBytes(length) - return response - } - - /** - * Advances the current offset by a specified number of bytes. - * @param length The number of bytes to skip. - * @throws Error if attempting to skip beyond the buffer length. - */ - skipBytes(length: number) { - if (this.offset + length > this.internalBuffer.length) { - throw new ResponseError(LedgerError.UnknownError, 'Attempt to skip beyond buffer length') - } - this.offset += length - } - - /** - * Resets the current offset to zero. - */ - resetOffset() { - this.offset = 0 + super(payload) } } diff --git a/src/responseError.ts b/src/responseError.ts index a43b64d..8c0819d 100644 --- a/src/responseError.ts +++ b/src/responseError.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. *****************************************************************************/ -import { errorCodeToString } from './common' +import { errorCodeToString } from './errors' /** * Class representing a response error.