{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# OPTIONS -fno-warn-unused-do-bind #-} -- | Package identifier (name-version). module Stack.Types.PackageIdentifier ( PackageIdentifier(..) , toTuple , fromTuple , parsePackageIdentifier , parsePackageIdentifierFromString , packageIdentifierParser , packageIdentifierString , packageIdentifierText ) where import Control.Applicative import Control.DeepSeq import Control.Exception (Exception) import Control.Monad.Catch (MonadThrow, throwM) import Data.Aeson.Extended import Data.Attoparsec.Text import Data.Data import Data.Hashable import Data.Store (Store) import Data.Text (Text) import qualified Data.Text as T import GHC.Generics import Prelude hiding (FilePath) import Stack.Types.PackageName import Stack.Types.Version -- | A parse fail. data PackageIdentifierParseFail = PackageIdentifierParseFail Text deriving (Typeable) instance Show PackageIdentifierParseFail where show (PackageIdentifierParseFail bs) = "Invalid package identifier: " ++ show bs instance Exception PackageIdentifierParseFail -- | A pkg-ver combination. data PackageIdentifier = PackageIdentifier { -- | Get the name part of the identifier. packageIdentifierName :: !PackageName -- | Get the version part of the identifier. , packageIdentifierVersion :: !Version } deriving (Eq,Ord,Generic,Data,Typeable) instance NFData PackageIdentifier where rnf (PackageIdentifier !p !v) = seq (rnf p) (rnf v) instance Hashable PackageIdentifier instance Store PackageIdentifier instance Show PackageIdentifier where show = show . packageIdentifierString instance ToJSON PackageIdentifier where toJSON = toJSON . packageIdentifierString instance FromJSON PackageIdentifier where parseJSON = withText "PackageIdentifier" $ \t -> case parsePackageIdentifier t of Left e -> fail $ show (e, t) Right x -> return x -- | Convert from a package identifier to a tuple. toTuple :: PackageIdentifier -> (PackageName,Version) toTuple (PackageIdentifier n v) = (n,v) -- | Convert from a tuple to a package identifier. fromTuple :: (PackageName,Version) -> PackageIdentifier fromTuple (n,v) = PackageIdentifier n v -- | A parser for a package-version pair. packageIdentifierParser :: Parser PackageIdentifier packageIdentifierParser = do name <- packageNameParser char '-' version <- versionParser return (PackageIdentifier name version) -- | Convenient way to parse a package identifier from a 'Text'. parsePackageIdentifier :: MonadThrow m => Text -> m PackageIdentifier parsePackageIdentifier x = go x where go = either (const (throwM (PackageIdentifierParseFail x))) return . parseOnly (packageIdentifierParser <* endOfInput) -- | Convenience function for parsing from a 'String'. parsePackageIdentifierFromString :: MonadThrow m => String -> m PackageIdentifier parsePackageIdentifierFromString = parsePackageIdentifier . T.pack -- | Get a string representation of the package identifier; name-ver. packageIdentifierString :: PackageIdentifier -> String packageIdentifierString (PackageIdentifier n v) = show n ++ "-" ++ show v -- | Get a Text representation of the package identifier; name-ver. packageIdentifierText :: PackageIdentifier -> Text packageIdentifierText = T.pack . packageIdentifierString