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
。
我正在尝试用 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
。