#ifndef ENABLE_INTERNAL_DOCUMENTATION
#endif
module OpenCV.Internal.Exception
(
CvException(..)
, CoerceMatError(..)
, ExpectationError(..)
, CvCppException
, handleCvException
, cvExcept
, cvExceptU
, CvExcept
, CvExceptT
, pureExcept
, exceptError
, exceptErrorIO
, exceptErrorM
, runCvExceptST
, unsafeCvExcept
, unsafeWrapException
) where
import "base" Control.Monad.ST ( ST, runST )
import "base" Control.Exception ( Exception, mask_, throw, throwIO )
import "base" Control.Monad ( (<=<) )
import "base" Data.Functor.Identity
import "base" Data.Monoid ( (<>) )
import "base" Foreign.C.String ( peekCString )
import "base" Foreign.ForeignPtr ( ForeignPtr, withForeignPtr )
import "base" Foreign.Ptr ( Ptr, nullPtr )
import "base" System.IO.Unsafe ( unsafePerformIO )
import qualified "inline-c" Language.C.Inline as C
import qualified "inline-c" Language.C.Inline.Unsafe as CU
import qualified "inline-c-cpp" Language.C.Inline.Cpp as C
import "template-haskell" Language.Haskell.TH.Quote ( QuasiQuoter, quoteExp )
import "this" OpenCV.Internal.C.Inline ( openCvCtx )
import "this" OpenCV.Internal.C.Types
import "this" OpenCV.Internal.Core.Types.Mat.Depth
import "this" OpenCV.Internal ( objFromPtr )
import "transformers" Control.Monad.Trans.Except
C.context openCvCtx
C.include "opencv2/core.hpp"
C.using "namespace cv"
data CvException
= BindingException !CvCppException
| CoerceMatError ![CoerceMatError]
deriving Show
data CoerceMatError
= ShapeError !(ExpectationError Int)
| SizeError !Int !(ExpectationError Int)
| ChannelError !(ExpectationError Int)
| DepthError !(ExpectationError Depth)
deriving Show
data ExpectationError a
= ExpectationError
{ expectedValue :: !a
, actualValue :: !a
} deriving (Show, Functor)
instance Exception CvException
newtype CvCppException = CvCppException { unCvCppException :: ForeignPtr (C CvCppException) }
type instance C CvCppException = C'CvCppException
instance WithPtr CvCppException where
withPtr = withForeignPtr . unCvCppException
instance FromPtr CvCppException where
fromPtr = objFromPtr CvCppException $ \ptr ->
[CU.exp| void { delete $(Exception * ptr) }|]
instance Show CvCppException where
show cvException = unsafePerformIO $
withPtr cvException $ \cvExceptionPtr -> do
charPtr <- [CU.exp| const char * { $(Exception * cvExceptionPtr)->what() } |]
peekCString charPtr
handleCvException
:: IO a
-> IO (Ptr (C CvCppException))
-> IO (Either CvException a)
handleCvException okAct act = mask_ $ do
exceptionPtr <- act
if exceptionPtr /= nullPtr
then do cppErr <- fromPtr (pure exceptionPtr)
pure $ Left $ BindingException cppErr
else Right <$> okAct
cvExcept :: QuasiQuoter
cvExcept = C.block {quoteExp = \s -> quoteExp C.block $ cvExceptWrap s}
cvExceptU :: QuasiQuoter
cvExceptU = CU.block {quoteExp = \s -> quoteExp CU.block $ cvExceptWrap s}
cvExceptWrap :: String -> String
cvExceptWrap s = unlines
[ "Exception * {"
, " try"
, " { " <> s <> ""
, " return NULL;"
, " }"
, " catch (const cv::Exception & e)"
, " {"
, " return new cv::Exception(e);"
, " }"
, "}"
]
type CvExcept a = Except CvException a
type CvExceptT m a = ExceptT CvException m a
pureExcept :: (Applicative m) => CvExcept a -> CvExceptT m a
pureExcept = mapExceptT (pure . runIdentity)
exceptError :: CvExcept a -> a
exceptError = either throw id . runExcept
exceptErrorIO :: CvExceptT IO a -> IO a
exceptErrorIO = either throwIO pure <=< runExceptT
exceptErrorM :: (Monad m) => CvExceptT m a -> m a
exceptErrorM = either throw pure <=< runExceptT
runCvExceptST :: (forall s. CvExceptT (ST s) a) -> CvExcept a
runCvExceptST act = except $ runST $ runExceptT act
unsafeCvExcept :: CvExceptT IO a -> CvExcept a
unsafeCvExcept = mapExceptT (Identity . unsafePerformIO)
unsafeWrapException :: IO (Either CvException a) -> CvExcept a
unsafeWrapException = unsafeCvExcept . ExceptT