kaitai-io / kaitai_struct

Kaitai Struct: declarative language to generate binary data parsers in C++ / C# / Go / Java / JavaScript / Lua / Nim / Perl / PHP / Python / Ruby
https://kaitai.io
3.96k stars 192 forks source link

Signaling errors in switch constructs #208

Open cyco opened 7 years ago

cyco commented 7 years ago

The switch type operation provides a default case that falls back to raw bytes if none of the cases match. While this is quite useful in combination with a size attribute to skip over unknown message types during development, a complete definition of a binary structure might want to signal an error for unknown types instead.

Workaround

Currently, an error can be enforced by adding an error type whose contents are unlikely to be encountered in real world situations.

  message:
    seq:
      - id: rec_type
        type: u4
      - id: rec_len
        type: u4
      - id: content
        type:
          switch-on: rec_type
          cases:
             1: handshake
             ...
             _: unknown_type_error
  unknown_type_error:
    seq:
      - id: message
        contents: "Unknown record type"

Possible solutions:

GreyCat commented 7 years ago

Searching Gitter archives, I've found that @DarkDimius was definitely interested in this issue previously, and probably @mickdekkers as well.

KOLANICH commented 7 years ago

in #81 I have proposed the syntax

throw: #```throw``` block is proposed to be an ```instances``` block bound to the generated exception object but with one-time (at the time of creation) access to all the local variables.
  if: checksum_checksum_type(....) != expected_value
  result: # the member name in exception object
    type: u1 # the type of member
    enum: error # the values here are from the ```error``` enum. 
    value: 'error::it_happened_again' # the value set to a member. Essentially it is the same that a ```value``` in instances, but we should be able to use visible variables here.
........
enums:
  error:
    1: it_happenned_again
    2: that_happenned_again

it is easily generalized to cases

cases:
  _ :
    throw:
      result:
        value: "oh no!" #here the value is a string
mickdekkers commented 7 years ago

@GreyCat thanks for the ping :)

I think an _error type with error message parameter would be a great solution here.

Semantically, an _error type in the default case would do the same thing as an error attribute, and it could be used anywhere types are used, so it's not just bound to switch/case constructs.