datatype as parameter in kaitai (create generic kaitai type)

194 Views Asked by At

let's say I have the following two types:

types:
  arrayf4:
    params:
      - id: size
        type: u4
    seq:
      - id: member
        type: f4
        repeat: expr
        repeat-expr: size
  arrays2:
    params:
      - id: size
        type: u4
    seq:
      - id: member
        type: s2
        repeat: expr
        repeat-expr: size

is it possible to implement a generic type in kaitai as follows? (this example below does not compile in kaitai Web IDE). This must be able to work not only with simple types like s2 or f4 but also with user-defined types.

types:
  generic_array:
    params:
      - id: size
        type: u4
      - id: dtype
        type: strz
    seq:
      - id: member
        type: dtype
        repeat: expr
        repeat-expr: size
1

There are 1 best solutions below

0
Serhii On

As understood from this thread on GitHub, there is no generics in kaitai as of time when this answer had been posted.

I was able to find a workaround for myself - unfortunately, the workaround still requires a lot unnecessary effort to maintain. However, in my case, it still makes my kaitai code cleaner, so I am posting this solution here, in case it might be helpful for someone in a similar situation.

My generic type is defined as follows:

ptr:
    params:
      - id: dtype
        type: str
    seq:
      - id: offset
        type: u4
    instances:
      data:
        pos: offset
        type:
          switch-on: dtype
          cases:
            '"material"': material
            '"node"': node
            '"animation"': animation
            _: unknown_type

In code this type is used as follows:

seq:
  - id: material
    type: ptr('material')

Pros.

  1. The code using the ptr type becomes much cleaner. I have a lot of pointers of this type in the binary format I am parsing, so this has made my code immediately a ton more readable.
  2. The generated code (python, in my case) is truly generic. You always get the same Ptr class for your object, and the data inside may be of any type defined, in my case material, node, or animation, so at the end it has exactly the effect I was aiming for.

Cons.

  1. Obviously, you have to manually add types which are accepted by this generic type - in the switch-on clause, otherwise by default it will be set to an unknown type which is simply defined as an empty dummy which does not read any bytes. If you have several generic types, this scales respectively. I initially thought about writing a pre-processing routine but in my case it is easier to maintain this manually.
  2. Secondly, nested generic types won't work. For example, ptr('other_generic(some_type)'), of course, won't work.