Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PoC] Parse integer data #32

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

arthurschreiber
Copy link

This adds a very rough, unfinished implementation for parsing little- and big-endian integers, based on my question here: #31

See also these 2 PRs:

This only includes the code to generate JS output (for now), and has no tests at all. 🤷‍♂ I'll try to flesh this out if I can find some more time.

Example input

const { LLParse } = require('./lib/api.js');

const p = new LLParse('colmetadata');

p.property('i16', 'userType');
p.property('i8', 'flags');
p.property('i8', 'type');
p.property('i32', 'dataLength');
p.property('i8', 'scale');
p.property('i8', 'precision');
p.property('i8', 'schemaPresent');
p.property('i8', 'dbNameLength');
p.property('i8', 'owningSchemaLength');
p.property('i16', 'xmlSchemaCollectionLength');
p.property('i8', 'collationLength');
p.property('i8', 'typeNameLength');
p.property('i16', 'assemblyNameLength');

const onCollation = p.span(p.code.span('on_collation'));
const onDbName = p.span(p.code.span('on_db_name'));
const onOwningSchema = p.span(p.code.span('on_owning_schema'));
const onXmlSchemaCollection = p.span(p.code.span('on_xml_schema_collection'));
const onTypeName = p.span(p.code.span('on_type_name'));
const onAssemblyName = p.span(p.code.span('on_assembly_name'));

const done = p.pause(1, "done");

function readUInt8(field, next) {
  return p.uIntLE(field, 1).skipTo(next);
}

function readUInt16LE(field, next) {
  return p.uIntLE(field, 2).skipTo(next);
}

function readUInt32LE(field, next) {
  return p.uIntLE(field, 4).skipTo(next);
}

const dataLengthByte = readUInt8('dataLength', done);
const dataLengthShort = readUInt16LE('dataLength', done);
const dataLengthLong = readUInt32LE('dataLength', done);

const dataLengthByteWithScaleAndPrecision = readUInt8('dataLength', readUInt8('scale', readUInt8('precision', done)));

const collation = p.invoke(p.code.update('collationLength', 5)).
  otherwise(
    onCollation.start(
      p.consume('collationLength').otherwise(onCollation.end(done)
    )
  )
);

const dataLengthShortWithCollation = readUInt16LE('dataLength', collation);
const dataLengthLongWithCollation = readUInt32LE('dataLength', collation);

function readBVarChar(name, span, next) {
  return readUInt8(name + 'Length', span.start(p.consume(name + 'Length').otherwise(span.end(next))));
}

function readUsVarChar(name, span, next) {
  return readUInt16LE(name + 'Length', span.start(p.consume(name + 'Length').otherwise(span.end(next))));
}

const schema = readUInt8('schemaPresent', p.invoke(p.code.load('schemaPresent'), {
  0x01: readBVarChar('dbName', onDbName,
    readBVarChar('owningSchema', onOwningSchema,
      readUsVarChar('xmlSchemaCollection', onXmlSchemaCollection, done)
    )
  )
}).skipTo(done));

const udtInfo = readBVarChar('dbName', onDbName,
  readBVarChar('owningSchema', onOwningSchema,
    readBVarChar('typeName', onTypeName,
      readUsVarChar('assemblyName', onAssemblyName, done)
    )
  )
);

const dataLengthShortWithUDTInfo = readUInt16LE('dataLength', udtInfo);

const TYPES = {
  NULL: 0x1F,
  TINYINT: 0x30,
  BIT: 0x32,
  SMALLINT: 0x34,
  INT: 0x38,
  SMALLDATETIME: 0x3A,
  REAL: 0x3B,
  MONEY: 0x3C,
  DATETIME: 0x3D,
  FLOAT: 0x3E,
  SMALLMONEY: 0x7A,
  BIGINT: 0x7F,

  GUID: 0x24,
  INTN: 0x26,
  DECIMAL: 0x37,
  NUMERIC: 0x3F,
  BITN: 0x68,
  DECIMALN: 0x6A,
  NUMERICN: 0x6C,
  FLOATN: 0x6D,
  MONEYN: 0x6E,
  DATETIMEN: 0x6F,
  DATEN: 0x28,
  TIMEN: 0x29,
  DATETIME2N: 0x2A,
  DATETIMEOFFSETN: 0x2B,
  CHAR: 0x2F,
  VARCHAR: 0x27,
  BINARY: 0x2D,
  VARBINARY: 0x25,

  BIGVARBINARY: 0xA5,
  BIGVARCHAR: 0xA7,
  BIGBINARY: 0xAD,
  BIGCHAR: 0XAF,
  NVARCHAR: 0xE7,
  NCHAR: 0xEF,
  XML: 0xF1,
  UDT: 0xF0,

  TEXT: 0x23,
  IMAGE: 0x22,
  NTEXT: 0x63,
  VARIANT: 0x62
}

