{-|
Module      : Botan.Low.Error
Description : Error codes and exception handling
Copyright   : (c) Leo D, 2023
License     : BSD-3-Clause
Maintainer  : leo@apotheca.io
Stability   : experimental
Portability : POSIX
-}

module Botan.Low.Error
( BotanErrorCode(..)
, pattern Success
, pattern InvalidIdentifier
, pattern InvalidInput
, pattern BadMAC
, pattern InsufficientBufferSpace
, pattern StringConversionError
, pattern ExceptionThrown
, pattern OutOfMemory
, pattern SystemError
, pattern InternalError
, pattern BadFlag
, pattern NullPointer
, pattern BadParameter
, pattern KeyNotSet
, pattern InvalidKeyLength
, pattern InvalidObjectState
, pattern NotImplemented
, pattern InvalidObject
, pattern TLSError
, pattern HttpError
, pattern RoughtimeError
, pattern UnknownError
, botanErrorDescription
, botanErrorLastExceptionMessage
, SomeBotanException(..)
, toBotanException
, fromBotanException
, InvalidInputException(..)
, BadMACException(..)
, InsufficientBufferSpaceException(..)
, StringConversionException(..)
, ExceptionThrownException(..)
, OutOfMemoryException(..)
, SystemErrorException(..)
, InternalErrorException(..)
, BadFlagException(..)
, NullPointerException(..)
, BadParameterException(..)
, KeyNotSetException(..)
, InvalidKeyLengthException(..)
, InvalidObjectStateException(..)
, NotImplementedException(..)
, InvalidObjectException(..)
, UnknownException(..)
, throwBotanError
, throwBotanIfNegative
, throwBotanIfNegative_
, throwBotanCatchingSuccess
, throwBotanCatchingBool
, throwBotanCatchingInt
, throwBotanErrorWithCallstack
, tryBotan
, catchBotan
, handleBotan
) where

import Data.Typeable

import Botan.Bindings.Error

import Botan.Low.Prelude

import qualified Data.ByteString        as ByteString
import qualified Data.ByteString.Char8  as Char8
import qualified Data.Text              as Text

-- | Botan error code data type
type BotanErrorCode = CInt

{-
Botan error code patterns
-}

pattern Success
    ,   InvalidIdentifier
    ,   InvalidInput
    ,   BadMAC
    ,   InsufficientBufferSpace
    ,   StringConversionError
    ,   ExceptionThrown
    ,   OutOfMemory
    ,   SystemError
    ,   InternalError
    ,   BadFlag
    ,   NullPointer
    ,   BadParameter
    ,   KeyNotSet
    ,   InvalidKeyLength
    ,   InvalidObjectState
    ,   NotImplemented
    ,   InvalidObject
    ,   TLSError
    ,   HttpError
    ,   RoughtimeError
    ,   UnknownError
    :: BotanErrorCode

