conduit-extra 1.1.17 → 1.2.0
raw patch · 4 files changed
+55/−37 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Conduit.Attoparsec: [posOffset] :: Position -> {-# UNPACK #-} !Int
- Data.Conduit.Attoparsec: Position :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Position
+ Data.Conduit.Attoparsec: Position :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Position
Files
- ChangeLog.md +6/−0
- Data/Conduit/Attoparsec.hs +19/−14
- conduit-extra.cabal +1/−1
- test/Data/Conduit/AttoparsecSpec.hs +29/−22
ChangeLog.md view
@@ -1,3 +1,9 @@+## 1.2.0++* Added the `posOffset` field to the+ `Data.Conduit.Attoparsec.Position` data type+ [#331](https://github.com/snoyberg/conduit/issues/331).+ ## 1.1.17 * Speed up `sinkHandle` by not flushing after every output operation.
Data/Conduit/Attoparsec.hs view
@@ -53,11 +53,13 @@ data Position = Position { posLine :: {-# UNPACK #-} !Int , posCol :: {-# UNPACK #-} !Int+ , posOffset :: {-# UNPACK #-} !Int+ -- ^ @since 1.2.0 } deriving (Eq, Ord) instance Show Position where- show (Position l c) = show l ++ ':' : show c+ show (Position l c off) = show l ++ ':' : show c ++ " (" ++ show off ++ ")" data PositionRange = PositionRange { posRangeStart :: {-# UNPACK #-} !Position@@ -88,10 +90,11 @@ empty = B.empty isNull = B.null notEmpty = filter (not . B.null)- getLinesCols = B.foldl' f (Position 0 0)+ getLinesCols = B.foldl' f (Position 0 0 0) where- f (Position l c) ch | ch == 10 = Position (l + 1) 0- | otherwise = Position l (c + 1)+ f (Position l c o) ch+ | ch == 10 = Position (l + 1) 0 (o + 1)+ | otherwise = Position l (c + 1) (o + 1) stripFromEnd b1 b2 = B.take (B.length b1 - B.length b2) b1 instance AttoparsecInput T.Text where@@ -100,10 +103,11 @@ empty = T.empty isNull = T.null notEmpty = filter (not . T.null)- getLinesCols = T.foldl' f (Position 0 0)+ getLinesCols = T.foldl' f (Position 0 0 0) where- f (Position l c) ch | ch == '\n' = Position (l + 1) 0- | otherwise = Position l (c + 1)+ f (Position l c o) ch+ | ch == '\n' = Position (l + 1) 0 (o + 1)+ | otherwise = Position l (c + 1) (o + 1) stripFromEnd (TI.Text arr1 off1 len1) (TI.Text _ _ len2) = TI.text arr1 off1 (len1 - len2) @@ -114,14 +118,14 @@ -- -- Since 0.5.0 sinkParser :: (AttoparsecInput a, MonadThrow m) => A.Parser a b -> Consumer a m b-sinkParser = fmap snd . sinkParserPosErr (Position 1 1)+sinkParser = fmap snd . sinkParserPosErr (Position 1 1 0) -- | Same as 'sinkParser', but we return an 'Either' type instead -- of raising an exception. -- -- Since 1.1.5 sinkParserEither :: (AttoparsecInput a, Monad m) => A.Parser a b -> Consumer a m (Either ParseError b)-sinkParserEither = (fmap.fmap) snd . sinkParserPos (Position 1 1)+sinkParserEither = (fmap.fmap) snd . sinkParserPos (Position 1 1 0) -- | Consume a stream of parsed tokens, returning both the token and@@ -131,7 +135,7 @@ -- Since 0.5.0 conduitParser :: (AttoparsecInput a, MonadThrow m) => A.Parser a b -> Conduit a m (PositionRange, b) conduitParser parser =- conduit $ Position 1 1+ conduit $ Position 1 1 0 where conduit !pos = await >>= maybe (return ()) go where@@ -158,7 +162,7 @@ => A.Parser a b -> Conduit a m (Either ParseError (PositionRange, b)) conduitParserEither parser =- conduit $ Position 1 1+ conduit $ Position 1 1 0 where conduit !pos = await >>= maybe (return ()) go where@@ -232,10 +236,11 @@ pos' = addLinesCols prev pos addLinesCols :: AttoparsecInput a => a -> Position -> Position- addLinesCols x (Position lines cols) =- lines' `seq` cols' `seq` Position lines' cols'+ addLinesCols x (Position lines cols off) =+ lines' `seq` cols' `seq` off' `seq` Position lines' cols' off' where- Position dlines dcols = getLinesCols x+ Position dlines dcols doff = getLinesCols x lines' = lines + dlines cols' = (if dlines > 0 then 1 else cols) + dcols+ off' = off + doff {-# INLINE sinkParserPos #-}
conduit-extra.cabal view
@@ -1,5 +1,5 @@ Name: conduit-extra-Version: 1.1.17+Version: 1.2.0 Synopsis: Batteries included conduit: adapters for common libraries. Description: The conduit package itself maintains relative small dependencies. The purpose of this package is to collect commonly used utility functions wrapping other library dependencies, without depending on heavier-weight dependencies. The basic idea is that this package should only depend on haskell-platform packages and conduit.
test/Data/Conduit/AttoparsecSpec.hs view
@@ -22,6 +22,7 @@ let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"] badLine = 4 badCol = 6+ badOff = 15 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -30,15 +31,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works for bytestring" $ do let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"] badLine = 4 badCol = 6+ badOff = 15 parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -47,15 +49,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works in last chunk" $ do let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"] badLine = 6 badCol = 5+ badOff = 22 parser = Data.Attoparsec.Text.char 'c' <|> (Data.Attoparsec.Text.anyChar >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -64,15 +67,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works in last chunk" $ do let input = ["aaa\na", "aaa\n\n", "aaa", "aa\n\naaaab"] badLine = 6 badCol = 6+ badOff = 22 parser = Data.Attoparsec.Text.string "bc" <|> (Data.Attoparsec.Text.anyChar >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -81,15 +85,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works after new line in text" $ do let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"] badLine = 5 badCol = 1+ badOff = 15 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -98,15 +103,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works after new line in bytestring" $ do let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"] badLine = 5 badCol = 1+ badOff = 15 parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -115,15 +121,16 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff it "works for first line" $ do let input = ["aab\na", "aaa\n\n", "aaa", "aab\n\naaaa"] badLine = 1 badCol = 3+ badOff = 2 parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser) sink = sinkParser parser sink' = sinkParserEither parser@@ -132,11 +139,11 @@ Left e -> case fromException e of Just pe -> do- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff ea' <- CL.sourceList input $$ sink' case ea' of Left pe ->- errorPosition pe `shouldBe` Position badLine badCol+ errorPosition pe `shouldBe` Position badLine badCol badOff describe "conduitParser" $ do it "parses a repeated stream" $ do@@ -147,7 +154,7 @@ let chk a = case a of Left{} -> False Right (_, xs) -> xs == "aaa"- chkp l = (PositionRange (Position l 1) (Position (l+1) 1))+ chkp l = PositionRange (Position l 1 ((l - 1) * 4)) (Position (l+1) 1 (l * 4)) forM_ ea $ \ a -> a `shouldSatisfy` chk :: Expectation forM_ (zip ea [1..]) $ \ (Right (pos, _), l) -> pos `shouldBe` chkp l length ea `shouldBe` 4@@ -156,14 +163,14 @@ results <- yield "hihihi\nhihi" $$ conduitParser (Data.Attoparsec.Text.string "\n" <|> Data.Attoparsec.Text.string "hi") =$ CL.consume- let f (a, b, c, d, e) = (PositionRange (Position a b) (Position c d), e)+ let f (a, b, c, d, e, f, g) = (PositionRange (Position a b c) (Position d e f), g) results `shouldBe` map f- [ (1, 1, 1, 3, "hi")- , (1, 3, 1, 5, "hi")- , (1, 5, 1, 7, "hi")+ [ (1, 1, 0, 1, 3, 2, "hi")+ , (1, 3, 2, 1, 5, 4, "hi")+ , (1, 5, 4, 1, 7, 6, "hi") - , (1, 7, 2, 1, "\n")+ , (1, 7, 6, 2, 1, 7, "\n") - , (2, 1, 2, 3, "hi")- , (2, 3, 2, 5, "hi")+ , (2, 1, 7, 2, 3, 9, "hi")+ , (2, 3, 9, 2, 5, 11, "hi") ]