{-# 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