content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE LambdaCase #-}
  -- | Definition of the parsing monad, plus internal
  -- unsafe functions.
  module Data.ProtoLens.Encoding.Parser.Internal
      ( Parser(..)
      , ParseResult(..)
      ) where
  
  import Control.Monad (ap)
  import qualified Control.Monad.Fail as Fail
  import Data.Word (Word8)
  import Foreign.Ptr
  
  -- | A monad for parsing an input buffer.
  newtype Parser a = Parser
      { unParser :: Ptr Word8 -- End position of the input
                 -> Ptr Word8 -- Current position in the input
                 -> IO (ParseResult a)
      }
  
  data ParseResult a
      = ParseSuccess
          { _newPos :: !(Ptr Word8) -- ^ New position in the input
          , unParserResult :: a
          }
      | ParseFailure String
  
  instance Functor ParseResult where
      fmap f (ParseSuccess p x) = ParseSuccess p (f x)
      fmap _ (ParseFailure s) = ParseFailure s
  
  instance Functor Parser where
      fmap f (Parser g) = Parser $ \end cur -> fmap f <$> g end cur
  
  instance Applicative Parser where
      pure x = Parser $ \_ cur -> return $ ParseSuccess cur x
      (<*>) = ap
  
  instance Monad Parser where
  #if !MIN_VERSION_base(4,13,0)
      fail = Fail.fail
  #endif
      return = pure
      Parser f >>= g = Parser $ \end pos -> f end pos >>= \case
          ParseSuccess pos' x -> unParser (g x) end pos'
          ParseFailure s -> return $ ParseFailure s
  
  instance Fail.MonadFail Parser where
      fail s = Parser $ \_ _ -> return $ ParseFailure s
  