-- Auto-generated protocol definition
-- DO NOT EDIT - This file is generated by Morel
local Protocol = {}
Protocol.name = "txse_feed"
Protocol.description = "txse_feed"
-- Enum definitions
Protocol.enums = {}
Protocol.enums.MarketHoursState = {
  [0] = "CLOSED_BEFORE_HOURS",
  [1] = "EARLY_SESSION",
  [2] = "REGULAR_SESSION",
  [3] = "AFTER_HOURS_SESSION",
  [4] = "CLOSED_AFTER_HOURS",
}
Protocol.enums.OperationalHaltReason = {
  [0] = "ADMINISTRATIVE",
}
Protocol.enums.RegulatoryHaltReason = {
  [0] = "REASON_NOT_AVAILABLE",
  [1] = "NEWS_PENDING",
  [2] = "NEWS_DISSEMINATION",
  [3] = "INFO_REQUESTED",
  [4] = "ORDER_IMBALANCE",
  [5] = "EXTRAORDINARY_MARKET_ACTIVITY",
  [6] = "LULD_PAUSE",
  [7] = "NON_COMPLIANCE",
  [8] = "FILINGS_NOT_CURRENT",
  [9] = "SEC_SUSPENSION",
  [10] = "REGULATORY_CONCERN",
  [11] = "SUB_PENNY_TRADING",
  [12] = "ETF",
  [13] = "IPO_NOT_TRADING",
  [14] = "CORPORATE_ACTION",
  [15] = "CIRCUIT_BREAKER_L1",
  [16] = "CIRCUIT_BREAKER_L2",
  [17] = "CIRCUIT_BREAKER_L3",
}
Protocol.enums.SessionTradingState = {
  [0] = "CLOSED",
  [1] = "TRADING",
  [2] = "HALTED",
}
Protocol.enums.ShortSaleRestrictionState = {
  [0] = "NONE",
  [1] = "ACTIVATED",
  [2] = "CONTINUED",
}
Protocol.enums.SymbolTradingState = {
  [1] = "TRADING",
  [2] = "HALTED",
}
-- Field definitions
-- Returns a function that creates Fields table given TXSE lib
Protocol.createFields = function(TXSE)
  local Fields = {}
  local Enums = Protocol.enums
  Fields["msgType"] = {
    length = 1,
    abbr = "txse_feed.msgType",
    name = "msgType",
    ftype = ftypes.CHAR,
    encoding = ENC_ASCII,
    value_map = {
      [97] = "AddOrder",
      [98] = "BreakTrade",
      [100] = "DeleteOrder",
      [101] = "ExecuteOrder",
      [105] = "TradingSessionStatus",
      [109] = "ModifySizeDown",
      [112] = "ExecuteOrderWithPrice",
      [114] = "ReplaceOrder",
      [115] = "DefineSymbol",
      [116] = "Trade",
      [121] = "SymbolStatus",
    },
  }
  Fields["com.txse.exchange.specs.shared.define.DefineSymbolBitFields"] = {
    length = 1,
    abbr = "txse_feed.defineSymbolBitFields",
    name = "defineSymbolBitFields",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.specs.shared.define.DefineSymbolBitFields",
    custom_decode = function(buffer, pinfo, tree)
      local numeric = buffer(0, 1):le_uint()
      tree:add(buffer, string.format("isTest: %d", TXSE.extract_bits(numeric, 0)))
      tree:add(buffer, string.format("reserved: %d", TXSE.extract_bits(numeric, 1, 7)))
    end,
  }
  Fields["execId"] = {
    length = 8,
    abbr = "txse_feed.execId",
    name = "execId",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.ExecId",
  }
  Fields["execPrice"] = {
    length = 8,
    abbr = "txse_feed.execPrice",
    name = "execPrice",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.avail.Price",
  }
  Fields["lotSize"] = {
    length = 4,
    abbr = "txse_feed.lotSize",
    name = "lotSize",
    ftype = ftypes.INT32,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.avail.Quantity",
  }
  Fields["marketHoursState"] = {
    length = 1,
    abbr = "txse_feed.marketHoursState",
    name = "marketHoursState",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.MarketHoursState",
    value_map = Enums.MarketHoursState,
  }
  Fields["matchingEngineId"] = {
    length = 1,
    abbr = "txse_feed.matchingEngineId",
    name = "matchingEngineId",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.avail.StreamId",
  }
  Fields["newOrderId"] = {
    length = 8,
    abbr = "txse_feed.newOrderId",
    name = "newOrderId",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.OrderId",
  }
  Fields["oldOrderId"] = {
    length = 8,
    abbr = "txse_feed.oldOrderId",
    name = "oldOrderId",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.OrderId",
  }
  Fields["operationalHaltReason"] = {
    length = 1,
    abbr = "txse_feed.operationalHaltReason",
    name = "operationalHaltReason",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.OperationalHaltReason",
    value_map = Enums.OperationalHaltReason,
  }
  Fields["com.txse.exchange.specs.feed.define.OrderBitFields"] = {
    length = 1,
    abbr = "txse_feed.orderBitFields",
    name = "orderBitFields",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.specs.feed.define.OrderBitFields",
    custom_decode = function(buffer, pinfo, tree)
      local numeric = buffer(0, 1):le_uint()
      tree:add(buffer, string.format("isBuy: %d", TXSE.extract_bits(numeric, 0)))
      tree:add(buffer, string.format("reserved: %d", TXSE.extract_bits(numeric, 1, 7)))
    end,
  }
  Fields["orderId"] = {
    length = 8,
    abbr = "txse_feed.orderId",
    name = "orderId",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.OrderId",
  }
  Fields["price"] = {
    length = 8,
    abbr = "txse_feed.price",
    name = "price",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.avail.Price",
  }
  Fields["qty"] = {
    length = 4,
    abbr = "txse_feed.qty",
    name = "qty",
    ftype = ftypes.INT32,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.avail.Quantity",
  }
  Fields["regulatoryHaltReason"] = {
    length = 1,
    abbr = "txse_feed.regulatoryHaltReason",
    name = "regulatoryHaltReason",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.RegulatoryHaltReason",
    value_map = Enums.RegulatoryHaltReason,
  }
  Fields["sessionTradingState"] = {
    length = 1,
    abbr = "txse_feed.sessionTradingState",
    name = "sessionTradingState",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.SessionTradingState",
    value_map = Enums.SessionTradingState,
  }
  Fields["shortSaleRestrictionState"] = {
    length = 1,
    abbr = "txse_feed.shortSaleRestrictionState",
    name = "shortSaleRestrictionState",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.ShortSaleRestrictionState",
    value_map = Enums.ShortSaleRestrictionState,
  }
  Fields["suffix"] = {
    length = 8,
    abbr = "txse_feed.suffix",
    name = "suffix",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.SymbolSuffix",
  }
  Fields["symbol"] = {
    length = 8,
    abbr = "txse_feed.symbol",
    name = "symbol",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.SymbolRoot",
  }
  Fields["symbolId"] = {
    length = 2,
    abbr = "txse_feed.symbolId",
    name = "symbolId",
    ftype = ftypes.INT16,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.exchange.SymbolId",
  }
  Fields["symbolTradingState"] = {
    length = 1,
    abbr = "txse_feed.symbolTradingState",
    name = "symbolTradingState",
    ftype = ftypes.INT8,
    encoding = ENC_NA,
    kotlin_type = "com.txse.exchange.SymbolTradingState",
    value_map = Enums.SymbolTradingState,
  }
  Fields["transactTime"] = {
    length = 8,
    abbr = "txse_feed.transactTime",
    name = "transactTime",
    ftype = ftypes.INT64,
    encoding = ENC_LITTLE_ENDIAN,
    kotlin_type = "com.txse.avail.TimeStamp",
  }
  Fields["symbolStatusPresence"] = {
    length = 1,
    abbr = "txse_feed.symbolStatusPresence",
    name = "symbolStatusPresence",
    ftype = ftypes.BYTES,
    encoding = ENC_NA,
    is_presence_field = true,
  }
  Fields["tradingSessionStatusPresence"] = {
    length = 1,
    abbr = "txse_feed.tradingSessionStatusPresence",
    name = "tradingSessionStatusPresence",
    ftype = ftypes.BYTES,
    encoding = ENC_NA,
    is_presence_field = true,
  }
  return Fields
