Distribution/Utils/ShortText.hs

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric #-}

    module Distribution.Utils.ShortText
        ( -- * 'ShortText' type
          ShortText
        , toShortText
        , fromShortText

          -- * internal utilities
        , decodeStringUtf8
        , encodeStringUtf8
        ) where

    import Prelude ()
    import Distribution.Compat.Prelude
    import Distribution.Utils.String

    #if defined(MIN_VERSION_bytestring)
    # if MIN_VERSION_bytestring(0,10,4)
    # define HAVE_SHORTBYTESTRING 1
    # endif
    #endif

    -- Hack for GHC bootstrapping
    --
    -- Currently (as of GHC 8.1), GHC bootstraps Cabal by building
    -- binary and Cabal in one giant ghc --make command.  This
    -- means no MIN_VERSION_binary macro is available.
    --
    -- We could try to cleverly figure something out in this case,
    -- but there is a better plan: just use the unoptimized version
    -- of the Binary instance.  We're not going to use it for anything
    -- real in any case.
    --
    -- WARNING: Don't use MIN_VERSION_binary to smooth over a BC-break!
    --
    #ifndef MIN_VERSION_binary
    #define MIN_VERSION_binary(x, y, z) 0
    #endif

    #if HAVE_SHORTBYTESTRING
    import qualified Data.ByteString.Short as BS.Short
    #endif

    -- | Construct 'ShortText' from 'String'
    toShortText :: String -> ShortText

    -- | Convert 'ShortText' to 'String'
    fromShortText :: ShortText -> String

    -- | Compact representation of short 'Strings'
    --
    -- The data is stored internally as UTF8 in an
    -- 'BS.Short.ShortByteString' when compiled against @bytestring >=
    -- 0.10.4@, and otherwise the fallback is to use plain old non-compat
    -- '[Char]'.
    --
    -- Note: This type is for internal uses (such as e.g. 'PackageName')
    -- and shall not be exposed in Cabal's API
    --
    -- @since 2.0.0.2
    #if HAVE_SHORTBYTESTRING
    newtype ShortText = ST { unST :: BS.Short.ShortByteString }
                      deriving (Eq,Ord,Generic,Data,Typeable)

    # if MIN_VERSION_binary(0,8,1)
    instance Binary ShortText where
        put = put . unST
        get = fmap ST get
    # else
    instance Binary ShortText where
        put = put . BS.Short.fromShort . unST
        get = fmap (ST . BS.Short.toShort) get
    # endif

    toShortText = ST . BS.Short.pack . encodeStringUtf8

    fromShortText = decodeStringUtf8 . BS.Short.unpack . unST
    #else
    newtype ShortText = ST { unST :: String }
                      deriving (Eq,Ord,Generic,Data,Typeable)

    instance Binary ShortText where
        put = put . encodeStringUtf8 . unST
        get = fmap (ST . decodeStringUtf8) get

    toShortText = ST

    fromShortText = unST
    #endif

    instance NFData ShortText where
        rnf = rnf . unST

    instance Show ShortText where
        show = show . fromShortText

    instance Read ShortText where
        readsPrec p = map (first toShortText) . readsPrec p

    instance Semigroup ShortText where
        ST a <> ST b = ST (mappend a b)

    instance Monoid ShortText where
        mempty = ST mempty
        mappend = (<>)

    instance IsString ShortText where
        fromString = toShortText