diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/asn1js/src/BaseBlock.ts | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/asn1js/src/BaseBlock.ts')
-rw-r--r-- | comm/third_party/asn1js/src/BaseBlock.ts | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/comm/third_party/asn1js/src/BaseBlock.ts b/comm/third_party/asn1js/src/BaseBlock.ts new file mode 100644 index 0000000000..8a4c58528c --- /dev/null +++ b/comm/third_party/asn1js/src/BaseBlock.ts @@ -0,0 +1,186 @@ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { IBerConvertible } from "./types"; +import { LocalBaseBlockJson, LocalBaseBlockParams, LocalBaseBlock } from "./internals/LocalBaseBlock"; +import { LocalIdentificationBlock, LocalIdentificationBlockJson, LocalIdentificationBlockParams } from "./internals/LocalIdentificationBlock"; +import { LocalLengthBlock, LocalLengthBlockJson, LocalLengthBlockParams } from "./internals/LocalLengthBlock"; +import { ViewWriter } from "./ViewWriter"; +import { ValueBlock, ValueBlockJson } from "./ValueBlock"; +import { EMPTY_BUFFER, EMPTY_STRING } from "./internals/constants"; +import { typeStore } from "./TypeStore"; + +export interface IBaseBlock { + name: string; + optional: boolean; + primitiveSchema?: BaseBlock; +} + +export interface BaseBlockParams extends LocalBaseBlockParams, LocalIdentificationBlockParams, LocalLengthBlockParams, Partial<IBaseBlock> { } + +export interface ValueBlockConstructor<T extends ValueBlock = ValueBlock> { + new(...args: any[]): T; +} + +export interface BaseBlockJson<T extends LocalBaseBlockJson = LocalBaseBlockJson> extends LocalBaseBlockJson, Omit<IBaseBlock, "primitiveSchema"> { + idBlock: LocalIdentificationBlockJson; + lenBlock: LocalLengthBlockJson; + valueBlock: T; + primitiveSchema?: BaseBlockJson; +} + +export type StringEncoding = "ascii" | "hex"; + +export class BaseBlock<T extends ValueBlock = ValueBlock, J extends ValueBlockJson = ValueBlockJson> extends LocalBaseBlock implements IBaseBlock, IBerConvertible { + + static { + + } + + public static override NAME = "BaseBlock"; + + public idBlock: LocalIdentificationBlock; + public lenBlock: LocalLengthBlock; + public valueBlock: T; + public name: string; + public optional: boolean; + public primitiveSchema?: BaseBlock; + + constructor({ + name = EMPTY_STRING, + optional = false, + primitiveSchema, + ...parameters + }: BaseBlockParams = {}, valueBlockType?: ValueBlockConstructor<T>) { + super(parameters); + + this.name = name; + this.optional = optional; + if (primitiveSchema) { + this.primitiveSchema = primitiveSchema; + } + + this.idBlock = new LocalIdentificationBlock(parameters); + this.lenBlock = new LocalLengthBlock(parameters); + this.valueBlock = valueBlockType ? new valueBlockType(parameters) : new ValueBlock(parameters) as unknown as T; + } + + public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, (this.lenBlock.isIndefiniteForm) ? inputLength : this.lenBlock.length); + if (resultOffset === -1) { + this.error = this.valueBlock.error; + + return resultOffset; + } + + if (!this.idBlock.error.length) + this.blockLength += this.idBlock.blockLength; + + if (!this.lenBlock.error.length) + this.blockLength += this.lenBlock.blockLength; + + if (!this.valueBlock.error.length) + this.blockLength += this.valueBlock.blockLength; + + return resultOffset; + } + + public toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer { + const _writer = writer || new ViewWriter(); + + if (!writer) { + prepareIndefiniteForm(this); + } + + const idBlockBuf = this.idBlock.toBER(sizeOnly); + + _writer.write(idBlockBuf); + + if (this.lenBlock.isIndefiniteForm) { + _writer.write(new Uint8Array([0x80]).buffer); + + this.valueBlock.toBER(sizeOnly, _writer); + + _writer.write(new ArrayBuffer(2)); + } + else { + const valueBlockBuf = this.valueBlock.toBER(sizeOnly); + this.lenBlock.length = valueBlockBuf.byteLength; + const lenBlockBuf = this.lenBlock.toBER(sizeOnly); + + _writer.write(lenBlockBuf); + _writer.write(valueBlockBuf); + } + + if (!writer) { + return _writer.final(); + } + + return EMPTY_BUFFER; + } + + public override toJSON(): BaseBlockJson<J> { + const object: BaseBlockJson = { + ...super.toJSON(), + idBlock: this.idBlock.toJSON(), + lenBlock: this.lenBlock.toJSON(), + valueBlock: this.valueBlock.toJSON(), + name: this.name, + optional: this.optional, + }; + + + if (this.primitiveSchema) + object.primitiveSchema = this.primitiveSchema.toJSON(); + + return object as BaseBlockJson<J>; + } + public override toString(encoding: StringEncoding = "ascii"): string { + if (encoding === "ascii") { + return this.onAsciiEncoding(); + } + + return pvtsutils.Convert.ToHex(this.toBER()); + } + + protected onAsciiEncoding(): string { + return `${(this.constructor as typeof BaseBlock).NAME} : ${pvtsutils.Convert.ToHex(this.valueBlock.valueBeforeDecodeView)}`; + } + + /** + * Determines whether two object instances are equal + * @param other Object to compare with the current object + */ + public isEqual(other: unknown): other is this { + if (this === other) { + return true; + } + + // Check input type + if (!(other instanceof this.constructor)) { + return false; + } + + const thisRaw = this.toBER(); + const otherRaw = (other as BaseBlock).toBER(); + + return pvutils.isEqualBuffer(thisRaw, otherRaw); + } + +} + +/** + * Recursive function which checks and enables isIndefiniteForm flag for constructed blocks if any child has that flag enabled + * @param baseBlock Base ASN.1 block + * @returns Returns `true` if incoming block is `indefinite form` + */ +function prepareIndefiniteForm(baseBlock: BaseBlock): boolean { + if (baseBlock instanceof typeStore.Constructed) { + for (const value of baseBlock.valueBlock.value) { + if (prepareIndefiniteForm(value)) { + baseBlock.lenBlock.isIndefiniteForm = true; + } + } + } + + return !!baseBlock.lenBlock.isIndefiniteForm; +} |