3

Doing my first steps in Kaitai Struct, I've been trying to do BSON parser as an excercise. My .ksy code that parses BSON element now looks like that:

  element:
    seq:
      - id: el_type
        type: u1
        enum: bson_type
      - id: el_name
        type: strz
        encoding: UTF-8
        if: el_type != bson_type::end_of_document
      - id: el_string
        type: bson_string
        if: el_type == bson_type::string
      - id: el_document
        type: bson_document
        if: el_type == bson_type::document
      - id: el_boolean
        type: u1
        if: el_type == bson_type::boolean
      - id: el_int32
        type: s4
        if: el_type == bson_type::int32
      - id: el_int64
        type: s4
        if: el_type == bson_type::int64
enums:
  bson_type:
    0: end_of_document
    1: double
    2: string
    3: document
    8: boolean
    0x10: int32
    0x12: int64

As you might have noticed, there's lots of repetition. One just have go duplicate if block every time one wants to do additional element type. Even worse, you basically have to duplicate stuff 3 times in every such field, i.e.:

  - id: el_string                    # <= string!
    type: bson_string                # <= string!
    if: el_type == bson_type::string # <= string!

My target language is Java. Before Kaitai, I've only tried Preon, and there we had clauses such as:

@Choices(prefixSize = 8, alternatives = {
    @Choice(condition = "prefix==0x01", type = FloatNamedElement.class),
    @Choice(condition = "prefix==0x02", type = UTF8NamedElement.class)
}
private NamedElement elements;

There you automatically get these two elements based on value of "prefix". Is it possible to do it in Kaitai?

1 Answers1

2

Well, you're right, and this feature was requested like 3 or 4 times already ;) I've filed an issue for that.

I can't agree on Preon's implementation, though, it seems very limited to me. You can have only a single "prefix", it is always integer, and it always must immediately preceed your point of choice.

I want to implement a little more generic switch style statement, something like that:

  - id: value
    switch: code
    cases:
      string:
        type: bson_string
      document:
        type: bson_document
      boolean:
        type: u1
      int32:
        type: s4
      int64:
        type: s8

What do you think of that?

Note that chances are that you won't be get the "proper" OOP object hierarchy, though, as you're getting with Preon. This is because Preon's classes are made by hand and you can actually do the common superclass and inherit both FloatNamedElement and UTF8NamedElement from it, but I can't think of a method to do so in current KS model now.

GreyCat
  • 16,622
  • 18
  • 74
  • 112
  • Interestingly, Preon is everything but limited, unless you're considering the codecs it's shipping by default. Extensibility is actually one of the key reasons why Preon was created, because none of the existing frameworks was extensible enough to fit all the use cases we were running into. Whatever problem you are trying to tackle, I'm pretty convinced you can extend Preon by adding a `Codec`, `CodecFactory` and perhaps some annotations to make it possible. – Wilfred Springer Aug 23 '17 at 09:53
  • Hi there, @WilfredSpringer, nice to meet you! As far as I understand, writing one's own `Codec` and similar classes in Preon technically moves it from "declarative" land into "imperative" land, as you literally write code which reads/writes the stream by hand. That was my only point here, calling Preon "limited". I'm sorry if that offended you, no offence was meant. Meanwhile, a lot of time passed since this question was asked, Kaitai Struct got type switching implemented out of the box. – GreyCat Aug 23 '17 at 13:40
  • No worries, not offended in any way. ;-) I guess Preon allows you to extend it's declarative abilities. Create new versions of Preon by implementing a single interface, allowing future users to leverage that new capability in a declarative way only. – Wilfred Springer Aug 25 '17 at 09:49