2011-12-30 36 views
3

我試圖用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完全正常,但ResultResponsePayloadCodec不再具有訪問權限字節用於前綴識別。

我的第一個想法是編寫自定義Codec<ResponsePacket>,並在裏面解碼我可以讀取第一個字節,並根據它的值我可以實例化新的編解碼器來解析緩衝區的其餘部分。

在這種情況下的問題是,我不會有關於包的總大小(nn),這有時在表達式中有用的信息。 此外,它看起來像其他結構的行爲是這樣的(第一個字節決定的類型),這將需要手寫很多代碼。

我希望有人能給我一個更清潔的解決方案。

回答

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

這樣你就可以在地獄表達式引用fieldNotPrefix作爲outer.fieldNotPrefix

+0

這樣我就不必存取權限fieldNotPrefix字節ResultsResponsePacketPayload,請仔細閱讀第一僞代碼。 – 2012-01-02 00:03:46

+0

我認爲sakfa說你可以通過使ResultResponsePacketPayload和ResponsePacket的所有子類內部類訪問fieldNotPrefix,然後如果你需要訪問fieldNotPrefix屬性,請從這些內部引用它'ResponsePacket.this.fieldNotPrefix'類。 – 2012-01-25 07:22:48

相關問題