pattern $mSuccess :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bSuccess :: BotanErrorCode
Success = BOTAN_FFI_SUCCESS
pattern $mInvalidIdentifier :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidIdentifier :: BotanErrorCode
InvalidIdentifier = BOTAN_FFI_INVALID_VERIFIER
pattern $mInvalidInput :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidInput :: BotanErrorCode
InvalidInput = BOTAN_FFI_ERROR_INVALID_INPUT
pattern $mBadMAC :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bBadMAC :: BotanErrorCode
BadMAC = BOTAN_FFI_ERROR_BAD_MAC
pattern $mInsufficientBufferSpace :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInsufficientBufferSpace :: BotanErrorCode
InsufficientBufferSpace = BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
pattern $mStringConversionError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bStringConversionError :: BotanErrorCode
StringConversionError = BOTAN_FFI_ERROR_STRING_CONVERSION_ERROR
pattern $mExceptionThrown :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bExceptionThrown :: BotanErrorCode
ExceptionThrown = BOTAN_FFI_ERROR_EXCEPTION_THROWN
pattern $mOutOfMemory :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bOutOfMemory :: BotanErrorCode
OutOfMemory = BOTAN_FFI_ERROR_OUT_OF_MEMORY
pattern $mSystemError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bSystemError :: BotanErrorCode
SystemError = BOTAN_FFI_ERROR_SYSTEM_ERROR
pattern $mInternalError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInternalError :: BotanErrorCode
InternalError = BOTAN_FFI_ERROR_INTERNAL_ERROR
pattern $mBadFlag :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bBadFlag :: BotanErrorCode
BadFlag = BOTAN_FFI_ERROR_BAD_FLAG
pattern $mNullPointer :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bNullPointer :: BotanErrorCode
NullPointer = BOTAN_FFI_ERROR_NULL_POINTER
pattern $mBadParameter :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bBadParameter :: BotanErrorCode
BadParameter = BOTAN_FFI_ERROR_BAD_PARAMETER
pattern $mKeyNotSet :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bKeyNotSet :: BotanErrorCode
KeyNotSet = BOTAN_FFI_ERROR_KEY_NOT_SET
pattern $mInvalidKeyLength :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidKeyLength :: BotanErrorCode
InvalidKeyLength = BOTAN_FFI_ERROR_INVALID_KEY_LENGTH
pattern $mInvalidObjectState :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidObjectState :: BotanErrorCode
InvalidObjectState = BOTAN_FFI_ERROR_INVALID_OBJECT_STATE
pattern $mNotImplemented :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bNotImplemented :: BotanErrorCode
NotImplemented = BOTAN_FFI_ERROR_NOT_IMPLEMENTED
pattern $mInvalidObject :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bInvalidObject :: BotanErrorCode
InvalidObject = BOTAN_FFI_ERROR_INVALID_OBJECT
pattern $mTLSError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bTLSError :: BotanErrorCode
TLSError = BOTAN_FFI_ERROR_TLS_ERROR
pattern $mHttpError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bHttpError :: BotanErrorCode
HttpError = BOTAN_FFI_ERROR_HTTP_ERROR
pattern $mRoughtimeError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bRoughtimeError :: BotanErrorCode
RoughtimeError = BOTAN_FFI_ERROR_ROUGHTIME_ERROR
pattern $mUnknownError :: forall {r}. BotanErrorCode -> ((# #) -> r) -> ((# #) -> r) -> r
$bUnknownError :: BotanErrorCode
UnknownError = BOTAN_FFI_ERROR_UNKNOWN_ERROR

{-
Botan error code functions
-}

-- | Convert an error code into a string. Returns "Unknown error" if the error code is not a known one.
botanErrorDescription :: BotanErrorCode -> IO ByteString
botanErrorDescription :: BotanErrorCode -> IO ByteString
botanErrorDescription BotanErrorCode
e = do
    ConstPtr CChar
descPtr <- BotanErrorCode -> IO (ConstPtr CChar)
botan_error_description BotanErrorCode
e
    CString -> IO ByteString
peekCString (ConstPtr CChar -> CString
forall a. ConstPtr a -> Ptr a
unConstPtr ConstPtr CChar
descPtr)

-- | Returns a static string stored in a thread local variable which contains the last exception message thrown.
--  WARNING: This string buffer is overwritten on the next call to the FFI layer
botanErrorLastExceptionMessage :: IO ErrorMessage
botanErrorLastExceptionMessage :: IO ByteString
botanErrorLastExceptionMessage = do
    ConstPtr CChar
msgPtr <- IO (ConstPtr CChar)
botan_error_last_exception_message
    CString -> IO ByteString
peekCString (ConstPtr CChar -> CString
forall a. ConstPtr a -> Ptr a
unConstPtr ConstPtr CChar
msgPtr)

type ErrorMessage = ByteString

{-
Exceptions
-}

-- | The SomeBotanException type is the root of the botan exception type hierarchy.
data SomeBotanException = forall e . Exception e => SomeBotanException e

instance Show SomeBotanException where
    show :: SomeBotanException -> String
show (SomeBotanException e
e) = e -> String
forall a. Show a => a -> String
show e
e

instance Exception SomeBotanException

toBotanException :: Exception e => e -> SomeException
toBotanException :: forall e. Exception e => e -> SomeException
toBotanException = SomeBotanException -> SomeException
forall e. Exception e => e -> SomeException
toException (SomeBotanException -> SomeException)
-> (e -> SomeBotanException) -> e -> SomeException
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> SomeBotanException
forall e. Exception e => e -> SomeBotanException
SomeBotanException

fromBotanException :: Exception e => SomeException -> Maybe e
fromBotanException :: forall e. Exception e => SomeException -> Maybe e
fromBotanException SomeException
x = do
    SomeBotanException e
a <- SomeException -> Maybe SomeBotanException
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
x
    e -> Maybe e
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast e
a

data InvalidVerifierException
    = InvalidVerifierException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InvalidVerifierException -> ShowS
[InvalidVerifierException] -> ShowS
InvalidVerifierException -> String
(Int -> InvalidVerifierException -> ShowS)
-> (InvalidVerifierException -> String)
-> ([InvalidVerifierException] -> ShowS)
-> Show InvalidVerifierException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InvalidVerifierException -> ShowS
showsPrec :: Int -> InvalidVerifierException -> ShowS
$cshow :: InvalidVerifierException -> String
show :: InvalidVerifierException -> String
$cshowList :: [InvalidVerifierException] -> ShowS
showList :: [InvalidVerifierException] -> ShowS
Show)

instance Exception InvalidVerifierException where
    toException :: InvalidVerifierException -> SomeException
toException = InvalidVerifierException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InvalidVerifierException
fromException = SomeException -> Maybe InvalidVerifierException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InvalidInputException
    = InvalidInputException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InvalidInputException -> ShowS
[InvalidInputException] -> ShowS
InvalidInputException -> String
(Int -> InvalidInputException -> ShowS)
-> (InvalidInputException -> String)
-> ([InvalidInputException] -> ShowS)
-> Show InvalidInputException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InvalidInputException -> ShowS
showsPrec :: Int -> InvalidInputException -> ShowS
$cshow :: InvalidInputException -> String
show :: InvalidInputException -> String
$cshowList :: [InvalidInputException] -> ShowS
showList :: [InvalidInputException] -> ShowS
Show)