const colmetadata =
  readUInt32LE.call(null, 'userType',
    readUInt16LE('flags',
      readUInt8('type',
        p.invoke(p.code.load('type'), {
          [TYPES.NULL]: done,
          [TYPES.TINYINT]: done,
          [TYPES.SMALLINT]: done,
          [TYPES.INT]: done,
          [TYPES.BIGINT]: done,
          [TYPES.REAL]: done,
          [TYPES.FLOAT]: done,
          [TYPES.SMALLMONEY]: done,
          [TYPES.MONEY]: done,
          [TYPES.BIT]: done,
          [TYPES.SMALLDATETIME]: done,
          [TYPES.DATETIME]: done,

          [TYPES.INTN]: dataLengthByte,
          [TYPES.FLOATN]: dataLengthByte,
          [TYPES.MONEYN]: dataLengthByte,
          [TYPES.BITN]: dataLengthByte,
          [TYPES.GUID]: dataLengthByte,
          [TYPES.DATETIMEN]: dataLengthByte,
          [TYPES.TIMEN]: dataLengthByte,
          [TYPES.DATETIME2N]: dataLengthByte,
          [TYPES.DATETIMEOFFSETN]: dataLengthByte,

          [TYPES.VARIANT]: dataLengthLong,
          [TYPES.IMAGE]: dataLengthLong,

          [TYPES.VARCHAR]: dataLengthByte,
          [TYPES.CHAR]: dataLengthByte,
          [TYPES.VARBINARY]: dataLengthByte,
          [TYPES.BINARY]: dataLengthByte,

          [TYPES.BIGVARCHAR]: dataLengthShortWithCollation,
          [TYPES.BIGCHAR]: dataLengthShortWithCollation,
          [TYPES.BIGVARBINARY]: dataLengthShort,
          [TYPES.BIGBINARY]: dataLengthShort,

          [TYPES.NVARCHAR]: dataLengthShortWithCollation,
          [TYPES.NCHAR]: dataLengthShortWithCollation,

          [TYPES.TEXT]: dataLengthLongWithCollation,
          [TYPES.NTEXT]: dataLengthLongWithCollation,


          [TYPES.XML]: schema,

          [TYPES.NUMERICN]: dataLengthByteWithScaleAndPrecision,
          [TYPES.DECIMALN]: dataLengthByteWithScaleAndPrecision,
          [TYPES.NUMERIC]: dataLengthByteWithScaleAndPrecision,
          [TYPES.DECIMAL]: dataLengthByteWithScaleAndPrecision,

          [TYPES.UDT]: dataLengthShortWithUDTInfo
        }).otherwise(p.error(1, "Unknown type"))
      )
    )
  );

done.otherwise(colmetadata);

p.property('i8', 'field');

const artifacts = p.build(colmetadata, { js: { module: 'commonjs' } });
console.log(artifacts.js);  // buffer

Example output

'use strict';

