summaryrefslogtreecommitdiffstats
path: root/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/asn1js/src/internals/LocalLengthBlock.ts')
-rw-r--r--comm/third_party/asn1js/src/internals/LocalLengthBlock.ts182
1 files changed, 182 insertions, 0 deletions
diff --git a/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts b/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts
new file mode 100644
index 0000000000..a4c7940b02
--- /dev/null
+++ b/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts
@@ -0,0 +1,182 @@
+import * as pvtsutils from "pvtsutils";
+import * as pvutils from "pvutils";
+import { IBerConvertible } from "../types";
+import { EMPTY_BUFFER } from "./constants";
+import { LocalBaseBlock, LocalBaseBlockJson } from "./LocalBaseBlock";
+import { checkBufferParams } from "./utils";
+
+export interface ILocalLengthBlock {
+ isIndefiniteForm: boolean;
+ longFormUsed: boolean;
+ length: number;
+}
+
+export interface LocalLengthBlockParams {
+ lenBlock?: Partial<ILocalLengthBlock>;
+}
+
+export interface LocalLengthBlockJson extends LocalBaseBlockJson, ILocalLengthBlock {
+ isIndefiniteForm: boolean;
+ longFormUsed: boolean;
+ length: number;
+}
+
+export class LocalLengthBlock extends LocalBaseBlock implements ILocalLengthBlock, IBerConvertible {
+
+ public static override NAME = "lengthBlock";
+
+ public isIndefiniteForm: boolean;
+ public longFormUsed: boolean;
+ public length: number;
+
+ constructor({
+ lenBlock = {},
+ }: LocalLengthBlockParams = {}) {
+ super();
+
+ this.isIndefiniteForm = lenBlock.isIndefiniteForm ?? false;
+ this.longFormUsed = lenBlock.longFormUsed ?? false;
+ this.length = lenBlock.length ?? 0;
+ }
+
+
+ public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ const view = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer);
+ // Basic check for parameters
+ if (!checkBufferParams(this, view, inputOffset, inputLength)) {
+ return -1;
+ }
+ //#region Getting Uint8Array from ArrayBuffer
+ const intBuffer = view.subarray(inputOffset, inputOffset + inputLength);
+ //#endregion
+ //#region Initial checks
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+
+ return -1;
+ }
+
+ if (intBuffer[0] === 0xFF) {
+ this.error = "Length block 0xFF is reserved by standard";
+
+ return -1;
+ }
+ //#endregion
+ //#region Check for length form type
+ this.isIndefiniteForm = intBuffer[0] === 0x80;
+ //#endregion
+ //#region Stop working in case of indefinite length form
+ if (this.isIndefiniteForm) {
+ this.blockLength = 1;
+
+ return (inputOffset + this.blockLength);
+ }
+ //#endregion
+ //#region Check is long form of length encoding using
+ this.longFormUsed = !!(intBuffer[0] & 0x80);
+ //#endregion
+ //#region Stop working in case of short form of length value
+ if (this.longFormUsed === false) {
+ this.length = (intBuffer[0]);
+ this.blockLength = 1;
+
+ return (inputOffset + this.blockLength);
+ }
+ //#endregion
+ //#region Calculate length value in case of long form
+ const count = intBuffer[0] & 0x7F;
+
+ if (count > 8) // Too big length value
+ {
+ this.error = "Too big integer";
+
+ return -1;
+ }
+
+ if ((count + 1) > intBuffer.length) {
+ this.error = "End of input reached before message was fully decoded";
+
+ return -1;
+ }
+
+ const lenOffset = inputOffset + 1;
+ const lengthBufferView = view.subarray(lenOffset, lenOffset + count);
+
+ if (lengthBufferView[count - 1] === 0x00)
+ this.warnings.push("Needlessly long encoded length");
+
+ this.length = pvutils.utilFromBase(lengthBufferView, 8);
+
+ if (this.longFormUsed && (this.length <= 127))
+ this.warnings.push("Unnecessary usage of long length form");
+
+ this.blockLength = count + 1;
+ //#endregion
+
+ return (inputOffset + this.blockLength); // Return current offset in input buffer
+ }
+
+ public toBER(sizeOnly = false): ArrayBuffer {
+ //#region Initial variables
+ let retBuf: ArrayBuffer;
+ let retView: Uint8Array;
+ //#endregion
+ if (this.length > 127)
+ this.longFormUsed = true;
+
+ if (this.isIndefiniteForm) {
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+ retView[0] = 0x80;
+ }
+
+ return retBuf;
+ }
+
+ if (this.longFormUsed) {
+ const encodedBuf = pvutils.utilToBase(this.length, 8);
+
+ if (encodedBuf.byteLength > 127) {
+ this.error = "Too big length";
+
+ return (EMPTY_BUFFER);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength + 1);
+
+ if (sizeOnly)
+ return retBuf;
+
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+
+ retView[0] = encodedBuf.byteLength | 0x80;
+
+ for (let i = 0; i < encodedBuf.byteLength; i++)
+ retView[i + 1] = encodedView[i];
+
+ return retBuf;
+ }
+
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+
+ retView[0] = this.length;
+ }
+
+ return retBuf;
+ }
+
+ public override toJSON(): LocalLengthBlockJson {
+ return {
+ ...super.toJSON(),
+ isIndefiniteForm: this.isIndefiniteForm,
+ longFormUsed: this.longFormUsed,
+ length: this.length,
+ };
+ }
+}