instance Exception InvalidInputException where
    toException :: InvalidInputException -> SomeException
toException = InvalidInputException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InvalidInputException
fromException = SomeException -> Maybe InvalidInputException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data BadMACException
    = BadMACException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> BadMACException -> ShowS
[BadMACException] -> ShowS
BadMACException -> String
(Int -> BadMACException -> ShowS)
-> (BadMACException -> String)
-> ([BadMACException] -> ShowS)
-> Show BadMACException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BadMACException -> ShowS
showsPrec :: Int -> BadMACException -> ShowS
$cshow :: BadMACException -> String
show :: BadMACException -> String
$cshowList :: [BadMACException] -> ShowS
showList :: [BadMACException] -> ShowS
Show)

instance Exception BadMACException where
    toException :: BadMACException -> SomeException
toException = BadMACException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe BadMACException
fromException = SomeException -> Maybe BadMACException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InsufficientBufferSpaceException
    = InsufficientBufferSpaceException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InsufficientBufferSpaceException -> ShowS
[InsufficientBufferSpaceException] -> ShowS
InsufficientBufferSpaceException -> String
(Int -> InsufficientBufferSpaceException -> ShowS)
-> (InsufficientBufferSpaceException -> String)
-> ([InsufficientBufferSpaceException] -> ShowS)
-> Show InsufficientBufferSpaceException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InsufficientBufferSpaceException -> ShowS
showsPrec :: Int -> InsufficientBufferSpaceException -> ShowS
$cshow :: InsufficientBufferSpaceException -> String
show :: InsufficientBufferSpaceException -> String
$cshowList :: [InsufficientBufferSpaceException] -> ShowS
showList :: [InsufficientBufferSpaceException] -> ShowS
Show)

instance Exception InsufficientBufferSpaceException where
    toException :: InsufficientBufferSpaceException -> SomeException
toException = InsufficientBufferSpaceException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InsufficientBufferSpaceException
fromException = SomeException -> Maybe InsufficientBufferSpaceException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data StringConversionException
    = StringConversionException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> StringConversionException -> ShowS
[StringConversionException] -> ShowS
StringConversionException -> String
(Int -> StringConversionException -> ShowS)
-> (StringConversionException -> String)
-> ([StringConversionException] -> ShowS)
-> Show StringConversionException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> StringConversionException -> ShowS
showsPrec :: Int -> StringConversionException -> ShowS
$cshow :: StringConversionException -> String
show :: StringConversionException -> String
$cshowList :: [StringConversionException] -> ShowS
showList :: [StringConversionException] -> ShowS
Show)

instance Exception StringConversionException where
    toException :: StringConversionException -> SomeException
