nycJSorg/angular-presentation

View on GitHub
apps/kirjs/src/app/modules/binary/parser/binary-parser.ts

Summary

Maintainability
C
1 day
Test Coverage
import { BinaryObjectParser } from './parsers/object-parser';
import { StringParser, StringParserConfig } from './parsers/string-parser';
import { BinaryChoiceParser } from './parsers/choice-parser';
import { BinaryArrayParser } from './parsers/array-parser';
import { BitParser } from './parsers/bit-parser';
import { VarUintParser, VarUintParserConfig } from './parsers/var-uint-parser';
import { BinaryReader } from './readers/abstract-reader';
import { beToLe32 } from './parsers/common';

export interface BaseConfig {
  description?: string;
  length?: number;
  type?: string;
  converter?: (a: string) => number;
  enum?: { [key: string]: string };
}

export class BinaryParser {
  type = 'object';
  private parser: BinaryObjectParser;

  constructor() {
    this.parser = new BinaryObjectParser();
  }

  string(name: string, config: StringParserConfig) {
    this.parser.addStep(name, new StringParser(config));
    return this;
  }

  varuint7(name: string, config: Partial<VarUintParserConfig> = {}) {
    this.parser.addStep(name, new VarUintParser(config));
    return this;
  }

  varuint31(name: string, config: Partial<VarUintParserConfig> = {}) {
    this.parser.addStep(
      name,
      new VarUintParser({
        ...config,
        size: 31
      })
    );
    return this;
  }

  choice(name: string, config: any) {
    this.parser.addStep(name, new BinaryChoiceParser({ ...config }));
    return this;
  }

  array(name: string, config: any) {
    this.parser.addStep(name, new BinaryArrayParser({ ...config }));
    return this;
  }

  bit(name: string, config: any) {
    this.parser.addStep(name, new BitParser({ ...config }));
    return this;
  }

  block(name: string, parser) {
    this.parser.addStep(name, parser);
    return this;
  }

  constBits(value, config?: Partial<BaseConfig>) {
    return this.bit('const', {
      length: value.length,
      type: 'const',
      ...config
    });
  }

  boolean(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 1, type: 'boolean', ...config });
  }

  bit1(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 1, ...config });
  }

  bit2(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 2, ...config });
  }

  bit3(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 3, ...config });
  }

  bit8(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 8, ...config });
  }

  bit32(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 32, ...config });
  }
  bit24(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 24, ...config });
  }

  object(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, { length: 1, ...config });
  }

  uInt16(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, {
      type: 'number',
      length: 16,
      converter: a => {
        return parseInt(a.slice(8) + a.slice(0, 8), 2);
      },
      ...config
    });
  }

  uInt24(name: string, config: any = {}) {
    return this.bit(name, {
      type: 'number',
      length: 24,
      converter: a => {
        return parseInt(a, 2);
      },
      ...config
    });
  }

  uInt32(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, {
      type: 'number',
      length: 32,
      converter: a => {
        return parseInt(a, 2);
      },
      ...config
    });
  }

  uInt32le(name: string, config?: Partial<BaseConfig>) {
    return this.uInt32(name, {
      converter: a => {
        return beToLe32(parseInt(a, 2));
      },
      ...config
    });
  }

  uInt8(name: string, config?: Partial<BaseConfig>) {
    return this.bit(name, {
      type: 'number',
      subtype: 'uint8',
      length: 8,
      converter: a => {
        return parseInt(a, 2);
      },
      ...config
    });
  }

  hex(name: string, config?: Partial<BaseConfig>) {
    if (typeof config.length === 'function') {
      // tslint:disable-next-line:no-debugger
      debugger;
      // TODO
    }

    return this.bit(name, {
      type: 'hex',
      converter: data => {
        return Array.from(data.match(/.{4}/g))
          .map(a => parseInt(a.toString(), 2))
          .map(a => a.toString(16))
          .join('');
      },
      ...config,
      length: config.length * 4
    });
  }

  read(reader, data: any = {}) {
    return this.parser.read(reader, data);
  }

  readOrdered(reader: BinaryReader, data: any = [], start = 0) {
    const v = this.parser.readOrdered(reader, data, start);

    return {
      start: start,
      ...v
    };
  }
}