0

我正在解析一个长度编码的二进制流,并且正在尝试编译此代码。combinatorrent 代码(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?

4

1 回答 1

1

parser 的两个分支的第一个组件具有不同的类型,一个Jumbo分支是 a Parser FrameSize,另一个是 plain 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,所以我建议选择它)。

于 2011-10-26T20:12:53.340 回答