module Util where

import qualified Data.ByteString.Char8 as BS
import Foreign.C.Error (Errno (Errno), errnoToIOError)
import System.Posix.ByteString (RawFilePath)

import qualified Evdev.LowLevel as LL

fromEnum' :: (Num c, Enum a) => a -> c
fromEnum' :: forall c a. (Num c, Enum a) => a -> c
fromEnum' = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> Int
fromEnum

--TODO careful - for some C calls (eg. libevdev_enable_event_code),
-- int returned doesn't necessarily correspond to a particular error number
--TODO this kinda seems like overkill, but things were getting ugly without it...
class CErrInfo a where
    cErrInfo :: a -> IO (Maybe RawFilePath)
instance CErrInfo () where
    cErrInfo :: () -> IO (Maybe RawFilePath)
cErrInfo () = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
instance CErrInfo RawFilePath where
    cErrInfo :: RawFilePath -> IO (Maybe RawFilePath)
cErrInfo = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure
instance CErrInfo LL.UDevice where
    cErrInfo :: UDevice -> IO (Maybe RawFilePath)
cErrInfo = UDevice -> IO (Maybe RawFilePath)
LL.getSyspath

-- for c actions which return an error value (0 for success)
-- run the action, throwing a relevant exception if the C errno is not 0
class CErrCall a where
    type CErrCallRes a
    cErrCall :: CErrInfo info => String -> info -> IO a -> IO (CErrCallRes a)
instance CErrCall Errno where
    type CErrCallRes Errno = ()
    cErrCall :: forall info.
CErrInfo info =>
String -> info -> IO Errno -> IO (CErrCallRes Errno)
cErrCall String
func info
path IO Errno
x = forall a info.
(CErrCall a, CErrInfo info) =>
String -> info -> IO a -> IO (CErrCallRes a)
cErrCall String
func info
path forall a b. (a -> b) -> a -> b
$ (,()) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Errno
x
instance CErrCall (Errno, a) where
    type CErrCallRes (Errno, a) = a
    cErrCall :: forall info.
CErrInfo info =>
String -> info -> IO (Errno, a) -> IO (CErrCallRes (Errno, a))
cErrCall String
func info
info IO (Errno, a)
x = do
        (Errno
errno, a
res) <- IO (Errno, a)
x
        case Errno
errno of
            Errno CInt
0 -> forall (m :: * -> *) a. Monad m => a -> m a
return a
res
            Errno CInt
n -> do
                Maybe RawFilePath
path' <- forall a. CErrInfo a => a -> IO (Maybe RawFilePath)
cErrInfo info
info
                forall a. IOError -> IO a
ioError forall a b. (a -> b) -> a -> b
$ String -> Errno -> Maybe Handle -> Maybe String -> IOError
errnoToIOError String
func (CInt -> Errno
Errno forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs CInt
n) forall a. Maybe a
Nothing forall a b. (a -> b) -> a -> b
$ RawFilePath -> String
BS.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe RawFilePath
path'