toException = StringConversionException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe StringConversionException
fromException = SomeException -> Maybe StringConversionException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data ExceptionThrownException
    = ExceptionThrownException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> ExceptionThrownException -> ShowS
[ExceptionThrownException] -> ShowS
ExceptionThrownException -> String
(Int -> ExceptionThrownException -> ShowS)
-> (ExceptionThrownException -> String)
-> ([ExceptionThrownException] -> ShowS)
-> Show ExceptionThrownException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExceptionThrownException -> ShowS
showsPrec :: Int -> ExceptionThrownException -> ShowS
$cshow :: ExceptionThrownException -> String
show :: ExceptionThrownException -> String
$cshowList :: [ExceptionThrownException] -> ShowS
showList :: [ExceptionThrownException] -> ShowS
Show)

instance Exception ExceptionThrownException where
    toException :: ExceptionThrownException -> SomeException
toException = ExceptionThrownException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe ExceptionThrownException
fromException = SomeException -> Maybe ExceptionThrownException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data OutOfMemoryException
    = OutOfMemoryException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> OutOfMemoryException -> ShowS
[OutOfMemoryException] -> ShowS
OutOfMemoryException -> String
(Int -> OutOfMemoryException -> ShowS)
-> (OutOfMemoryException -> String)
-> ([OutOfMemoryException] -> ShowS)
-> Show OutOfMemoryException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OutOfMemoryException -> ShowS
showsPrec :: Int -> OutOfMemoryException -> ShowS
$cshow :: OutOfMemoryException -> String
show :: OutOfMemoryException -> String
$cshowList :: [OutOfMemoryException] -> ShowS
showList :: [OutOfMemoryException] -> ShowS
Show)

instance Exception OutOfMemoryException where
    toException :: OutOfMemoryException -> SomeException
toException = OutOfMemoryException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe OutOfMemoryException
fromException = SomeException -> Maybe OutOfMemoryException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data SystemErrorException
    = SystemErrorException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> SystemErrorException -> ShowS
[SystemErrorException] -> ShowS
SystemErrorException -> String
(Int -> SystemErrorException -> ShowS)
-> (SystemErrorException -> String)
-> ([SystemErrorException] -> ShowS)
-> Show SystemErrorException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SystemErrorException -> ShowS
showsPrec :: Int -> SystemErrorException -> ShowS
$cshow :: SystemErrorException -> String
show :: SystemErrorException -> String
$cshowList :: [SystemErrorException] -> ShowS
showList :: [SystemErrorException] -> ShowS
Show)

instance Exception SystemErrorException where
    toException :: SystemErrorException -> SomeException
toException = SystemErrorException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe SystemErrorException
fromException = SomeException -> Maybe SystemErrorException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InternalErrorException
    = InternalErrorException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InternalErrorException -> ShowS
[InternalErrorException] -> ShowS
InternalErrorException -> String
(Int -> InternalErrorException -> ShowS)
-> (InternalErrorException -> String)
-> ([InternalErrorException] -> ShowS)
-> Show InternalErrorException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InternalErrorException -> ShowS
showsPrec :: Int -> InternalErrorException -> ShowS
$cshow :: InternalErrorException -> String
show :: InternalErrorException -> String
$cshowList :: [InternalErrorException] -> ShowS
showList :: [InternalErrorException] -> ShowS
Show)

instance Exception InternalErrorException where
    toException :: InternalErrorException -> SomeException
toException = InternalErrorException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InternalErrorException
fromException = SomeException -> Maybe InternalErrorException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data BadFlagException
    = BadFlagException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> BadFlagException -> ShowS
[BadFlagException] -> ShowS
BadFlagException -> String
(Int -> BadFlagException -> ShowS)
-> (BadFlagException -> String)
-> ([BadFlagException] -> ShowS)
-> Show BadFlagException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BadFlagException -> ShowS
showsPrec :: Int -> BadFlagException -> ShowS
$cshow :: BadFlagException -> String
show :: BadFlagException -> String
$cshowList :: [BadFlagException] -> ShowS
showList :: [BadFlagException] -> ShowS
Show)

instance Exception BadFlagException where
    toException :: BadFlagException -> SomeException
toException = BadFlagException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe BadFlagException
fromException = SomeException -> Maybe BadFlagException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data NullPointerException
    = NullPointerException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> NullPointerException -> ShowS