module.exports = (binding) => {
  function unreachable() {
    throw new Error('Unreachable');
  }
  
  const S_ERROR = 0;
  const S_N_COLMETADATA__N_PAUSE = 1;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4 = 2;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3 = 3;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2 = 4;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE = 5;
  const S_N_COLMETADATA__N_SPAN_END_ON_COLLATION = 6;
  const S_N_COLMETADATA__N_CONSUME_COLLATIONLENGTH = 7;
  const S_N_COLMETADATA__N_SPAN_START_ON_COLLATION = 8;
  const S_N_COLMETADATA__N_INVOKE_UPDATE_COLLATIONLENGTH = 9;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4_1 = 10;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3_1 = 11;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2_1 = 12;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_1 = 13;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_8 = 14;
  const S_N_COLMETADATA__N_PRECISION_UINT_8 = 15;
  const S_N_COLMETADATA__N_SCALE_UINT_8 = 16;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_8_1 = 17;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2 = 18;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE = 19;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_1 = 20;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1 = 21;
  const S_N_COLMETADATA__N_SPAN_END_ON_ASSEMBLY_NAME = 22;
  const S_N_COLMETADATA__N_CONSUME_ASSEMBLYNAMELENGTH = 23;
  const S_N_COLMETADATA__N_SPAN_START_ON_ASSEMBLY_NAME = 24;
  const S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE_BYTE2 = 25;
  const S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE = 26;
  const S_N_COLMETADATA__N_SPAN_END_ON_TYPE_NAME = 27;
  const S_N_COLMETADATA__N_CONSUME_TYPENAMELENGTH = 28;
  const S_N_COLMETADATA__N_SPAN_START_ON_TYPE_NAME = 29;
  const S_N_COLMETADATA__N_TYPENAMELENGTH_UINT_8 = 30;
  const S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA = 31;
  const S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH = 32;
  const S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA = 33;
  const S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8 = 34;
  const S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME = 35;
  const S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH = 36;
  const S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME = 37;
  const S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8 = 38;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_2 = 39;
  const S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_2 = 40;
  const S_N_COLMETADATA__N_SPAN_END_ON_XML_SCHEMA_COLLECTION = 41;
  const S_N_COLMETADATA__N_CONSUME_XMLSCHEMACOLLECTIONLENGTH = 42;
  const S_N_COLMETADATA__N_SPAN_START_ON_XML_SCHEMA_COLLECTION = 43;
  const S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE_BYTE2 = 44;
  const S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE = 45;
  const S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA_1 = 46;
  const S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH_1 = 47;
  const S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA_1 = 48;
  const S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8_1 = 49;
  const S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME_1 = 50;
  const S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH_1 = 51;
  const S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME_1 = 52;
  const S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8_1 = 53;
  const S_N_COLMETADATA__N_INVOKE_LOAD_SCHEMAPRESENT = 54;
  const S_N_COLMETADATA__N_SCHEMAPRESENT_UINT_8 = 55;
  const S_N_COLMETADATA__N_ERROR = 56;
  const S_N_COLMETADATA__N_INVOKE_LOAD_TYPE = 57;
  const S_N_COLMETADATA__N_TYPE_UINT_8 = 58;
  const S_N_COLMETADATA__N_FLAGS_UINT_16_LE_BYTE2 = 59;
  const S_N_COLMETADATA__N_FLAGS_UINT_16_LE = 60;
  const S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE4 = 61;
  const S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE3 = 62;
  const S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE2 = 63;
  const S_N_COLMETADATA__N_USERTYPE_UINT_32_LE = 64;
  
  const on_db_name = binding.on_db_name;
  
  const on_owning_schema = binding.on_owning_schema;
  
  const on_xml_schema_collection = binding.on_xml_schema_collection;
  
  const on_type_name = binding.on_type_name;
  
  const on_assembly_name = binding.on_assembly_name;
  
  const on_collation = binding.on_collation;
  
  class Parser {
    constructor() {
      this._index = 0;
      this._current = S_N_COLMETADATA__N_USERTYPE_UINT_32_LE;
      this._status = 0;
      this.error = 0;
      this.reason = null;
      this.errorOff = 0;
      this.userType = 0;
      this.flags = 0;
      this.type = 0;
      this.dataLength = 0;
      this.scale = 0;
      this.precision = 0;
      this.schemaPresent = 0;
      this.dbNameLength = 0;
      this.owningSchemaLength = 0;
      this.xmlSchemaCollectionLength = 0;
      this.collationLength = 0;
      this.typeNameLength = 0;
      this.assemblyNameLength = 0;
      this.field = 0;
      this._spanOff0 = -1;
      this._spanCb0 = null;
    }
  
    _on_db_name(buf, off, offEnd) {
      return on_db_name(this, buf, off, offEnd);
    }
    
    _on_owning_schema(buf, off, offEnd) {
      return on_owning_schema(this, buf, off, offEnd);
    }
    
    _on_xml_schema_collection(buf, off, offEnd) {
      return on_xml_schema_collection(this, buf, off, offEnd);
    }
    
    _on_type_name(buf, off, offEnd) {
      return on_type_name(this, buf, off, offEnd);
    }
    
    _on_assembly_name(buf, off, offEnd) {
      return on_assembly_name(this, buf, off, offEnd);
    }
    
    _on_collation(buf, off, offEnd) {
      return on_collation(this, buf, off, offEnd);
    }
    
    _colmetadata__c_load_type(buf, off) {
      return this.type;
    }
    
    _colmetadata__c_update_collationLength(buf, off) {
      this.collationLength = 5;
      return 0;
    }
    
    _colmetadata__c_load_schemaPresent(buf, off) {
      return this.schemaPresent;
    }
    
    _run(current, buf, off) {
      let match;
      for (;;) {
        switch (current | 0) {
          case S_N_COLMETADATA__N_PAUSE: {
            this.error = 0x1;
            this.reason = "done";
            this.errorOff = off;
            this._current = S_N_COLMETADATA__N_USERTYPE_UINT_32_LE
            return S_ERROR;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4;
            }
            this.dataLength += buf[off] * 2 ** 24;
            off++;
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3;
            }
            this.dataLength += buf[off] * 2 ** 16;
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2;
            }
            this.dataLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_COLLATION: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_collation(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_PAUSE;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_COLLATIONLENGTH: {
            let avail = buf.length - off;
            const need = this.collationLength;
            if (avail >= need) {
              off += need;
              this.collationLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_COLLATION;
              continue;
            }
            
            this.collationLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_COLLATIONLENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_COLLATION: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_COLLATION;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_collation;
            current = S_N_COLMETADATA__N_CONSUME_COLLATIONLENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_INVOKE_UPDATE_COLLATIONLENGTH: {
            switch (this._colmetadata__c_update_collationLength(buf, off) | 0) {
              default:
                current = S_N_COLMETADATA__N_SPAN_START_ON_COLLATION;
                continue;
            }
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4_1;
            }
            this.dataLength += buf[off] * 2 ** 24;
            off++;
            current = S_N_COLMETADATA__N_INVOKE_UPDATE_COLLATIONLENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3_1;
            }
            this.dataLength += buf[off] * 2 ** 16;
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE4_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2_1;
            }
            this.dataLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE3_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_1;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_BYTE2_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_8;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_PRECISION_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_PRECISION_UINT_8;
            }
            this.precision = buf[off];
            off++;
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SCALE_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SCALE_UINT_8;
            }
            this.scale = buf[off];
            off++;
            current = S_N_COLMETADATA__N_PRECISION_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_8_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_8_1;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SCALE_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2;
            }
            this.dataLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_1;
            }
            this.dataLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_INVOKE_UPDATE_COLLATIONLENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_ASSEMBLY_NAME: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_assembly_name(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_PAUSE;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_ASSEMBLYNAMELENGTH: {
            let avail = buf.length - off;
            const need = this.assemblyNameLength;
            if (avail >= need) {
              off += need;
              this.assemblyNameLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_ASSEMBLY_NAME;
              continue;
            }
            
            this.assemblyNameLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_ASSEMBLYNAMELENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_ASSEMBLY_NAME: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_ASSEMBLY_NAME;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_assembly_name;
            current = S_N_COLMETADATA__N_CONSUME_ASSEMBLYNAMELENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE_BYTE2;
            }
            this.assemblyNameLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_ASSEMBLY_NAME;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE;
            }
            this.assemblyNameLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE_BYTE2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_TYPE_NAME: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_type_name(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_ASSEMBLYNAMELENGTH_UINT_16_LE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_TYPENAMELENGTH: {
            let avail = buf.length - off;
            const need = this.typeNameLength;
            if (avail >= need) {
              off += need;
              this.typeNameLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_TYPE_NAME;
              continue;
            }
            
            this.typeNameLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_TYPENAMELENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_TYPE_NAME: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_TYPE_NAME;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_type_name;
            current = S_N_COLMETADATA__N_CONSUME_TYPENAMELENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_TYPENAMELENGTH_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_TYPENAMELENGTH_UINT_8;
            }
            this.typeNameLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_TYPE_NAME;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_owning_schema(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_TYPENAMELENGTH_UINT_8;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_TYPENAMELENGTH_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH: {
            let avail = buf.length - off;
            const need = this.owningSchemaLength;
            if (avail >= need) {
              off += need;
              this.owningSchemaLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA;
              continue;
            }
            
            this.owningSchemaLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_owning_schema;
            current = S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8;
            }
            this.owningSchemaLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_db_name(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH: {
            let avail = buf.length - off;
            const need = this.dbNameLength;
            if (avail >= need) {
              off += need;
              this.dbNameLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME;
              continue;
            }
            
            this.dbNameLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_db_name;
            current = S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8;
            }
            this.dbNameLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_2;
            }
            this.dataLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_2;
            }
            this.dataLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_BYTE2_2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_XML_SCHEMA_COLLECTION: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_xml_schema_collection(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_PAUSE;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_PAUSE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_XMLSCHEMACOLLECTIONLENGTH: {
            let avail = buf.length - off;
            const need = this.xmlSchemaCollectionLength;
            if (avail >= need) {
              off += need;
              this.xmlSchemaCollectionLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_XML_SCHEMA_COLLECTION;
              continue;
            }
            
            this.xmlSchemaCollectionLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_XMLSCHEMACOLLECTIONLENGTH;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_XML_SCHEMA_COLLECTION: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_XML_SCHEMA_COLLECTION;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_xml_schema_collection;
            current = S_N_COLMETADATA__N_CONSUME_XMLSCHEMACOLLECTIONLENGTH;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE_BYTE2;
            }
            this.xmlSchemaCollectionLength += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_XML_SCHEMA_COLLECTION;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE;
            }
            this.xmlSchemaCollectionLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE_BYTE2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA_1: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_owning_schema(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_XMLSCHEMACOLLECTIONLENGTH_UINT_16_LE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH_1: {
            let avail = buf.length - off;
            const need = this.owningSchemaLength;
            if (avail >= need) {
              off += need;
              this.owningSchemaLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_OWNING_SCHEMA_1;
              continue;
            }
            
            this.owningSchemaLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH_1;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA_1;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_owning_schema;
            current = S_N_COLMETADATA__N_CONSUME_OWNINGSCHEMALENGTH_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8_1;
            }
            this.owningSchemaLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_OWNING_SCHEMA_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME_1: {
            const start = this._spanOff0;
            this._spanOff0 = -1;
            const err = this._on_db_name(buf, start, off) | 0;
            if (err !== 0) {
              this.error = err;
              this.errorOff = off;
              this._current = S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8_1;
              return S_ERROR;
            }
            current = S_N_COLMETADATA__N_OWNINGSCHEMALENGTH_UINT_8_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH_1: {
            let avail = buf.length - off;
            const need = this.dbNameLength;
            if (avail >= need) {
              off += need;
              this.dbNameLength = 0;
              current = S_N_COLMETADATA__N_SPAN_END_ON_DB_NAME_1;
              continue;
            }
            
            this.dbNameLength -= avail;
            return S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH_1;
            unreachable();
          }
          case S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME_1;
            }
            this._spanOff0 = off;
            this._spanCb0 = this._on_db_name;
            current = S_N_COLMETADATA__N_CONSUME_DBNAMELENGTH_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8_1: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8_1;
            }
            this.dbNameLength = buf[off];
            off++;
            current = S_N_COLMETADATA__N_SPAN_START_ON_DB_NAME_1;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_INVOKE_LOAD_SCHEMAPRESENT: {
            switch (this._colmetadata__c_load_schemaPresent(buf, off) | 0) {
              case 1:
                current = S_N_COLMETADATA__N_DBNAMELENGTH_UINT_8_1;
                continue;
              default:
                off++;
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
            }
            unreachable();
          }
          case S_N_COLMETADATA__N_SCHEMAPRESENT_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_SCHEMAPRESENT_UINT_8;
            }
            this.schemaPresent = buf[off];
            off++;
            current = S_N_COLMETADATA__N_INVOKE_LOAD_SCHEMAPRESENT;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_ERROR: {
            this.error = 0x1;
            this.reason = "Unknown type";
            this.errorOff = off;
            this._current = S_ERROR;
            return S_ERROR;
            unreachable();
          }
          case S_N_COLMETADATA__N_INVOKE_LOAD_TYPE: {
            switch (this._colmetadata__c_load_type(buf, off) | 0) {
              case 31:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 34:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE;
                continue;
              case 35:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_1;
                continue;
              case 36:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 37:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 38:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 39:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 41:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 42:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 43:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 45:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 47:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 48:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 50:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 52:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 55:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8_1;
                continue;
              case 56:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 58:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 59:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 60:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 61:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 62:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 63:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8_1;
                continue;
              case 98:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE;
                continue;
              case 99:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_32_LE_1;
                continue;
              case 104:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 106:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8_1;
                continue;
              case 108:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8_1;
                continue;
              case 109:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 110:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 111:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_8;
                continue;
              case 122:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 127:
                current = S_N_COLMETADATA__N_PAUSE;
                continue;
              case 165:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE;
                continue;
              case 167:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1;
                continue;
              case 173:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE;
                continue;
              case 175:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1;
                continue;
              case 231:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1;
                continue;
              case 239:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_1;
                continue;
              case 240:
                current = S_N_COLMETADATA__N_DATALENGTH_UINT_16_LE_2;
                continue;
              case 241:
                current = S_N_COLMETADATA__N_SCHEMAPRESENT_UINT_8;
                continue;
              default:
                current = S_N_COLMETADATA__N_ERROR;
                continue;
            }
            unreachable();
          }
          case S_N_COLMETADATA__N_TYPE_UINT_8: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_TYPE_UINT_8;
            }
            this.type = buf[off];
            off++;
            current = S_N_COLMETADATA__N_INVOKE_LOAD_TYPE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_FLAGS_UINT_16_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_FLAGS_UINT_16_LE_BYTE2;
            }
            this.flags += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_TYPE_UINT_8;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_FLAGS_UINT_16_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_FLAGS_UINT_16_LE;
            }
            this.flags = buf[off];
            off++;
            current = S_N_COLMETADATA__N_FLAGS_UINT_16_LE_BYTE2;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE4: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE4;
            }
            this.userType += buf[off] * 2 ** 24;
            off++;
            current = S_N_COLMETADATA__N_FLAGS_UINT_16_LE;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE3: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE3;
            }
            this.userType += buf[off] * 2 ** 16;
            off++;
            current = S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE4;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE2: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE2;
            }
            this.userType += buf[off] * 2 ** 8;
            off++;
            current = S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE3;
            continue;
            unreachable();
          }
          case S_N_COLMETADATA__N_USERTYPE_UINT_32_LE: {
            if (off === buf.length) {
              return S_N_COLMETADATA__N_USERTYPE_UINT_32_LE;
            }
            this.userType = buf[off];
            off++;
            current = S_N_COLMETADATA__N_USERTYPE_UINT_32_LE_BYTE2;
            continue;
            unreachable();
          }
        }
      }
      unreachable();
    }
  
    execute(buf) {
      // check lingering errors
      if (this.error !== 0) {
        return this.error;
      }
  
      // restart spans
      if (this._spanOff0 !== -1) {
        this._spanOff0 = 0;
      }
      
      const next = this._run(this._current, buf, 0);
      if (next === S_ERROR) {
        return this.error;
      }
      this._current = next;
  
      // execute spans
      if (this._spanOff0 !== -1) {
        const error = this._spanCb0(buf, this._spanOff0, buf.length) | 0;
        if (error !== 0) {
          this.error = error;
          this.errorOff = buf.length;
          return error;
        }
      }
      
      return 0;
    }
  }
  
  return Parser;
};

