在Kaitai Struct的第一步中,我一直在尝试将BSON解析器作为一项练习。现在,解析BSON元素的.ksy代码如下所示:
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
您可能已经注意到,重复很多。每当一个人想要做其他元素类型时,就会有一个重复的
if
块。更糟糕的是,您基本上必须在每个此类字段中重复3次,即: - id: el_string # <= string!
type: bson_string # <= string!
if: el_type == bson_type::string # <= string!
我的目标语言是Java。在Kaitai之前,我只尝试过Preon,并且那里有以下子句:
@Choices(prefixSize = 8, alternatives = {
@Choice(condition = "prefix==0x01", type = FloatNamedElement.class),
@Choice(condition = "prefix==0x02", type = UTF8NamedElement.class)
}
private NamedElement elements;
在那里,您将根据“前缀”的值自动获得这两个元素。在开泰有可能吗?
最佳答案
好吧,您是对的,这个功能已经被请求了3到4次;)我为此使用filed an issue。
我不能同意Preon的实现,但是,这似乎仅限于我自己。您只能有一个“前缀”,它始终是整数,并且始终必须立即位于您选择的位置之前。
我想实现一些通用的switch
样式语句,类似这样:
- id: value
switch: code
cases:
string:
type: bson_string
document:
type: bson_document
boolean:
type: u1
int32:
type: s4
int64:
type: s8
你对那个怎么想的?
请注意,但是,就像使用Preon一样,您可能不会获得“适当的” OOP对象层次结构。这是因为Preon的类是手工制作的,您实际上可以执行公共的超类,并从中继承
FloatNamedElement
和UTF8NamedElement
,但是我现在想不出在当前KS模型中这样做的方法。