2011-10-26 44 views
0

我正在解析長度編碼的二進制流,我試圖讓這個代碼編譯。組合代碼(https://github.com/jlouis/combinatorrent/blob/master/src/Protocol/Wire.hs)對於讓我繼續前進非常有幫助,但現在我陷入困境。如何在return語句中使用frame_length?有條件的解析和鑄造Attoparsec

data FrameCont = FINAL | MORE | BADCONT 
    deriving (Show, Eq) 
frame_cont 0x00  = FINAL 
frame_cont 0x01  = MORE 
frame_cont otherwise = BADCONT 

data FrameSize = Small Word8 | Jumbo B.ByteString 
    deriving (Show) 

get_fc = do 
    raw_cont <- AP.anyWord8 
    guard((frame_cont raw_cont) /= BADCONT) AP.<?> "State must be either MORE or FINAL" 
    return raw_cont 

parser = do 
    frame_length <- AP.anyWord8 
    case frame_length of 
     0x255  -> return (Jumbo <$> AP.take 8, get_fc, AP.take (fromIntegral frame_length)) 
     otherwise -> return (Small otherwise, get_fc, AP.take (fromIntegral frame_length)) 

另外:我如何使用通過(AP.take 8)到Word64中?

+0

沒有更多的上下文,我們只能猜測。 「解析器」應具有哪種類型?它應該做什麼?如果我正確理解了最後一個問題:可以通過'foldl'(\ wb - >(shiftL w 8)。|將一個8字節ByteString(從AP.take 8獲得)轉換爲Word64。來自整體b)0。 unpack'。 –

+0

我已經提前並添加了更多上下文。我有一個封裝了Word8和ByteString的類型。我將來想要將字符串更改爲Word64。 – xrl

回答

1

解析器的兩個分支的第一個組件有不同的類型,Jumbo分支的一個是Parser FrameSize,另一個是一個普通的FrameSize。如果parser應具有Parser (Parser FrameSize, Parser Word8, Parser ByteString)類型,只需將第二個分支的第一個組件更改爲return (Small otherwise)即可。但是,您似乎更希望parser :: Parser (FrameSize, Word8, ByteString),因此您必須運行parser內的其他解析器。我認爲

parser = do 
    frame_length <- AP.anyWord8 
    frame_size <- case frame_length of 
        0xFF -> Jumbo <$> AP.take 8 -- 0xFF == 255, 0x255 == 597 
        flen -> return (Small flen) 
    fc <- get_fc 
    bs <- AP.take (fromIntegral frame_length) 
    return (frame_size, fc, bs) 

至少接近你想要的。

關於樣式的說明:混合camelCase和underscore_separated單詞,更好地解決一個問題(Haskell中的主要樣式是camelCase,所以我建議選擇它)。

+0

他確實有一個模式:大寫單詞使用CamelCase,小寫單詞use_underscores。這有點不尋常,但並不矛盾。 – Zopa

+0

是的,它是一致的。至少在他*代碼中。但通過使用camelCased庫函數,他得到了兩種風格的混合體。如果他不太喜歡下劃線,我認爲最好符合主導風格。 –