管道解析器过早中断

时间:2017-08-24 23:21:58

标签: haskell conduit attoparsec

我正在开发一个程序,我需要从USB连接中解析数据并将其写入循环缓冲区。

我一直遇到的问题是解析器没有消耗输入。我是否需要使用其他运算符将解析器管道连接到ByteString s?

的流

如果删除两个'过滤器'dropCdropWhileC,解析器会消耗一些输入但是会失败,因为前几个数据块都是垃圾。

显然,我的图书馆工作方式的心理模型是以某种方式关闭的(我之前从未使用过它)。

我还想知道conduitParser是否将空字符串视为EOF标记,与attoparsec自己的parseWith一样。

-- |
sourcePort :: SerialPort -> Producer IO ByteString
sourcePort port = repeatMC (recv port 16)


-- |
parseSerialStream :: (Vector v (Int, Int)) => RingBuffer v (Int, Int) -> SerialPort -> IO () -- ConduitM a c IO ()
parseSerialStream buffer port = sourcePort port
                             .| dropC 4
                             .| dropWhileC B.null
                             .| conduitParser (parseMeasurement <* endOfLine)
                             $$ mapM_C (\item -> print item >> RB.append (snd item) buffer)

1 个答案:

答案 0 :(得分:2)

@danidiaz在评论中解释dropC et.al.不要产生任何值,这就是为什么你必须使用monadic组合而不是管道(.|)。

对于偶然发现此问题的任何人,请参阅this answer了解详情。

此代码按预期工作:

parseSerialStream :: RingBuffer VU.Vector (Int, Int) -> SerialPort -> IO () -- ConduitM a c IO ()
parseSerialStream buffer port = sourcePort port
                             .| (dropC 4
                             >> dropWhileC B.null
                             >> conduitParser (parseMeasurement <* endOfLine))
                             $$ mapM_C (\item -> RB.append (snd item) buffer)

我喜欢管道看起来如何。哦,好吧......