Как анализировать разные типы пакетов в зависимости от первого байта - PullRequest
3 голосов
/ 30 декабря 2011

Я пытаюсь проанализировать пакеты результата mysql, используя preon. Пакет выглядит так:

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), который иногда полезен в выражениях. Кроме того, похоже, что существуют другие структуры, которые ведут себя подобным образом (первый байт определяет тип), но для этого потребуется много кода, написанного вручную.

Надеюсь, кто-нибудь покажет мне более чистое решение.

1 Ответ

2 голосов
/ 02 января 2012

Тогда не используйте префикс, у вас есть весь контекст преобразователя в доступном условии.

@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")
    }))

Таким образом, вы сможете ссылаться на fieldNotPrefix в выражениях неопределенности как external.fieldNotPrefix

...