    {-# LANGUAGE LambdaCase #-}
    module Hpack.Error (
    -- | /__NOTE:__/ This module is exposed to allow integration of Hpack into
    -- other tools.  It is not meant for general use by end users.  The following
    -- caveats apply:
    --
    -- * The API is undocumented, consult the source instead.
    --
    -- * The exposed types and functions primarily serve Hpack's own needs, not
    -- that of a public API.  Breaking changes can happen as Hpack evolves.
    --
    -- As an Hpack user you either want to use the @hpack@ executable or a build
    -- tool that supports Hpack (e.g. @stack@ or @cabal2nix@).
      HpackError (..)
    , formatHpackError
    , ProgramName (..)
    , URL
    , Status (..)
    , formatStatus
    ) where

    import qualified Data.ByteString.Char8 as B
    import           Data.List (intercalate)
    import           Data.String (IsString (..))
    import           Data.Version (Version (..), showVersion)
    import           Network.HTTP.Types.Status (Status (..))

    type URL = String

    data HpackError =
        HpackVersionNotSupported FilePath Version Version
      | DefaultsFileNotFound FilePath
      | DefaultsDownloadFailed URL Status
      | CycleInDefaults [FilePath]
      | ParseError String
      | DecodeValueError FilePath String
      deriving (HpackError -> HpackError -> Bool
    (HpackError -> HpackError -> Bool)
    -> (HpackError -> HpackError -> Bool) -> Eq HpackError
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HpackError -> HpackError -> Bool
    == :: HpackError -> HpackError -> Bool
    $c/= :: HpackError -> HpackError -> Bool
    /= :: HpackError -> HpackError -> Bool
    Eq, Int -> HpackError -> ShowS
    [HpackError] -> ShowS
    HpackError -> FilePath
    (Int -> HpackError -> ShowS)
    -> (HpackError -> FilePath)
    -> ([HpackError] -> ShowS)
    -> Show HpackError
    forall a.
    (Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HpackError -> ShowS
    showsPrec :: Int -> HpackError -> ShowS
    $cshow :: HpackError -> FilePath
    show :: HpackError -> FilePath
    $cshowList :: [HpackError] -> ShowS
    showList :: [HpackError] -> ShowS
    Show)

    newtype ProgramName = ProgramName {ProgramName -> FilePath
    unProgramName :: String}
      deriving (ProgramName -> ProgramName -> Bool
    (ProgramName -> ProgramName -> Bool)
    -> (ProgramName -> ProgramName -> Bool) -> Eq ProgramName
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ProgramName -> ProgramName -> Bool
    == :: ProgramName -> ProgramName -> Bool
    $c/= :: ProgramName -> ProgramName -> Bool
    /= :: ProgramName -> ProgramName -> Bool
    Eq, Int -> ProgramName -> ShowS
    [ProgramName] -> ShowS
    ProgramName -> FilePath
    (Int -> ProgramName -> ShowS)
    -> (ProgramName -> FilePath)
    -> ([ProgramName] -> ShowS)
    -> Show ProgramName
    forall a.
    (Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ProgramName -> ShowS
    showsPrec :: Int -> ProgramName -> ShowS
    $cshow :: ProgramName -> FilePath
    show :: ProgramName -> FilePath
    $cshowList :: [ProgramName] -> ShowS
    showList :: [ProgramName] -> ShowS
    Show)

    instance IsString ProgramName where
      fromString :: FilePath -> ProgramName
    fromString = FilePath -> ProgramName
    ProgramName

    formatHpackError :: ProgramName -> HpackError -> String
    formatHpackError :: ProgramName -> HpackError -> FilePath
    formatHpackError (ProgramName FilePath
    progName) = \ case
      HpackVersionNotSupported FilePath
    file Version
    wanted Version
    supported ->
        FilePath
    "The file " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    file FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " requires version " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Version -> FilePath
    showVersion Version
    wanted FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
        FilePath
    " of the Hpack package specification, however this version of " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
        FilePath
    progName FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " only supports versions up to " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Version -> FilePath
    showVersion Version
    supported FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
        FilePath
    ". Upgrading to the latest version of " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    progName FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " may resolve this issue."
      DefaultsFileNotFound FilePath
    file -> FilePath
    "Invalid value for \"defaults\"! File " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    file FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " does not exist!"
      DefaultsDownloadFailed FilePath
    url Status
    status -> FilePath
    "Error while downloading " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    url FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " (" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Status -> FilePath
    formatStatus Status
    status FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")"
      CycleInDefaults [FilePath]
    files -> FilePath
    "cycle in defaults (" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath -> [FilePath] -> FilePath
    forall a. [a] -> [[a]] -> [a]
    intercalate FilePath
    " -> " [FilePath]
    files FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")"
      ParseError FilePath
    err -> FilePath
    err
      DecodeValueError FilePath
    file FilePath
    err -> FilePath
    file FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ": " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    err

    formatStatus :: Status -> String
    formatStatus :: Status -> FilePath
    formatStatus (Status Int
    code ByteString
    message) = Int -> FilePath
    forall a. Show a => a -> FilePath
    show Int
    code FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> FilePath
    B.unpack ByteString
    message