{-# LANGUAGE OverloadedStrings #-} {-| Module: Capnp.Rpc.Errors Description: helpers for working with capnproto exceptions. In addition to the values exposed in the API, this module also defines an instance of Haskell's 'E.Exception' type class, for Cap'n Proto's 'Exception'. -} module Capnp.Rpc.Errors ( -- * Converting arbitrary exceptions to capnproto exceptions wrapException -- * Helpers for constructing exceptions , eMethodUnimplemented , eUnimplemented , eDisconnected , eFailed , throwFailed ) where import Data.Default (Default(def)) import Data.Maybe (fromMaybe) import Data.String (fromString) import Data.Text (Text) import qualified Control.Exception.Safe as E import Capnp.Gen.Capnp.Rpc.Pure (Exception(..), Exception'Type(..)) -- | Construct an exception with a type field of failed and the -- given text as its reason. eFailed :: Text -> Exception eFailed reason = def { type_ = Exception'Type'failed , reason = reason } -- | An exception with type = disconnected eDisconnected :: Exception eDisconnected = def { type_ = Exception'Type'disconnected , reason = "Disconnected" } -- | An exception indicating an unimplemented method. eMethodUnimplemented :: Exception eMethodUnimplemented = eUnimplemented "Method unimplemented" -- | An @unimplemented@ exception with a custom reason message. eUnimplemented :: Text -> Exception eUnimplemented reason = def { type_ = Exception'Type'unimplemented , reason = reason } instance E.Exception Exception -- | @'wrapException' debugMode e@ converts an arbitrary haskell exception -- @e@ into an rpc exception, which can be communicated to a remote vat. -- If @debugMode@ is true, the returned exception's reason field will include -- the text of @show e@. wrapException :: Bool -> E.SomeException -> Exception wrapException debugMode e = fromMaybe def { type_ = Exception'Type'failed , reason = if debugMode then "Unhandled exception: " <> fromString (show e) else "Unhandled exception" } (E.fromException e) -- | Throw an exception with a type field of 'Exception'Type'failed' and -- the argument as a reason. throwFailed :: E.MonadThrow m => Text -> m a throwFailed = E.throwM . eFailed