我正在解析长度编码的二进制流,我正在尝试编译这段代码。组合代码(https://github.com/jlouis/combinatorrent/blob/master/src/Protocol/Wire.hs)非常有助于让我继续前进,但现在我被卡住了。如何在return语句中使用frame_length?
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))
另外:如何将pass(AP.take 8)用于Word64?
答案 0 :(得分: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,所以我建议选择它。)