@@ -52,6 +52,7 @@ module Streamly.Internal.Data.Parser.ParserD
5252 , takeGE -- takeBetween n maxBound
5353
5454 -- Grab a sequence of input elements by inspecting them
55+ , takeP
5556 , lookAhead
5657 , takeWhile
5758 , takeWhile1
@@ -814,6 +815,56 @@ spanByRolling eq f1 f2 =
814815-- nested parsers
815816-------------------------------------------------------------------------------
816817
818+-- | See 'Streamly.Internal.Data.Parser.takeP'.
819+--
820+-- /Internal/
821+{-# INLINE takeP #-}
822+takeP :: Monad m => Int -> Parser m a b -> Parser m a b
823+takeP lim (Parser pstep pinitial pextract) = Parser step initial extract
824+
825+ where
826+
827+ initial = do
828+ res <- pinitial
829+ case res of
830+ IPartial s ->
831+ if lim > 0
832+ then return $ IPartial $ Tuple' 0 s
833+ else IDone <$> pextract s
834+ IDone b -> return $ IDone b
835+ IError e -> return $ IError e
836+
837+ step (Tuple' cnt r) a = do
838+ assert (cnt < lim) (return ())
839+ res <- pstep r a
840+ let cnt1 = cnt + 1
841+ case res of
842+ Partial 0 s -> do
843+ assert (cnt1 >= 0) (return ())
844+ if cnt1 < lim
845+ then return $ Partial 0 $ Tuple' cnt1 s
846+ else Done 0 <$> pextract s
847+ Continue 0 s -> do
848+ assert (cnt1 >= 0) (return ())
849+ if cnt1 < lim
850+ then return $ Continue 0 $ Tuple' cnt1 s
851+ -- XXX This should error out?
852+ -- If designed properly, this will probably error out.
853+ -- "pextract" should error out
854+ else Done 0 <$> pextract s
855+ Partial n s -> do
856+ let taken = cnt1 - n
857+ assert (taken >= 0) (return ())
858+ return $ Partial n $ Tuple' taken s
859+ Continue n s -> do
860+ let taken = cnt1 - n
861+ assert (taken >= 0) (return ())
862+ return $ Continue n $ Tuple' taken s
863+ Done n b -> return $ Done n b
864+ Error str -> return $ Error str
865+
866+ extract (Tuple' _ r) = pextract r
867+
817868-- | See 'Streamly.Internal.Data.Parser.lookahead'.
818869--
819870-- /Pre-release/