never executed always true always false
1 {-# language CPP #-}
2 {-# language DeriveFunctor #-}
3 {-# language QuasiQuotes #-}
4 {-# language RankNTypes #-}
5 {-# language TemplateHaskell #-}
6
7 #ifndef ENABLE_INTERNAL_DOCUMENTATION
8 {-# OPTIONS_HADDOCK hide #-}
9 #endif
10
11 module OpenCV.Internal.Exception
12 ( -- * Exception type
13 CvException(..)
14 , CoerceMatError(..)
15 , ExpectationError(..)
16 , CvCppException
17
18 -- * Handling C++ exceptions
19 , handleCvException
20
21 -- * Quasi quoters
22 , cvExcept
23 , cvExceptU
24
25 -- * Monadic interface
26 , CvExcept
27 , CvExceptT
28 , pureExcept
29
30 -- * Promoting exceptions to errors
31 , exceptError
32 , exceptErrorIO
33 , exceptErrorM
34 , runCvExceptST
35
36 -- * Unsafe stuff
37 , unsafeCvExcept
38 , unsafeWrapException
39 ) where
40
41 import "base" Control.Monad.ST ( ST, runST )
42 import "base" Control.Exception ( Exception, mask_, throw, throwIO )
43 import "base" Control.Monad ( (<=<) )
44 import "base" Data.Functor.Identity
45 import "base" Data.Monoid ( (<>) )
46 import "base" Foreign.C.String ( peekCString )
47 import "base" Foreign.ForeignPtr ( ForeignPtr, withForeignPtr )
48 import "base" Foreign.Ptr ( Ptr, nullPtr )
49 import "base" System.IO.Unsafe ( unsafePerformIO )
50 import qualified "inline-c" Language.C.Inline as C
51 import qualified "inline-c" Language.C.Inline.Unsafe as CU
52 import qualified "inline-c-cpp" Language.C.Inline.Cpp as C
53 import "template-haskell" Language.Haskell.TH.Quote ( QuasiQuoter, quoteExp )
54 import "this" OpenCV.Internal.C.Inline ( openCvCtx )
55 import "this" OpenCV.Internal.C.Types
56 import "this" OpenCV.Internal.Core.Types.Mat.Depth
57 import "this" OpenCV.Internal ( objFromPtr )
58 import "transformers" Control.Monad.Trans.Except
59
60 --------------------------------------------------------------------------------
61
62 C.context openCvCtx
63
64 C.include "opencv2/core.hpp"
65 C.using "namespace cv"
66
67
68 --------------------------------------------------------------------------------
69 -- Exceptions
70 --------------------------------------------------------------------------------
71
72 data CvException
73 = BindingException !CvCppException
74 | CoerceMatError ![CoerceMatError]
75 deriving Show
76
77 data CoerceMatError
78 = ShapeError !(ExpectationError Int)
79 | SizeError !Int !(ExpectationError Int)
80 | ChannelError !(ExpectationError Int)
81 | DepthError !(ExpectationError Depth)
82 deriving Show
83
84 data ExpectationError a
85 = ExpectationError
86 { expectedValue :: !a
87 , actualValue :: !a
88 } deriving (Show, Functor)
89
90 instance Exception CvException
91
92 newtype CvCppException = CvCppException { unCvCppException :: ForeignPtr (C CvCppException) }
93
94 type instance C CvCppException = C'CvCppException
95
96 instance WithPtr CvCppException where
97 withPtr = withForeignPtr . unCvCppException
98
99 instance FromPtr CvCppException where
100 fromPtr = objFromPtr CvCppException $ \ptr ->
101 [CU.exp| void { delete $(Exception * ptr) }|]
102
103 instance Show CvCppException where
104 show cvException = unsafePerformIO $
105 withPtr cvException $ \cvExceptionPtr -> do
106 charPtr <- [CU.exp| const char * { $(Exception * cvExceptionPtr)->what() } |]
107 peekCString charPtr
108
109 handleCvException
110 :: IO a
111 -> IO (Ptr (C CvCppException))
112 -> IO (Either CvException a)
113 handleCvException okAct act = mask_ $ do
114 exceptionPtr <- act
115 if exceptionPtr /= nullPtr
116 then do cppErr <- fromPtr (pure exceptionPtr)
117 pure $ Left $ BindingException cppErr
118 else Right <$> okAct
119
120 cvExcept :: QuasiQuoter
121 cvExcept = C.block {quoteExp = \s -> quoteExp C.block $ cvExceptWrap s}
122
123 cvExceptU :: QuasiQuoter
124 cvExceptU = CU.block {quoteExp = \s -> quoteExp CU.block $ cvExceptWrap s}
125
126 cvExceptWrap :: String -> String
127 cvExceptWrap s = unlines
128 [ "Exception * {"
129 , " try"
130 , " { " <> s <> ""
131 , " return NULL;"
132 , " }"
133 , " catch (const cv::Exception & e)"
134 , " {"
135 , " return new cv::Exception(e);"
136 , " }"
137 , "}"
138 ]
139
140 type CvExcept a = Except CvException a
141 type CvExceptT m a = ExceptT CvException m a
142
143 pureExcept :: (Applicative m) => CvExcept a -> CvExceptT m a
144 pureExcept = mapExceptT (pure . runIdentity)
145
146 exceptError :: CvExcept a -> a
147 exceptError = either throw id . runExcept
148
149 exceptErrorIO :: CvExceptT IO a -> IO a
150 exceptErrorIO = either throwIO pure <=< runExceptT
151
152 exceptErrorM :: (Monad m) => CvExceptT m a -> m a
153 exceptErrorM = either throw pure <=< runExceptT
154
155 runCvExceptST :: (forall s. CvExceptT (ST s) a) -> CvExcept a
156 runCvExceptST act = except $ runST $ runExceptT act
157
158 unsafeCvExcept :: CvExceptT IO a -> CvExcept a
159 unsafeCvExcept = mapExceptT (Identity . unsafePerformIO)
160
161 unsafeWrapException :: IO (Either CvException a) -> CvExcept a
162 unsafeWrapException = unsafeCvExcept . ExceptT