UNPKG

@toit/esptool.js

Version:
243 lines 7.28 kB
"use strict"; // Copyright (C) 2021 Toitware ApS. All rights reserved. // Use of this source code is governed by an MIT-style license that can be // found in the LICENSE file. Object.defineProperty(exports, "__esModule", { value: true }); exports.isTransientError = exports.toHex = exports.toByteArray = exports.Uint8BufferSlipEncode = exports.Uint8Buffer = exports.sleep = void 0; async function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } exports.sleep = sleep; class Uint8Buffer { constructor(size = 64) { this.readOffset = 0; this.writeOffset = 0; this.size = size; this._buffer = new ArrayBuffer(this.size); this._view = new Uint8Array(this._buffer); } get length() { return this.writeOffset - this.readOffset; } shift() { if (this.length <= 0) { return undefined; } return this._view[this.readOffset++]; } grow(newSize) { const newBuffer = new ArrayBuffer(newSize); const newView = new Uint8Array(newBuffer); newView.set(this._view, 0); this.size = newSize; this._buffer = newBuffer; this._view = newView; } fill(element, length = 1) { this.ensure(length); this._view.fill(element, this.writeOffset, this.writeOffset + length); this.writeOffset += length; } ensure(length) { if (this.size - this.writeOffset < length) { const newSize = this.size + Math.max(length, this.size); this.grow(newSize); } } pushBytes(value, byteCount, littleEndian) { for (let i = 0; i < byteCount; i++) { if (littleEndian) { this.push((value >> (i * 8)) & 0xff); } else { this.push((value >> ((byteCount - i) * 8)) & 0xff); } } } pack(format, ...args) { let pointer = 0; const data = args; if (format.replace(/[<>]/, "").length != data.length) { throw "Pack format to Argument count mismatch"; } let littleEndian = true; for (let i = 0; i < format.length; i++) { if (format[i] == "<") { littleEndian = true; } else if (format[i] == ">") { littleEndian = false; } else if (format[i] == "B") { this.pushBytes(data[pointer], 1, littleEndian); pointer++; } else if (format[i] == "H") { this.pushBytes(data[pointer], 2, littleEndian); pointer++; } else if (format[i] == "I") { this.pushBytes(data[pointer], 4, littleEndian); pointer++; } else { throw "Unhandled character in pack format"; } } } reset() { this.writeOffset = 0; this.readOffset = 0; } push(...bytes) { this.ensure(bytes.length); this._view.set(bytes, this.writeOffset); this.writeOffset += bytes.length; } copy(bytes) { this.ensure(bytes.length); this._view.set(bytes, this.writeOffset); this.writeOffset += bytes.length; } /** * @name packet * returns the bytes between two 0xc0 bytes. */ packet() { let dataStart; let dataEnd; for (let i = this.readOffset; i < this.writeOffset; i++) { if (this._view[i] === 0xc0) { if (dataStart === undefined) { dataStart = i + 1; // Empty package, normally because of wrong start marker. } else if (dataStart === i) { dataStart = i + 1; } else { dataEnd = i; break; } } } if (dataEnd === undefined || dataStart === undefined) { return undefined; } this.readOffset = dataEnd + 1; const res = new Uint8Array(this._buffer, dataStart, dataEnd - dataStart); if (this.readOffset == this.writeOffset) { this.reset(); } return res; } view(reset = true) { const res = new Uint8Array(this._buffer, this.readOffset, this.writeOffset); if (reset) { this.reset(); } return res; } } exports.Uint8Buffer = Uint8Buffer; /** * @name Uint8BufferSlipEncode * makes a Uint8Buffer with slipEncoding mechanisms. * When slipEncode is enabled it: * * replaces 0xdb with 0xdb 0xdd * * and 0xc0 with 0xdb 0xdc * for all write operations. */ class Uint8BufferSlipEncode extends Uint8Buffer { constructor() { super(...arguments); this.slipEncode = false; } push(...bytes) { if (!this.slipEncode) { super.push(...bytes); } else { bytes.forEach((v) => this.slipEncodeByte(v)); } } reset() { this.slipEncode = false; super.reset(); } copy(bytes) { if (!this.slipEncode) { super.copy(bytes); } else { bytes.forEach((v) => this.slipEncodeByte(v)); } } /** * @name packet * returns the bytes between two 0xc0 bytes. * decodes slip encoding */ packet(slipDecode = false) { const res = super.packet(); if (res === undefined || !slipDecode) { return res; } let writeOffset = 0; for (let i = 0; i < res.byteLength; i++) { if (res[i] == 0xdb && i + 1 < res.byteLength && res[i + 1] == 0xdd) { res[writeOffset++] = 0xdb; i++; } else if (res[i] == 0xdb && i + 1 < res.byteLength && res[i + 1] == 0xdc) { res[writeOffset++] = 0xc0; i++; } else { res[writeOffset++] = res[i]; } } res.slice(0, writeOffset); return res; } /** * @name slipEncodeByte * Replaces 0xdb with 0xdb 0xdd and 0xc0 with 0xdb 0xdc */ slipEncodeByte(v) { if (v == 0xdb) { super.push(0xdb, 0xdd); } else if (v == 0xc0) { super.push(0xdb, 0xdc); } else { super.push(v); } } } exports.Uint8BufferSlipEncode = Uint8BufferSlipEncode; function toByteArray(str) { const byteArray = new Uint8Array(str.length); for (let i = 0; i < str.length; i++) { const charcode = str.charCodeAt(i); byteArray[i] = charcode & 0xff; } return byteArray; } exports.toByteArray = toByteArray; function toHex(value, size = 2) { return "0x" + value.toString(16).toUpperCase().padStart(size, "0"); } exports.toHex = toHex; function isTransientError(e) { if (e instanceof DOMException) { return (e.name === "BufferOverrunError" || e.name === "BreakError" || e.name === "FramingError" || e.name === "ParityError"); } return false; } exports.isTransientError = isTransientError; //# sourceMappingURL=util.js.map