如何根据第一个字节解析不同的数据包类型

时间:2011-12-30 16:20:15

标签: java buffer preon

我正在尝试使用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")
        }))

它对OkResponsePayloadErrorResponsePayload完全正常,但ResultResponsePayload Codec不再具有对用于前缀识别的第一个字节的访问权限。

我的第一个想法是编写自定义Codec<ResponsePacket>,在内部解码中,我可以读取第一个字节,并根据它的值,我可以实例化新的编解码器来解析其余的缓冲区。

在这种情况下的问题是我不会有关于包的总大小(nn)的信息,这在表达式中有时是有用的。 此外,它看起来还有其他类似行为的结构(第一个字节决定了类型),这需要大量手工编写的代码。

我希望有人能给我一个更清洁的解决方案。

1 个答案:

答案 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