[NullPointerException] -> ShowS
NullPointerException -> String
(Int -> NullPointerException -> ShowS)
-> (NullPointerException -> String)
-> ([NullPointerException] -> ShowS)
-> Show NullPointerException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NullPointerException -> ShowS
showsPrec :: Int -> NullPointerException -> ShowS
$cshow :: NullPointerException -> String
show :: NullPointerException -> String
$cshowList :: [NullPointerException] -> ShowS
showList :: [NullPointerException] -> ShowS
Show)

instance Exception NullPointerException where
    toException :: NullPointerException -> SomeException
toException = NullPointerException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe NullPointerException
fromException = SomeException -> Maybe NullPointerException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data BadParameterException
    = BadParameterException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> BadParameterException -> ShowS
[BadParameterException] -> ShowS
BadParameterException -> String
(Int -> BadParameterException -> ShowS)
-> (BadParameterException -> String)
-> ([BadParameterException] -> ShowS)
-> Show BadParameterException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BadParameterException -> ShowS
showsPrec :: Int -> BadParameterException -> ShowS
$cshow :: BadParameterException -> String
show :: BadParameterException -> String
$cshowList :: [BadParameterException] -> ShowS
showList :: [BadParameterException] -> ShowS
Show)

instance Exception BadParameterException where
    toException :: BadParameterException -> SomeException
toException = BadParameterException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe BadParameterException
fromException = SomeException -> Maybe BadParameterException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data KeyNotSetException
    = KeyNotSetException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> KeyNotSetException -> ShowS
[KeyNotSetException] -> ShowS
KeyNotSetException -> String
(Int -> KeyNotSetException -> ShowS)
-> (KeyNotSetException -> String)
-> ([KeyNotSetException] -> ShowS)
-> Show KeyNotSetException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KeyNotSetException -> ShowS
showsPrec :: Int -> KeyNotSetException -> ShowS
$cshow :: KeyNotSetException -> String
show :: KeyNotSetException -> String
$cshowList :: [KeyNotSetException] -> ShowS
showList :: [KeyNotSetException] -> ShowS
Show)

instance Exception KeyNotSetException where
    toException :: KeyNotSetException -> SomeException
toException = KeyNotSetException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe KeyNotSetException
fromException = SomeException -> Maybe KeyNotSetException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InvalidKeyLengthException
    = InvalidKeyLengthException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InvalidKeyLengthException -> ShowS
[InvalidKeyLengthException] -> ShowS
InvalidKeyLengthException -> String
(Int -> InvalidKeyLengthException -> ShowS)
-> (InvalidKeyLengthException -> String)
-> ([InvalidKeyLengthException] -> ShowS)
-> Show InvalidKeyLengthException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InvalidKeyLengthException -> ShowS
showsPrec :: Int -> InvalidKeyLengthException -> ShowS
$cshow :: InvalidKeyLengthException -> String
show :: InvalidKeyLengthException -> String
$cshowList :: [InvalidKeyLengthException] -> ShowS
showList :: [InvalidKeyLengthException] -> ShowS
Show)

instance Exception InvalidKeyLengthException where
    toException :: InvalidKeyLengthException -> SomeException
toException = InvalidKeyLengthException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InvalidKeyLengthException
fromException = SomeException -> Maybe InvalidKeyLengthException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InvalidObjectStateException
    = InvalidObjectStateException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InvalidObjectStateException -> ShowS
[InvalidObjectStateException] -> ShowS
InvalidObjectStateException -> String
(Int -> InvalidObjectStateException -> ShowS)
-> (InvalidObjectStateException -> String)
-> ([InvalidObjectStateException] -> ShowS)
-> Show InvalidObjectStateException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InvalidObjectStateException -> ShowS
showsPrec :: Int -> InvalidObjectStateException -> ShowS
$cshow :: InvalidObjectStateException -> String
show :: InvalidObjectStateException -> String
$cshowList :: [InvalidObjectStateException] -> ShowS
showList :: [InvalidObjectStateException] -> ShowS
Show)

instance Exception InvalidObjectStateException where
    toException :: InvalidObjectStateException -> SomeException
toException = InvalidObjectStateException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InvalidObjectStateException
fromException = SomeException -> Maybe InvalidObjectStateException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data NotImplementedException
    = NotImplementedException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> NotImplementedException -> ShowS
