Kaitai Struct:通过一些字段实现容错
Kaitai Struct: pass some field to achieve fault tolerance
在 Kaitai Struct 中解析截断的日志时,有什么方法可以传递一些字段吗?
因为如果它读取一个字段(类型指定为枚举)但值不在其中,它将引发 NullPointer Exception.
所以我想问一下是否有任何方法可以像 python 库 Construct
中的 default: pass
属性那样实现
这是我的 ksy
文件:
meta:
id: btsnoop
endian: be
seq:
- id: header
type: header
- id: packets
type: packet
repeat: eos
types:
header:
seq:
- id: iden
size: 8
- id: version
type: u4
- id: datalink_type
type: u4
enum: linktype
packet:
seq:
- id: ori_len
type: u4
- id: include_len
type: u4
- id: pkt_flags
type: u4
- id: cumu_drop
type: u4
- id: timestamp
type: s8
- id: data
size: include_len
type: frame
frame:
seq:
- id: pkt_type
type: u1
enum: pkttype
- id: cmd
type: cmd
if: pkt_type == pkttype::cmd_pkt
- id: acl
type: acl
if: pkt_type == pkttype::acl_pkt
- id: evt
type: evt
if: pkt_type == pkttype::evt_pkt
cmd:
seq:
- id: opcode
type: u2le
- id: params_len
type: u1
- id: params
size: params_len
acl:
seq:
- id: handle
type: u2le
evt:
seq:
- id: status
type: u1
enum: status
- id: total_length
type: u1
- id: params
size-eos: true
enums: <-- I need to list all possible option in every enum?
linktype:
0x03E9: unencapsulated_hci
0x03EA: hci_uart
0x03EB: hci_bscp
0x03EC: hci_serial
pkttype:
1: cmd_pkt
2: acl_pkt
4: evt_pkt
status:
0x0D: complete_D
0x0E: complete_E
0xFF: vendor_specific
感谢回复:)
这里还有两个问题:)
正在解析部分/截断/损坏的数据
这里的主要问题是通常 Kaitai Struct 将 .ksy 编译成在 class 构造函数中进行实际解析的代码。这意味着如果出现问题,繁荣,你根本没有对象。在大多数用例中,这是期望的行为,因为它实际上允许您确保对象已完全初始化。问题通常是 EOFException
,当 format 想要读取下一个基元,但流中没有剩余数据,或者在一些更复杂的情况下,还有其他问题。
但是,如您所提到的,在某些用例中,"best effort" 解析会有所帮助 - 即您可以接受半填充的对象。另一个流行的用例是可视化工具:在那里显示 "best effort" 也很有帮助,因为最好向用户显示可视化的半解析结果(以帮助定位错误)而不是根本没有结果(然后离开猜测的用户)。
在 Kaitai Struct 中有一个简单的解决方案 - 您可以使用 --debug
选项编译 class。这样你会得到一个 class 对象创建和解析分离,解析只是对象的另一种方法 (void _read()
)。但是,这意味着您必须手动调用解析方法。例如,如果您的原始代码是:
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
System.out.println(b.packets.size());
用 --debug
编译后,您还需要执行额外的步骤:
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
b._read();
System.out.println(b.packets.size());
然后你可以把它包在一个 try/catch 块中,实际上即使在得到 IOException
:
之后继续处理
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
try {
b._read();
} catch (IOException e) {
System.out.println("warning: truncated packets");
}
System.out.println(b.packets.size());
虽然有一些问题:
--debug
尚未可用于 Java 目标,截至版本 v0.3;实际上,它现在甚至不在 public git 存储库中,不过我希望我会尽快推送它。
--debug
还做了一些额外的事情,比如写下每个属性的位置,这会带来相当苛刻的性能/内存损失。告诉我您是否需要一个开关来编译 "separate constructor/parsing" 功能而不需要其他 --debug
功能 - 我可以想到额外的开关来启用它。
- 如果您需要在传入数据包到达时对其进行连续解析,那么将它们全部存储在内存中并在每次更新时重新解析它们可能不是一个好主意。我们正在为那个考虑基于事件的解析模型,如果您对那个感兴趣,请告诉我。
缺少枚举值和 NPE
当前的 Java 实现将枚举读入类似
的内容
this.pet1 = Animal.byId(_io.readU4le());
其中Animal.byId翻译成:
private static final Map<Long, Animal> byId = new HashMap<Long, Animal>(3);
static {
for (Animal e : Animal.values())
byId.put(e.id(), e);
}
public static Animal byId(long id) { return byId.get(id); }
Java 当在地图中找不到任何值时,地图根据合同获得 returns null
。您应该能够将该 null 与某些东西(即其他枚举值)进行比较,并获得正确的 true 或 false。你能告诉我你到底在哪里有 NPE 问题吗,即你的代码、生成的代码和堆栈跟踪?
在 Kaitai Struct 中解析截断的日志时,有什么方法可以传递一些字段吗?
因为如果它读取一个字段(类型指定为枚举)但值不在其中,它将引发 NullPointer Exception.
所以我想问一下是否有任何方法可以像 python 库 Construct
default: pass
属性那样实现
这是我的 ksy
文件:
meta:
id: btsnoop
endian: be
seq:
- id: header
type: header
- id: packets
type: packet
repeat: eos
types:
header:
seq:
- id: iden
size: 8
- id: version
type: u4
- id: datalink_type
type: u4
enum: linktype
packet:
seq:
- id: ori_len
type: u4
- id: include_len
type: u4
- id: pkt_flags
type: u4
- id: cumu_drop
type: u4
- id: timestamp
type: s8
- id: data
size: include_len
type: frame
frame:
seq:
- id: pkt_type
type: u1
enum: pkttype
- id: cmd
type: cmd
if: pkt_type == pkttype::cmd_pkt
- id: acl
type: acl
if: pkt_type == pkttype::acl_pkt
- id: evt
type: evt
if: pkt_type == pkttype::evt_pkt
cmd:
seq:
- id: opcode
type: u2le
- id: params_len
type: u1
- id: params
size: params_len
acl:
seq:
- id: handle
type: u2le
evt:
seq:
- id: status
type: u1
enum: status
- id: total_length
type: u1
- id: params
size-eos: true
enums: <-- I need to list all possible option in every enum?
linktype:
0x03E9: unencapsulated_hci
0x03EA: hci_uart
0x03EB: hci_bscp
0x03EC: hci_serial
pkttype:
1: cmd_pkt
2: acl_pkt
4: evt_pkt
status:
0x0D: complete_D
0x0E: complete_E
0xFF: vendor_specific
感谢回复:)
这里还有两个问题:)
正在解析部分/截断/损坏的数据
这里的主要问题是通常 Kaitai Struct 将 .ksy 编译成在 class 构造函数中进行实际解析的代码。这意味着如果出现问题,繁荣,你根本没有对象。在大多数用例中,这是期望的行为,因为它实际上允许您确保对象已完全初始化。问题通常是 EOFException
,当 format 想要读取下一个基元,但流中没有剩余数据,或者在一些更复杂的情况下,还有其他问题。
但是,如您所提到的,在某些用例中,"best effort" 解析会有所帮助 - 即您可以接受半填充的对象。另一个流行的用例是可视化工具:在那里显示 "best effort" 也很有帮助,因为最好向用户显示可视化的半解析结果(以帮助定位错误)而不是根本没有结果(然后离开猜测的用户)。
在 Kaitai Struct 中有一个简单的解决方案 - 您可以使用 --debug
选项编译 class。这样你会得到一个 class 对象创建和解析分离,解析只是对象的另一种方法 (void _read()
)。但是,这意味着您必须手动调用解析方法。例如,如果您的原始代码是:
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
System.out.println(b.packets.size());
用 --debug
编译后,您还需要执行额外的步骤:
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
b._read();
System.out.println(b.packets.size());
然后你可以把它包在一个 try/catch 块中,实际上即使在得到 IOException
:
Btssnoop b = Btssnoop.fromFile("/path/to/file.bin");
try {
b._read();
} catch (IOException e) {
System.out.println("warning: truncated packets");
}
System.out.println(b.packets.size());
虽然有一些问题:
--debug
尚未可用于 Java 目标,截至版本 v0.3;实际上,它现在甚至不在 public git 存储库中,不过我希望我会尽快推送它。--debug
还做了一些额外的事情,比如写下每个属性的位置,这会带来相当苛刻的性能/内存损失。告诉我您是否需要一个开关来编译 "separate constructor/parsing" 功能而不需要其他--debug
功能 - 我可以想到额外的开关来启用它。- 如果您需要在传入数据包到达时对其进行连续解析,那么将它们全部存储在内存中并在每次更新时重新解析它们可能不是一个好主意。我们正在为那个考虑基于事件的解析模型,如果您对那个感兴趣,请告诉我。
缺少枚举值和 NPE
当前的 Java 实现将枚举读入类似
的内容this.pet1 = Animal.byId(_io.readU4le());
其中Animal.byId翻译成:
private static final Map<Long, Animal> byId = new HashMap<Long, Animal>(3);
static {
for (Animal e : Animal.values())
byId.put(e.id(), e);
}
public static Animal byId(long id) { return byId.get(id); }
Java 当在地图中找不到任何值时,地图根据合同获得 returns null
。您应该能够将该 null 与某些东西(即其他枚举值)进行比较,并获得正确的 true 或 false。你能告诉我你到底在哪里有 NPE 问题吗,即你的代码、生成的代码和堆栈跟踪?