Search code examples
kaitai-struct

Referencing enums in external file in Kaitai Struct


I'd like to have a Kaitai Struct ksy file which references some enums and types in different external files. In the external files there I'd like to have only subtypes and enums definitions.

This is the test file (test.ksy) that references the external types:

meta:
  id: test
  imports:
    - rowing
  endian: be

seq:
  - id: system_id
    type: u1
  - id: data
    type:
      switch-on: system_id
      cases:
        rowing_messages::position: rowing::rowing_position_message

and this is the file (rowing.ksy) including the external types:

meta:
  id: rowing
  endian: be

enums:
  rowing_messages:
    0x10: position
    0x12: meter_per_stroke

types:
  rowing_position_message:
    seq:
      - id: id
        type: u1
      - id: timestamp
        type: u4

The compiler complains:

test: /seq/1/type/cases/EnumByLabel(identifier(rowing_messages),identifier(position)): unable to find enum 'rowing_messages', searching from test

According to my tests it seems that I can reference the external rowing_position_message type with prefix rowing:: but I cannot do the same for enums. If I do it like rowing::rowing_messages::position the compiler complains:

/seq/1/cases/rowing::rowing_messages::position: parsing expression 'rowing::rowing_messages::position' failed on 1:24, expected "or" | CharsWhile(Set( , n)) | "\\\n" | End

Thank in advance for any ideas.


Solution

  • Prepending rowing:: is the correct behavior here, as there is no way for a compiler to reference enum declared in the external class except for that.

    Also, you'll need to declare system_id as enum, not just an integer, by adding

    enum: 'rowing::rowing_messages'
    

    This issue was resolved in relatively modern compiler (i.e. >0.8, any modern 0.9 unstable snapshot should work), so this should work:

      - id: system_id
        type: u1
        enum: 'rowing::rowing_messages'
      - id: data
        type:
          switch-on: system_id
          cases:
            'rowing::rowing_messages::position': 'rowing::rowing_position_message'
    

    For another option possible with .to_i on enums (in theory, you'd rather not use that in practice), please see more in-depth explanation at https://github.com/kaitai-io/kaitai_struct/issues/643.