I'm parsing a length-encoded binary stream and I'm trying to get this code compiling. The combinatorrent code ( https://github.com/jlouis/combinatorrent/blob/master/src/Protocol/Wire.hs ) was very helpful to get me moving along but now I'm stuck. How do I use the frame_length in the return statement?
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))
Also: how do I use pass (AP.take 8) into a Word64?
The first components of the two branches of parser have different types, the
Jumbo
branch's is aParser FrameSize
, the other a plainFrameSize
. Ifparser
should have the typeParser (Parser FrameSize, Parser Word8, Parser ByteString)
, simply change the first component of the second branch toreturn (Small otherwise)
. However, it seems more likely that you wantparser :: Parser (FrameSize, Word8, ByteString)
, so you have to run the other parsers insideparser
. I thinkis at least close to what you want.
A note on style: You mix camelCase and underscore_separated words, better settle for one (the predominant style in Haskell is camelCase, so I advise choosing that).