@zondax/ledger-js
Version:
TS / Node API for apps running on Ledger devices
229 lines • 9.21 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ByteStream = void 0;
/******************************************************************************
* (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.
*****************************************************************************/
const consts_1 = require("./consts");
const responseError_1 = require("./responseError");
/**
* Class representing a byte stream for reading and writing data.
*/
class ByteStream {
constructor(buffer) {
this.readOffset = 0;
this.writeOffset = 0;
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) {
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) {
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) {
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) {
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) {
if (this.readOffset + length > this.internalBuffer.length) {
throw new responseError_1.ResponseError(consts_1.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, offset) {
if (offset + length > this.internalBuffer.length) {
throw new responseError_1.ResponseError(consts_1.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) {
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, offset) {
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, offset) {
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) {
if (this.readOffset + length > this.internalBuffer.length) {
throw new responseError_1.ResponseError(consts_1.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() {
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() {
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() {
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() {
return this.internalBuffer.length;
}
/**
* Returns the current read offset.
* @returns The current read offset.
*/
getReadOffset() {
return this.readOffset;
}
/**
* Returns the current write offset.
* @returns The current write offset.
*/
getWriteOffset() {
return this.writeOffset;
}
/**
* Sets the read offset to a specified value.
* @param offset The new read offset.
*/
setReadOffset(offset) {
if (offset < 0 || offset > this.internalBuffer.length) {
throw new responseError_1.ResponseError(consts_1.LedgerError.UnknownError, 'Invalid read offset');
}
this.readOffset = offset;
}
/**
* Sets the write offset to a specified value.
* @param offset The new write offset.
*/
setWriteOffset(offset) {
if (offset < 0 || offset > this.internalBuffer.length) {
throw new responseError_1.ResponseError(consts_1.LedgerError.UnknownError, 'Invalid write offset');
}
this.writeOffset = offset;
}
}
exports.ByteStream = ByteStream;
//# sourceMappingURL=byteStream.js.map