Kaitai (Kasya) - 可选属性

Kaitai (KSY) - optional attribute

我正在尝试用 Kaitai 语言(.ksy 文件)描述 SSH 协议。 最开始有协议版本交换,格式如下:

SSH-protoversion-softwareversion SP comments CR LF

其中 SP comments 是可选的。 AFAIK,没有办法将属性描述为完全可选的,只能通过 if 条件。有谁知道如何在 Kaitai 中描述这种关系,以便解析器也接受这种格式:SSH-protoversion-softwareversion CR LF?

谢谢

Kaitai Struct 并不是被设计成传统意义上的语法(即映射到 regular language, context-free grammar, BNF 或类似的东西)。传统语法有 "this element being optional" 或 "this element can be repeated multiple times" 的概念,但 KS 的工作方式相反:它甚至没有试图解决 歧义 问题,而是建立在事实上,所有二进制格式都设计是明确的。

因此,每当您遇到 "optional element" 或 "repeated element" 之类的东西而没有任何进一步的上下文时,请停下来考虑一下 Kaitai Struct 是否是完成该任务的正确工具,它是不是实际上是您要解析的二进制格式。例如,理论上可以使用 KS 解析 JSON 或 XML 或 YAML 之类的内容,但结果不会有太大用处。

也就是说,在这种特殊情况下,完全可以使用 Kaitai Struct,您只需要考虑现实生活中的二进制解析器将如何处理它。根据我的理解,现实生活中的解析器会读取整行直到 CR 字节,然后会再次尝试解释该行的内容。您可以使用类似的东西在 KS 中对其进行建模:

seq:
  - id: line
    terminator: 0xd # CR
    type: version_line
    # ^^^ this creates a substream with all bytes up to CR byte
  - id: reserved_lf
    contents: [0xa]
types:
  version_line:
    seq:
      - id: magic
        contents: 'SSH-'
      - id: proto_version
        type: str
        terminator: 0x2d # '-'
      - id: software_version
        type: str
        terminator: 0x20 # ' '
        eos-error: false
        # ^^^ if we don't find that space and will just hit end of stream, that's fine
      - id: comments
        type: str
        size-eos: true 
        # ^^^ if we still have some data in the stream, that's all comment

如果你想得到 null 而不是评论的空字符串,当它们不包括在内时,只需为 comments 属性添加额外的 if: not _io.eof