{-|
Module      : Network.Wai.RequestSpec.Parser
Description : Running parsers and generating errors
Copyright   : Allele Dev 2015
License     : BSD-3
Maintainer  : allele.dev@gmail.com
Stability   : experimental
Portability : POSIX
-}
module Network.Wai.RequestSpec.Parser (
  Result(..),
  P,

  parse,
  parseMaybe,
  parseEither,

  (<?>),
  missing,
  malformed,
  freeform
) where

import Data.Monoid
import Data.Text

import Network.Wai.RequestSpec.Error
import Network.Wai.RequestSpec.Internal.Parser

----------------------------------------------------------------------
                        -- Invoking Parsers --
----------------------------------------------------------------------
parse_ :: (a -> P b) -> a -> (Error -> t) -> (b -> t) -> t
parse_ m v l r = case runP (m v) Failure (\a _ -> Success a) of
  (Failure x) -> l x
  (Success x) -> r x

parse :: (a -> P b) -> a -> Result b
parse m v = parse_ m v Failure Success

parseMaybe :: (a -> P b) -> a -> Maybe b
parseMaybe m v = parse_ m v (const Nothing) Just

parseEither :: (a -> P b) -> a -> Either Error b
parseEither m v = parse_ m v Left Right

----------------------------------------------------------------------
                        -- Creating Errors --
----------------------------------------------------------------------
(<?>) :: P a -> Text -> P a
p <?> s = P $ \kf ks ->
  runP p (\e -> kf (Annotation s <> e)) (\a e -> ks a (Annotation s <> e))

failure_ :: Error -> P a
failure_ e = P $ \kf _ -> kf e

missing :: Loc -> P a
missing l = failure_ (Missing l)

malformed :: Reason -> Text -> P a
malformed r s = failure_ (Malformed r s)

freeform :: Text -> P a
freeform r = failure_ (Freeform r)