{-# LANGUAGE AllowAmbiguousTypes #-}

-- | Handy utilities for defining predicates.

module Rerefined.Predicate.Common
  (
  -- * Re-exports
    module Rerefined.Predicate
  , proxy#
  , TBL.Builder

  -- * Predicate validation
  , validateFail, validateBool
  ) where

import Rerefined.Predicate
import GHC.Exts ( Proxy#, proxy#, IsString(fromString) )
import Data.Text.Builder.Linear qualified as TBL

-- | Shortcut for returning a predicate validation failure.
validateFail
    :: forall p
    .  (Predicate p, KnownPredicateName p)
    => Proxy# p -> TBL.Builder -> [RefineFailure]
    -> Maybe RefineFailure
validateFail :: forall {k} (p :: k).
(Predicate p, KnownPredicateName p) =>
Proxy# p -> Builder -> [RefineFailure] -> Maybe RefineFailure
validateFail Proxy# p
_p Builder
msg [RefineFailure]
es =
    RefineFailure -> Maybe RefineFailure
forall a. a -> Maybe a
Just (RefineFailure -> Maybe RefineFailure)
-> RefineFailure -> Maybe RefineFailure
forall a b. (a -> b) -> a -> b
$ Builder -> Builder -> [RefineFailure] -> RefineFailure
RefineFailure (String -> Builder
forall a. IsString a => String -> a
fromString (String -> Builder) -> String -> Builder
forall a b. (a -> b) -> a -> b
$ forall (p :: k). KnownPredicateName p => String
forall {k} (p :: k). KnownPredicateName p => String
predicateName @p) Builder
msg [RefineFailure]
es

-- | Shortcut for simply validating a 'Bool'.
validateBool
    :: forall p
    .  (Predicate p, KnownPredicateName p)
    => Proxy# p -> TBL.Builder -> Bool
    -> Maybe RefineFailure
validateBool :: forall {k} (p :: k).
(Predicate p, KnownPredicateName p) =>
Proxy# p -> Builder -> Bool -> Maybe RefineFailure
validateBool Proxy# p
p Builder
e = \case
  Bool
True  -> Maybe RefineFailure
forall a. Maybe a
Nothing
  Bool
False -> Proxy# p -> Builder -> [RefineFailure] -> Maybe RefineFailure
forall {k} (p :: k).
(Predicate p, KnownPredicateName p) =>
Proxy# p -> Builder -> [RefineFailure] -> Maybe RefineFailure
validateFail Proxy# p
p Builder
e []