我正在尝试使用preon解析mysql结果包。数据包看起来像这样:
nn xx yy yy yy zz zz zz
我像这样解析它
class ResponsePacket {
@BoundNumber(size="1")
byte sizeOfThePacket;
/*
if(xx==00)
packet = OkResponsePayload(yy yy zz zz zz)
elseif(xx==ff)
packet = ErrorResponsePayload(yy yy zz zz zz)
else
packet = ResultResponsePayload(xx yy yy zz zz zz)
*/
PacketPayload packet;
}
我尝试使用@BoundObject
这样的注释:
@BoundObject( selectFrom = @Choices(prefixSize = 8,
defaultType=ResultsResponsePacketPayload.class,
alternatives={
@Choice(type=OkResponsePacketPayload.class, condition="prefix==0"),
@Choice(type=ErrorResponsePacketPayload.class, condition="prefix==255")
}))
它对OkResponsePayload
和ErrorResponsePayload
完全正常,但ResultResponsePayload
Codec
不再具有对用于前缀识别的第一个字节的访问权限。
我的第一个想法是编写自定义Codec<ResponsePacket>
,在内部解码中,我可以读取第一个字节,并根据它的值,我可以实例化新的编解码器来解析其余的缓冲区。
在这种情况下的问题是我不会有关于包的总大小(nn
)的信息,这在表达式中有时是有用的。
此外,它看起来还有其他类似行为的结构(第一个字节决定了类型),这需要大量手工编写的代码。
我希望有人能给我一个更清洁的解决方案。
答案 0 :(得分:2)
然后不要使用前缀,你有条件可用的整个解析器上下文。
@BoundNumber(size = "8")
public int fieldNotPrefix;
@BoundObject( selectFrom = @Choices(
defaultType=ResultsResponsePacketPayload.class,
alternatives={
@Choice(type=OkResponsePacketPayload.class, condition="fieldNotPrefix==0"),
@Choice(type=ErrorResponsePacketPayload.class, condition="fieldNotPrefix==255")
}))
这样你就可以在limbo表达式中引用fieldNotPrefix作为outer.fieldNotPrefix