{-# LANGUAGE LambdaCase #-} module Conduit.Splitter where import Conduit import Control.Monad import qualified Data.ByteString as StrictBS import Data.ByteString.Builder as BB import Data.ByteString.Lazy (ByteString, fromStrict, null, toStrict) import qualified Data.ByteString.Lazy as BS import Data.ByteString.Lazy.Search (split) import Data.Foldable import Data.Monoid splitDelim :: Monad m => StrictBS.ByteString -> Conduit ByteString m ByteString splitDelim delim = go mempty where go bldr = await >>= \case Nothing -> yieldB bldr Just bs -> case split delim bs of [] -> yieldB bldr >> go mempty [x] -> go (bldr <> BB.lazyByteString x) (x:bs) -> do let (xs, mbLast) = foldl' (\(as, l) x -> (maybe as (:as) l, Just x)) ([], Nothing) bs let lastB = maybe mempty BB.lazyByteString mbLast yieldB (bldr <> BB.lazyByteString x) forM_ xs yieldNonEmpty go lastB yieldNonEmpty bs = if not $ BS.null bs then yield bs else pure () yieldB b = yieldNonEmpty $ BB.toLazyByteString b