-- | To learn more about pipes-group and how to use these functions with it, check out the in -- depth tutorial at module Pipes.Break.ByteString ( -- * Group Producers By A Delimiter -- | Break any producer up into groups with the delimiter stripped out with the presumption that -- two 'Producer's are "equivalent" if they produce the same string when drained. -- -- @ -- 'unBreaksBy' delim ('breaksBy' delim foo) ≡ foo -- 'unBreakBy' delim ('breakBy' delim foo) ≡ foo -- @ breakBy, unBreakBy, breaksBy, unBreaksBy, -- * Group Producers Ending By A Delimiter -- | These are almost equivalent to the breakBy functions, however they imply that every chunk "ends" with a delimiter, -- rather than just being separated by them. -- -- Unfortunately it is impossible to know in a streaming fashion for sure that your next group will -- ever end with a delimiter (or end at all for that matter). The only way to find out is to store every line you receive until you find it. -- Therefore, the endsBy family of functions are not invertible. -- -- >>> mconcat $ Pipes.Prelude.toList (unEndsBy "\r\n" (endsBy "\r\n" (yield "A\r\nB\r\nC"))) -- "A\r\nB\r\nC\r\n" -- -- In other words: -- -- @ -- 'unEndsBy' delim ('endsBy' delim foo) ≠ foo -- 'unEndBy' delim ('endBy' delim foo) ≠ foo -- @ endBy, unEndBy, endsBy, unEndsBy, -- * Utilities replace ) where import Pipes as P import Pipes.Group as P import qualified Data.ByteString.Char8 as B import Pipes.Break.Internal -- | Yield argument until it reaches delimiter or end of stream, then return the remainder (minus the delimiter). -- -- This is equivalent to 'breakBy'. endBy :: (Monad m) => B.ByteString -> Producer B.ByteString m r -> Producer B.ByteString m (Producer B.ByteString m r) endBy = breakBy -- | Recombine a producer that had been previously broken by using a separator. If the second stream is empty, -- the delimiter will be added on at the end of the first producer anyways. -- -- >>> mconcat $ Pipes.Prelude.toList (unEndBy "\n" (yield "abc" >> return (yield "def"))) -- "abc\ndef" -- -- >>> mconcat $ Pipes.Prelude.toList (unEndBy "\n" (yield "abc" >> return (return ()))) -- "abc\n" -- -- This is /not/ equivalent to 'unBreakBy' and is not quite an inverse of 'endBy'. unEndBy :: (Monad m) => B.ByteString -> Producer B.ByteString m (Producer B.ByteString m r) -> Producer B.ByteString m r unEndBy = _unEndBy -- | Recombine a producer that had been previously broken recombining it with the provided delimiter. -- -- >>> mconcat $ Pipes.Prelude.toList (unBreakBy "\n" (yield "abc" >> return (yield "def"))) -- "abc\ndef" -- -- >>> mconcat $ Pipes.Prelude.toList (unBreakBy "\n" (yield "abc" >> return (return ()))) -- "abc" -- -- The inverse of 'breakBy'. unBreakBy :: (Monad m) => B.ByteString -> Producer B.ByteString m (Producer B.ByteString m r) -> Producer B.ByteString m r unBreakBy = _unBreakBy endsBy :: (Monad m) => B.ByteString -> Producer B.ByteString m r -> FreeT (Producer B.ByteString m) m r endsBy = _endsBy -- | Not quite the inverse of 'endsBy'. unEndsBy :: (Monad m) => B.ByteString -> FreeT (Producer B.ByteString m) m r -> Producer B.ByteString m r unEndsBy = _unEndsBy -- | The inverse of 'breaksBy'. unBreaksBy :: (Monad m) => B.ByteString -> FreeT (Producer B.ByteString m) m r -> Producer B.ByteString m r unBreaksBy = _unBreaksBy -- | Group a producer on any delimiter. breaksBy :: (Monad m) => B.ByteString -> Producer B.ByteString m r -> FreeT (Producer B.ByteString m) m r breaksBy = _breaksBy -- | Yield argument until it reaches delimiter or end of stream, then returns the remainder (minus the delimiter). -- -- >>> rest <- runEffect $ for (breakBy "\r\n" (yield "A\r\nB\r\nC\r\n")) (lift . Prelude.print) -- "A" -- -- >>> runEffect $ for rest (lift . print) -- "B\r\nC\r\n" -- -- This is almost equivalent to Pipes.ByteString.line except that it works for any delimiter, not just '\n', -- and it also consumes the delimiter. breakBy :: (Monad m) => B.ByteString -> Producer B.ByteString m r -> Producer B.ByteString m (Producer B.ByteString m r) breakBy = _breakBy -- | Replace one delimiter with another in a stream. -- -- >>> fmap mconcat <$> toListM $ replace "\r\n" "\n" (yield "abc\ndef\r\nfoo\n\r\nbar") -- "abc\ndef\nfoo\n\nbar" replace :: (Monad m) => B.ByteString -> B.ByteString -> Producer B.ByteString m r -> Producer B.ByteString m r replace from to = unBreaksBy to . breaksBy from