[NotImplementedException] -> ShowS
NotImplementedException -> String
(Int -> NotImplementedException -> ShowS)
-> (NotImplementedException -> String)
-> ([NotImplementedException] -> ShowS)
-> Show NotImplementedException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NotImplementedException -> ShowS
showsPrec :: Int -> NotImplementedException -> ShowS
$cshow :: NotImplementedException -> String
show :: NotImplementedException -> String
$cshowList :: [NotImplementedException] -> ShowS
showList :: [NotImplementedException] -> ShowS
Show)

instance Exception NotImplementedException where
    toException :: NotImplementedException -> SomeException
toException = NotImplementedException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe NotImplementedException
fromException = SomeException -> Maybe NotImplementedException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

data InvalidObjectException
    = InvalidObjectException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> InvalidObjectException -> ShowS
[InvalidObjectException] -> ShowS
InvalidObjectException -> String
(Int -> InvalidObjectException -> ShowS)
-> (InvalidObjectException -> String)
-> ([InvalidObjectException] -> ShowS)
-> Show InvalidObjectException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InvalidObjectException -> ShowS
showsPrec :: Int -> InvalidObjectException -> ShowS
$cshow :: InvalidObjectException -> String
show :: InvalidObjectException -> String
$cshowList :: [InvalidObjectException] -> ShowS
showList :: [InvalidObjectException] -> ShowS
Show)

instance Exception InvalidObjectException where
    toException :: InvalidObjectException -> SomeException
toException = InvalidObjectException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe InvalidObjectException
fromException = SomeException -> Maybe InvalidObjectException
forall e. Exception e => SomeException -> Maybe e
fromBotanException
    
data UnknownException
    = UnknownException BotanErrorCode ErrorMessage CallStack
    deriving (Int -> UnknownException -> ShowS
[UnknownException] -> ShowS
UnknownException -> String
(Int -> UnknownException -> ShowS)
-> (UnknownException -> String)
-> ([UnknownException] -> ShowS)
-> Show UnknownException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UnknownException -> ShowS
showsPrec :: Int -> UnknownException -> ShowS
$cshow :: UnknownException -> String
show :: UnknownException -> String
$cshowList :: [UnknownException] -> ShowS
showList :: [UnknownException] -> ShowS
Show)

instance Exception UnknownException where
    toException :: UnknownException -> SomeException
toException = UnknownException -> SomeException
forall e. Exception e => e -> SomeException
toBotanException
    fromException :: SomeException -> Maybe UnknownException
fromException = SomeException -> Maybe UnknownException
forall e. Exception e => SomeException -> Maybe e
fromBotanException

{-
Throwing exceptions
-}

throwBotanError :: HasCallStack => BotanErrorCode -> IO a
throwBotanError :: forall a. HasCallStack => BotanErrorCode -> IO a
throwBotanError BotanErrorCode
r = BotanErrorCode -> CallStack -> IO a
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack BotanErrorCode
r CallStack
HasCallStack => CallStack
callStack

throwBotanIfNegative :: HasCallStack => IO BotanErrorCode -> IO BotanErrorCode
throwBotanIfNegative :: HasCallStack => IO BotanErrorCode -> IO BotanErrorCode
throwBotanIfNegative IO BotanErrorCode
act = do
    BotanErrorCode
