Copyright | (c) Leon Mergen, 2015 |
---|---|
License | MIT |
Maintainer | leon@solatis.com |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
Utility functions for running a parser against a socket, without the need of a bigger framework such as Pipes or Conduit.
WARNING: In certain situations while using the attoparsec string parser, it is possible that a network parser ends in a forever-blocking state, expecting more input. This is a side effect of the way attoparsec is written. I have written a thorough explanation on this issue, and how to avoid attoparsec returning a partial result when a different branch should be evaluated.
Documentation
type ParseC a = ByteString -> Result a Source
The parsing continuation form of a Data.Attoparsec parser. This is typically created by running the attoparsec "parse" function:
createParser = AttoParsec.parse myParser
:: (MonadIO m, MonadMask m, Show a) | |
=> Socket | Socket to read data from |
-> ParseC a | Initial parser state |
-> ParseC a | Continuation parser state |
-> m (ParseC a, [a]) | Next parser state with parsed values |
Consumes input from socket and attempts to parse as many objects from the socket as possible. Use this function only when you expect more than one parse operation to succeed.
The function is continuation based, so you must provide the next parser state in successing calls as follows:
doParse sock = do (p1, xs1) <- parseMany sock (AttoParsec.parse myParser) (AttoParsec.parse myParser) (_, xs2) <- parseMany sock (AttoParsec.parse myParser) p1 return (xs1 ++ xs2)
For more usage examples, see the test directory.
:: (MonadIO m, MonadMask m, Show a) | |
=> Socket | Socket to read data from |
-> ParseC a | Initial parser state |
-> m a | Parsed value |
Similar to parseMany, but assumes that there will only be enough data for a single succesful parse on the socket, and guarantees that exactly one item will be parsed.
Warning: In order to make this function work stable with pipelined data, we read in data one byte at a time, which causes many context switches and kernel syscalls, and furthermore causes a lot of separate calls to attoparsec. So only use if performance is not a consideration.
The is typically used as follows:
doParse sock = parseOne sock (AttoParsec.parse myParser)