{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} module Stack.Types.PvpBounds ( PvpBounds (..) , PvpBoundsType (..) , pvpBoundsText , parsePvpBounds ) where import Data.Aeson.Types ( FromJSON (..), ToJSON (..), withText ) import qualified Data.Map as Map import qualified Data.Text as T import Stack.Prelude -- | How PVP bounds should be added to .cabal files data PvpBoundsType = PvpBoundsNone | PvpBoundsUpper | PvpBoundsLower | PvpBoundsBoth deriving (Bounded, Enum, Eq, Ord, Read, Show, Typeable) data PvpBounds = PvpBounds { pbType :: !PvpBoundsType , pbAsRevision :: !Bool } deriving (Eq, Ord, Read, Show, Typeable) pvpBoundsText :: PvpBoundsType -> Text pvpBoundsText PvpBoundsNone = "none" pvpBoundsText PvpBoundsUpper = "upper" pvpBoundsText PvpBoundsLower = "lower" pvpBoundsText PvpBoundsBoth = "both" parsePvpBounds :: Text -> Either String PvpBounds parsePvpBounds t = maybe err Right $ do (t', asRevision) <- case T.break (== '-') t of (x, "") -> Just (x, False) (x, "-revision") -> Just (x, True) _ -> Nothing x <- Map.lookup t' m Just PvpBounds { pbType = x , pbAsRevision = asRevision } where m = Map.fromList $ map (pvpBoundsText &&& id) [minBound..maxBound] err = Left $ "Invalid PVP bounds: " ++ T.unpack t instance ToJSON PvpBounds where toJSON (PvpBounds typ asRevision) = toJSON (pvpBoundsText typ <> (if asRevision then "-revision" else "")) instance FromJSON PvpBounds where parseJSON = withText "PvpBounds" (either fail pure . parsePvpBounds)