e <- IO BotanErrorCode
act
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (BotanErrorCode
e BotanErrorCode -> BotanErrorCode -> Bool
forall a. Ord a => a -> a -> Bool
< BotanErrorCode
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> CallStack -> IO ()
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack (BotanErrorCode -> BotanErrorCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral BotanErrorCode
e) CallStack
HasCallStack => CallStack
callStack
    BotanErrorCode -> IO BotanErrorCode
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return BotanErrorCode
e

throwBotanIfNegative_ :: HasCallStack => IO BotanErrorCode -> IO ()
throwBotanIfNegative_ :: HasCallStack => IO BotanErrorCode -> IO ()
throwBotanIfNegative_ IO BotanErrorCode
act = do
    BotanErrorCode
e <- IO BotanErrorCode
act
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (BotanErrorCode
e BotanErrorCode -> BotanErrorCode -> Bool
forall a. Ord a => a -> a -> Bool
< BotanErrorCode
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> CallStack -> IO ()
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack (BotanErrorCode -> BotanErrorCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral BotanErrorCode
e) CallStack
HasCallStack => CallStack
callStack

-- TODO: Rename to throwBotanCatchingInvalidIdentifier, make:
-- throwBotanCatchingSuccess :: HasCallStack => IO BotanErrorCode -> IO Bool
-- throwBotanCatchingSuccess act = do
--     result <- act
--     case result of
--         BOTAN_FFI_SUCCESS           -> return True
--         _                           -> throwBotanErrorWithCallstack (fromIntegral result) callStack
-- NOTE: Catches 0 / Success as True and 1 / InvalidIdentifier as False, throws all other values
throwBotanCatchingSuccess :: HasCallStack => IO BotanErrorCode -> IO Bool
throwBotanCatchingSuccess :: HasCallStack => IO BotanErrorCode -> IO Bool
throwBotanCatchingSuccess IO BotanErrorCode
act = do
    BotanErrorCode
result <- IO BotanErrorCode
act
    case BotanErrorCode
result of
        BotanErrorCode
BOTAN_FFI_SUCCESS           -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
        BotanErrorCode
BOTAN_FFI_INVALID_VERIFIER  -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        BotanErrorCode
_                           -> BotanErrorCode -> CallStack -> IO Bool
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack (BotanErrorCode -> BotanErrorCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral BotanErrorCode
result) CallStack
HasCallStack => CallStack
callStack

-- NOTE: Catches 1 as True and 0 as False, throws all other values
throwBotanCatchingBool :: HasCallStack => IO BotanErrorCode -> IO Bool
throwBotanCatchingBool :: HasCallStack => IO BotanErrorCode -> IO Bool
throwBotanCatchingBool IO BotanErrorCode
act = do
    BotanErrorCode
result <- IO BotanErrorCode
act
    case BotanErrorCode
result of
        BotanErrorCode
0 -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        BotanErrorCode
1 -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
        BotanErrorCode
_ -> BotanErrorCode -> CallStack -> IO Bool
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack BotanErrorCode
result CallStack
HasCallStack => CallStack
callStack


-- NOTE: Catches positive numbers including zero, throws all other values
-- Equivalent to fromIntegral . throwBotanIfNegative
throwBotanCatchingInt :: HasCallStack => IO BotanErrorCode -> IO Int
throwBotanCatchingInt :: HasCallStack => IO BotanErrorCode -> IO Int
throwBotanCatchingInt IO BotanErrorCode
act = do
    BotanErrorCode
result <- IO BotanErrorCode
act
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (BotanErrorCode
result BotanErrorCode -> BotanErrorCode -> Bool
forall a. Ord a => a -> a -> Bool
< BotanErrorCode
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> CallStack -> IO ()
forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack (BotanErrorCode -> BotanErrorCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral BotanErrorCode
result) CallStack
HasCallStack => CallStack
callStack
    Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanErrorCode -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral BotanErrorCode
result)

throwBotanErrorWithCallstack :: BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack :: forall a. BotanErrorCode -> CallStack -> IO a
throwBotanErrorWithCallstack BotanErrorCode
e CallStack
cs =  do
    ByteString
emsg <- IO ByteString
botanErrorLastExceptionMessage
    case BotanErrorCode
e of
        -- BOTAN_FFI_SUCCESS                           -> throwIO $ SUCCESS e cs
        BotanErrorCode
BOTAN_FFI_INVALID_VERIFIER                  -> InvalidVerifierException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InvalidVerifierException -> IO a)
-> InvalidVerifierException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> InvalidVerifierException
InvalidVerifierException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INVALID_INPUT               -> InvalidInputException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InvalidInputException -> IO a) -> InvalidInputException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> InvalidInputException
InvalidInputException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_BAD_MAC                     -> BadMACException -> IO a
forall e a. Exception e => e -> IO a
throwIO (BadMACException -> IO a) -> BadMACException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> BadMACException
BadMACException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE   -> InsufficientBufferSpaceException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InsufficientBufferSpaceException -> IO a)
-> InsufficientBufferSpaceException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> InsufficientBufferSpaceException
InsufficientBufferSpaceException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_STRING_CONVERSION_ERROR     -> StringConversionException -> IO a
forall e a. Exception e => e -> IO a
throwIO (StringConversionException -> IO a)
-> StringConversionException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> StringConversionException
StringConversionException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_EXCEPTION_THROWN            -> ExceptionThrownException -> IO a
forall e a. Exception e => e -> IO a
throwIO (ExceptionThrownException -> IO a)
-> ExceptionThrownException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> ExceptionThrownException
ExceptionThrownException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_OUT_OF_MEMORY               -> OutOfMemoryException -> IO a
forall e a. Exception e => e -> IO a
throwIO (OutOfMemoryException -> IO a) -> OutOfMemoryException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> OutOfMemoryException
OutOfMemoryException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_SYSTEM_ERROR                -> SystemErrorException -> IO a
forall e a. Exception e => e -> IO a
throwIO (SystemErrorException -> IO a) -> SystemErrorException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> SystemErrorException
SystemErrorException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INTERNAL_ERROR              -> InternalErrorException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InternalErrorException -> IO a) -> InternalErrorException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> InternalErrorException
InternalErrorException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_BAD_FLAG                    -> BadFlagException -> IO a
forall e a. Exception e => e -> IO a
throwIO (BadFlagException -> IO a) -> BadFlagException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> BadFlagException
BadFlagException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_NULL_POINTER                -> NullPointerException -> IO a
forall e a. Exception e => e -> IO a
throwIO (NullPointerException -> IO a) -> NullPointerException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> NullPointerException
NullPointerException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_BAD_PARAMETER               -> BadParameterException -> IO a
forall e a. Exception e => e -> IO a
throwIO (BadParameterException -> IO a) -> BadParameterException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> BadParameterException
BadParameterException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_KEY_NOT_SET                 -> KeyNotSetException -> IO a
forall e a. Exception e => e -> IO a
throwIO (KeyNotSetException -> IO a) -> KeyNotSetException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> KeyNotSetException
KeyNotSetException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INVALID_KEY_LENGTH          -> InvalidKeyLengthException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InvalidKeyLengthException -> IO a)
-> InvalidKeyLengthException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> InvalidKeyLengthException
InvalidKeyLengthException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INVALID_OBJECT_STATE        -> InvalidObjectStateException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InvalidObjectStateException -> IO a)
-> InvalidObjectStateException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> InvalidObjectStateException
InvalidObjectStateException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_NOT_IMPLEMENTED             -> NotImplementedException -> IO a
forall e a. Exception e => e -> IO a
throwIO (NotImplementedException -> IO a)
-> NotImplementedException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode
-> ByteString -> CallStack -> NotImplementedException
NotImplementedException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
BOTAN_FFI_ERROR_INVALID_OBJECT              -> InvalidObjectException -> IO a
forall e a. Exception e => e -> IO a
throwIO (InvalidObjectException -> IO a) -> InvalidObjectException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> InvalidObjectException
InvalidObjectException BotanErrorCode
e ByteString
emsg CallStack
cs
        BotanErrorCode