Copy link
Member

@indutny indutny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the direction of this! Great work!

const ctx = this.compilation;
const index = ctx.stateField(this.ref.field);

out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Let's use 1 << 7 instead of 2 ** 7. Mixing binary and floating point operators looks fishy.

I'm not sure that this line does what you want it to do, but I understand that this is work in progress. We can discuss it later.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is based on how Node.js Buffer also implements reading integers: https://github.com/nodejs/node/blob/f5512ff61ecb668c2f49b7c05d3227ef7aa5e85f/lib/internal/buffer.js#L416

I thought being consistent with core would make sense here? 🤔 I'm not sure what the pros or cons of switching to 1 << 7 would be. 🤷‍♂

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could also just inline the result of the multiplication / shifting by changing this to:

Suggested change
out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`)
out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & ${2 ** 7}) * 0x1fffffe;`);

What do you think?

}

case 1: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: same here, let's use << for binary operations.

}

case 2: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.

}

case 1: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.

}

case 1: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.

}

case 3: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 24;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.


switch (this.ref.byteOffset) {
case 0: {
out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.


switch (this.ref.byteOffset) {
case 0: {
out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.

}

case 1: {
out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: ditto.

}
}

private readUInt24BE(out: string[]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like it could be generalized a bit. There is no runtime savings from having separate methods for 16, 24, etc bits. These functions are executed only at compile time, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. My thinking was to keep these separated for readability - having all the logic in a single huge if/elseif/else statement made this really hard to understand. 🤷‍♂ Let's see how this looks like once all the other operations are in place too.

@arthurschreiber
Copy link
Author

@indutny I see that properties don't carry any sign information - is that a purposeful design decision in llparse? Does that mean that property access in C needs to be casted appropriately to not get the unsigned value? Am I missing something? 🤔

@indutny
Copy link
Member

indutny commented Jan 8, 2020

@arthurschreiber this is a design decision that was historically motivated by bitcode output. C has to cast fields if a signed access is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants