module Z.IO.Exception
(
SomeIOException(..)
, ioExceptionToException
, ioExceptionFromException
, IOEInfo(..)
, AlreadyExists(..)
, NoSuchThing(..)
, ResourceBusy(..)
, ResourceExhausted(..)
, EOF(..)
, IllegalOperation(..)
, PermissionDenied(..)
, UnsatisfiedConstraints(..)
, SystemError(..)
, ProtocolError(..)
, OtherError(..)
, InvalidArgument(..)
, InappropriateType(..)
, HardwareFault(..)
, UnsupportedOperation(..)
, TimeExpired(..)
, ResourceVanished(..)
, Interrupted(..)
, throwOOMIfNull
, throwUVIfMinus
, throwUVIfMinus_
, throwECLOSED
, throwECLOSEDSTM
, throwUVError
, module Control.Exception
, HasCallStack
, CallStack
, callStack
) where
import Control.Exception hiding (IOException)
import Control.Monad
import Control.Concurrent.STM
import Data.Typeable
import Foreign.Ptr
import Foreign.C.Types
import GHC.Stack
import Z.IO.UV.Errno
import Z.Data.CBytes (CBytes)
import qualified Z.Data.CBytes as CB
import qualified Z.Data.Text.ShowT as T
data SomeIOException = forall e . Exception e => SomeIOException e
deriving Typeable
instance Show SomeIOException where
show (SomeIOException e) = show e
instance Exception SomeIOException
ioExceptionToException :: Exception e => e -> SomeException
ioExceptionToException = toException . SomeIOException
ioExceptionFromException :: Exception e => SomeException -> Maybe e
ioExceptionFromException x = do
SomeIOException a <- fromException x
cast a
#define IOE(e) data e = e IOEInfo deriving (Show, Typeable); \
instance Exception e where \
{ toException = ioExceptionToException \
; fromException = ioExceptionFromException \
}
IOE(AlreadyExists)
IOE(NoSuchThing)
IOE(ResourceBusy)
IOE(ResourceExhausted)
IOE(EOF)
IOE(IllegalOperation)
IOE(PermissionDenied)
IOE(UnsatisfiedConstraints)
IOE(SystemError)
IOE(ProtocolError)
IOE(OtherError)
IOE(InvalidArgument)
IOE(InappropriateType)
IOE(HardwareFault)
IOE(UnsupportedOperation)
IOE(TimeExpired)
IOE(ResourceVanished)
IOE(Interrupted)
throwOOMIfNull :: HasCallStack
=> IO (Ptr a)
-> IO (Ptr a)
{-# INLINABLE throwOOMIfNull #-}
throwOOMIfNull f = do
addr <- f
if addr == nullPtr
then throwIO (ResourceExhausted (IOEInfo "OOM" "out of memory when doing allocation" callStack))
else return addr
throwUVIfMinus :: (HasCallStack, Integral a)
=> IO a
-> IO a
{-# INLINABLE throwUVIfMinus #-}
throwUVIfMinus f = do
errno <- f
let errno' = fromIntegral errno
if errno' < 0
then do
name <- uvErrName errno'
desc <- uvStdError errno'
throwUVError errno' (IOEInfo name desc callStack)
else return errno
throwUVIfMinus_ :: (HasCallStack, Integral a)
=> IO a
-> IO ()
{-# INLINABLE throwUVIfMinus_ #-}
throwUVIfMinus_ f = do
errno <- f
let errno' = fromIntegral errno
when (errno' < 0) $ do
name <- uvErrName errno'
desc <- uvStdError errno'
throwUVError errno' (IOEInfo name desc callStack)
throwECLOSED :: HasCallStack => IO a
throwECLOSED = throwIO (ResourceVanished
(IOEInfo "ECLOSED" "resource is closed" callStack))
throwECLOSEDSTM :: HasCallStack => STM a
throwECLOSEDSTM = throwSTM (ResourceVanished
(IOEInfo "ECLOSED" "resource is closed" callStack))
data IOEInfo = IOEInfo
{ ioeName :: CBytes
, ioeDescription :: CBytes
, ioeCallStack :: CallStack
}
instance Show IOEInfo where
show (IOEInfo errno desc cstack) =
"{name:" ++ CB.unpack errno ++
", description:" ++ CB.unpack desc ++
", callstack:" ++ prettyCallStack cstack ++ "}"
instance T.ShowT IOEInfo where
toTextBuilder _ (IOEInfo errno desc cstack) = do
"{name:"
T.unsafeFromBuilder(CB.toBuilder errno)
", description:"
T.unsafeFromBuilder (CB.toBuilder desc)
", callstack:"
T.stringUTF8 (prettyCallStack cstack)
"}"
throwUVError :: CInt -> IOEInfo -> IO a
throwUVError e info = case e of
UV_EOF -> throwIO (EOF info)
UV_E2BIG -> throwIO (ResourceExhausted info)
UV_EACCES -> throwIO (PermissionDenied info)
UV_EADDRINUSE -> throwIO (ResourceBusy info)
UV_EADDRNOTAVAIL -> throwIO (UnsupportedOperation info)
UV_EAFNOSUPPORT -> throwIO (UnsupportedOperation info)
UV_EAGAIN -> throwIO (ResourceExhausted info)
UV_EAI_ADDRFAMILY -> throwIO (UnsupportedOperation info)
UV_EAI_AGAIN -> throwIO (ResourceExhausted info)
UV_EAI_BADFLAGS -> throwIO (UnsupportedOperation info)
UV_EAI_BADHINTS -> throwIO (UnsupportedOperation info)
UV_EAI_CANCELED -> throwIO (ResourceVanished info)
UV_EAI_FAIL -> throwIO (OtherError info)
UV_EAI_FAMILY -> throwIO (UnsupportedOperation info)
UV_EAI_MEMORY -> throwIO (ResourceExhausted info)
UV_EAI_NODATA -> throwIO (NoSuchThing info)
UV_EAI_NONAME -> throwIO (NoSuchThing info)
UV_EAI_OVERFLOW -> throwIO (InvalidArgument info)
UV_EAI_PROTOCOL -> throwIO (ProtocolError info)
UV_EAI_SERVICE -> throwIO (UnsupportedOperation info)
UV_EAI_SOCKTYPE -> throwIO (UnsupportedOperation info)
UV_EALREADY -> throwIO (AlreadyExists info)
UV_EBADF -> throwIO (InvalidArgument info)
UV_EBUSY -> throwIO (ResourceBusy info)
UV_ECANCELED -> throwIO (ResourceVanished info)
UV_ECHARSET -> throwIO (OtherError info)
UV_ECONNABORTED -> throwIO (ResourceVanished info)
UV_ECONNREFUSED -> throwIO (NoSuchThing info)
UV_ECONNRESET -> throwIO (ResourceVanished info)
UV_EDESTADDRREQ -> throwIO (InvalidArgument info)
UV_EEXIST -> throwIO (AlreadyExists info)
UV_EFAULT -> throwIO (OtherError info)
UV_EFBIG -> throwIO (PermissionDenied info)
UV_EHOSTUNREACH -> throwIO (NoSuchThing info)
UV_EINTR -> throwIO (Interrupted info)
UV_EINVAL -> throwIO (InvalidArgument info)
UV_EIO -> throwIO (HardwareFault info)
UV_EISCONN -> throwIO (AlreadyExists info)
UV_EISDIR -> throwIO (InappropriateType info)
UV_ELOOP -> throwIO (InvalidArgument info)
UV_EMFILE -> throwIO (ResourceExhausted info)
UV_EMSGSIZE -> throwIO (InvalidArgument info)
UV_ENAMETOOLONG -> throwIO (InvalidArgument info)
UV_ENETDOWN -> throwIO (ResourceVanished info)
UV_ENETUNREACH -> throwIO (NoSuchThing info)
UV_ENFILE -> throwIO (ResourceExhausted info)
UV_ENOBUFS -> throwIO (ResourceExhausted info)
UV_ENODEV -> throwIO (UnsupportedOperation info)
UV_ENOENT -> throwIO (NoSuchThing info)
UV_ENOMEM -> throwIO (ResourceExhausted info)
UV_ENOPROTOOPT -> throwIO (UnsupportedOperation info)
UV_ENOSPC -> throwIO (ResourceExhausted info)
UV_ENOSYS -> throwIO (UnsupportedOperation info)
UV_ENOTCONN -> throwIO (InvalidArgument info)
UV_ENOTDIR -> throwIO (InappropriateType info)
UV_ENOTEMPTY -> throwIO (UnsatisfiedConstraints info)
UV_ENOTSOCK -> throwIO (InvalidArgument info)
UV_ENOTSUP -> throwIO (UnsupportedOperation info)
UV_EPERM -> throwIO (PermissionDenied info)
UV_EPIPE -> throwIO (ResourceVanished info)
UV_EPROTO -> throwIO (ProtocolError info)
UV_EPROTONOSUPPORT -> throwIO (ProtocolError info)
UV_EPROTOTYPE -> throwIO (ProtocolError info)
UV_ERANGE -> throwIO (UnsupportedOperation info)
UV_EROFS -> throwIO (PermissionDenied info)
UV_ESHUTDOWN -> throwIO (IllegalOperation info)
UV_ESPIPE -> throwIO (UnsupportedOperation info)
UV_ESRCH -> throwIO (NoSuchThing info)
UV_ETIMEDOUT -> throwIO (TimeExpired info)
UV_ETXTBSY -> throwIO (ResourceBusy info)
UV_EXDEV -> throwIO (UnsupportedOperation info)
UV_UNKNOWN -> throwIO (OtherError info)
UV_ENXIO -> throwIO (NoSuchThing info)
UV_EMLINK -> throwIO (ResourceExhausted info)
_ -> throwIO (OtherError info)