_                                           -> UnknownException -> IO a
forall e a. Exception e => e -> IO a
throwIO (UnknownException -> IO a) -> UnknownException -> IO a
forall a b. (a -> b) -> a -> b
$ BotanErrorCode -> ByteString -> CallStack -> UnknownException
UnknownException BotanErrorCode
e ByteString
emsg CallStack
cs

-- TODO: catchingBotan
-- r0 <- botan_foo
-- if r0 < 0
--   then pure r0
--   else do
--     r1 <- botan_bar

tryBotan :: IO a -> IO (Either SomeBotanException a)
tryBotan :: forall a. IO a -> IO (Either SomeBotanException a)
tryBotan = IO a -> IO (Either SomeBotanException a)
forall e a. Exception e => IO a -> IO (Either e a)
try

catchBotan :: IO a -> (SomeBotanException -> IO a) -> IO a
catchBotan :: forall a. IO a -> (SomeBotanException -> IO a) -> IO a
catchBotan = IO a -> (SomeBotanException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch

handleBotan :: (SomeBotanException -> IO a) -> IO a -> IO a
handleBotan :: forall a. (SomeBotanException -> IO a) -> IO a -> IO a
handleBotan = (IO a -> (SomeBotanException -> IO a) -> IO a)
-> (SomeBotanException -> IO a) -> IO a -> IO a
forall a b c. (a -> b -> c) -> b -> a -> c
flip IO a -> (SomeBotanException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch