content: {-# LANGUAGE DeriveDataTypeable #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  
  module Distribution.Types.UnitId
    ( UnitId, unUnitId, mkUnitId
    , DefUnitId
    , unsafeMkDefUnitId
    , unDefUnitId
    , newSimpleUnitId
    , mkLegacyUnitId
    , getHSLibraryName
    , InstalledPackageId -- backwards compat
    ) where
  
  import Prelude ()
  import Distribution.Compat.Prelude
  import Distribution.Utils.ShortText
  
  import qualified Distribution.Compat.ReadP as Parse
  import Distribution.Text
  import Distribution.Types.ComponentId
  import Distribution.Types.PackageId
  
  import Text.PrettyPrint (text)
  
  -- | A unit identifier identifies a (possibly instantiated)
  -- package/component that can be installed the installed package
  -- database.  There are several types of components that can be
  -- installed:
  --
  --  * A traditional library with no holes, so that 'unitIdHash'
  --    is @Nothing@.  In the absence of Backpack, 'UnitId'
  --    is the same as a 'ComponentId'.
  --
  --  * An indefinite, Backpack library with holes.  In this case,
  --    'unitIdHash' is still @Nothing@, but in the install,
  --    there are only interfaces, no compiled objects.
  --
  --  * An instantiated Backpack library with all the holes
  --    filled in.  'unitIdHash' is a @Just@ a hash of the
  --    instantiating mapping.
  --
  -- A unit is a component plus the additional information on how the
  -- holes are filled in. Thus there is a one to many relationship: for a
  -- particular component there are many different ways of filling in the
  -- holes, and each different combination is a unit (and has a separate
  -- 'UnitId').
  --
  -- 'UnitId' is distinct from 'OpenUnitId', in that it is always
  -- installed, whereas 'OpenUnitId' are intermediate unit identities
  -- that arise during mixin linking, and don't necessarily correspond
  -- to any actually installed unit.  Since the mapping is not actually
  -- recorded in a 'UnitId', you can't actually substitute over them
  -- (but you can substitute over 'OpenUnitId').  See also
  -- "Distribution.Backpack.FullUnitId" for a mechanism for expanding an
  -- instantiated 'UnitId' to retrieve its mapping.
  --
  -- Backwards compatibility note: if you need to get the string
  -- representation of a UnitId to pass, e.g., as a @-package-id@
  -- flag, use the 'display' function, which will work on all
  -- versions of Cabal.
  --
  newtype UnitId = UnitId ShortText
    deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, NFData)
  
  {-# DEPRECATED InstalledPackageId "Use UnitId instead" #-}
  type InstalledPackageId = UnitId
  
  instance Binary UnitId
  
  -- | The textual format for 'UnitId' coincides with the format
  -- GHC accepts for @-package-id@.
  --
  instance Text UnitId where
      disp = text . unUnitId
      parse = mkUnitId <$> Parse.munch1 (\c -> isAlphaNum c || c `elem` "-_.+")
  
  -- | If you need backwards compatibility, consider using 'display'
  -- instead, which is supported by all versions of Cabal.
  --
  unUnitId :: UnitId -> String
  unUnitId (UnitId s) = fromShortText s
  
  mkUnitId :: String -> UnitId
  mkUnitId = UnitId . toShortText
  
  -- | 'mkUnitId'
  --
  -- @since 2.0
  instance IsString UnitId where
      fromString = mkUnitId
  
  -- | Create a unit identity with no associated hash directly
  -- from a 'ComponentId'.
  newSimpleUnitId :: ComponentId -> UnitId
  newSimpleUnitId = mkUnitId . unComponentId
  
  -- | Make an old-style UnitId from a package identifier.
  -- Assumed to be for the public library
  mkLegacyUnitId :: PackageId -> UnitId
  mkLegacyUnitId = newSimpleUnitId . mkComponentId . display
  
  -- | Returns library name prefixed with HS, suitable for filenames
  getHSLibraryName :: UnitId -> String
  getHSLibraryName uid = display uid
  
  -- | A 'UnitId' for a definite package.  The 'DefUnitId' invariant says
  -- that a 'UnitId' identified this way is definite; i.e., it has no
  -- unfilled holes.
  newtype DefUnitId = DefUnitId { unDefUnitId :: UnitId }
    deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, Binary, NFData, Text)
  
  -- | Unsafely create a 'DefUnitId' from a 'UnitId'.  Your responsibility
  -- is to ensure that the 'DefUnitId' invariant holds.
  unsafeMkDefUnitId :: UnitId -> DefUnitId
  unsafeMkDefUnitId = DefUnitId
  