module Potoki.Core.Transform.Scanner where import Potoki.Core.Prelude hiding (take, takeWhile, filter, drop) import Potoki.Core.Types import Potoki.Core.Transform.Basic import Scanner {-# INLINE scan #-} scan :: Scanner a -> Transform ByteString (Either Text a) scan scanner = Transform $ \ (Fetch fetchIo) -> liftIO $ do unconsumedRef <- newMutVar mempty finishedRef <- newMutVar False return $ Fetch $ let matchResult = \ case More inputToResultVal -> consumeVal inputToResultVal Done unconsumed parsed -> do writeMutVar unconsumedRef unconsumed return (Just (Right parsed)) Fail unconsumed message -> do writeMutVar unconsumedRef unconsumed writeMutVar finishedRef True return (Just (Left (fromString message))) consumeVal inputToResultVal' = fetchIo >>= \ case Nothing -> do writeMutVar finishedRef True matchResult (inputToResultVal' mempty) Just input -> do when (input == mempty) (writeMutVar finishedRef True) matchResult (inputToResultVal' input) in do finished <- readMutVar finishedRef if finished then return Nothing else do unconsumed <- readMutVar unconsumedRef if unconsumed == mempty then fetchIo >>= \ case Nothing -> return Nothing Just input -> do if input == mempty then return Nothing else matchResult (Scanner.scan scanner input) else do writeMutVar unconsumedRef mempty matchResult (Scanner.scan scanner unconsumed)