end
-- Message definitions
Protocol.messages = {
  {
    name = "AddOrder",
    type = "a",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "orderId",
      "com.txse.exchange.specs.feed.define.OrderBitFields",
      "price",
      "qty",
    },
  },
  {
    name = "BreakTrade",
    type = "b",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "execId",
    },
  },
  {
    name = "DefineSymbol",
    type = "s",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "symbol",
      "suffix",
      "matchingEngineId",
      "com.txse.exchange.specs.shared.define.DefineSymbolBitFields",
      "lotSize",
    },
  },
  {
    name = "DeleteOrder",
    type = "d",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "orderId",
    },
  },
  {
    name = "ExecuteOrder",
    type = "e",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "orderId",
      "qty",
      "execId",
    },
  },
  {
    name = "ExecuteOrderWithPrice",
    type = "p",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "orderId",
      "qty",
      "execId",
      "execPrice",
    },
  },
  {
    name = "ModifySizeDown",
    type = "m",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "orderId",
      "qty",
    },
  },
  {
    name = "ReplaceOrder",
    type = "r",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "oldOrderId",
      "newOrderId",
      "price",
      "qty",
    },
  },
  {
    name = "SymbolStatus",
    type = "y",
    fields = {
      "msgType",
      "symbolStatusPresence",
      "transactTime",
      "symbolId",
      "symbolTradingState",
      "shortSaleRestrictionState",
    },
    presence_fields = {
      "operationalHaltReason",
      "regulatoryHaltReason",
    },
  },
  {
    name = "Trade",
    type = "t",
    fields = {
      "msgType",
      "transactTime",
      "symbolId",
      "price",
      "qty",
      "execId",
    },
  },
  {
    name = "TradingSessionStatus",
    type = "i",
    fields = {
      "msgType",
      "tradingSessionStatusPresence",
      "transactTime",
      "marketHoursState",
      "sessionTradingState",
    },
    presence_fields = {
      "operationalHaltReason",
      "regulatoryHaltReason",
    },
  },
}
-- Dissector setup
-- opts.payload_decoder: optional function(buffer, pinfo, tree_item) for trailing payload
Protocol.register = function(opts)
  local TXSE = require("txse-lib")
  local proto, messages = TXSE.Proto.new(TXSE.createSpec(Protocol, opts))
  function proto.dissector(buffer, pinfo, tree)
    local length = buffer:len()
    if length < 1 then
      return 0
    end
    local msg_type = buffer(0, 1):uint()
    local msg = messages.mapping[msg_type]
    if not msg then
      return 0
    end
    pinfo.cols.protocol = proto.name
    pinfo.cols.info = msg.name
    local subtree = tree:add(proto, buffer, msg.name)
    msg:parse(buffer, pinfo, subtree)
    return buffer:len()
  end
  return proto
end
return Protocol
