2011-10-26 36 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库函数,他得到了两种风格的混合体。如果他不太喜欢下划线,我认为最好符合主导风格。 –