trexio-hs-0.2.0: src-int/TREXIO/Internal/Base.hsc
module TREXIO.Internal.Base where
import Control.Exception.Safe
import Control.Monad.IO.Class
import Foreign
import Foreign.C.String
import Foreign.C.Types
import GHC.Generics
import System.IO.Unsafe (unsafePerformIO)
import Foreign.C.ConstPtr
#include <trexio.h>
type ExitCodeC = #type trexio_exit_code
-- | TREXIO Exit Codes. Can be thrown as Haskell exceptions in IO.
data ExitCode
= Failure
| Success
| InvalidArg1
| InvalidArg2
| InvalidArg3
| InvalidArg4
| InvalidArg5
| End
| ReadOnly
| Errno
| InvalidID
| AllocationFailed
| HasNot
| InvalidNum
| AttrAlreadyExists
| DSetAlreadyExists
| OpenError
| LockError
| UnlockError
| FileError
| GroupReadError
| GroupWriteError
| ElemReadError
| ElemWriteError
| UnsafeArrayDim
| AttrMissing
| DSetMissing
| BackEndMissing
| InvalidArg6
| InvalidArg7
| InvalidArg8
| InvalidStrLen
| IntSizeOverflow
| SafeMode
| InvalidElectronNum
| InvalidDeterminantNum
| InvalidState
| VersionParsingIssue
| PhaseChange
#if TREXIO_VERSION_MAJOR >= 2
#if TREXIO_VERSION_MINOR >= 6
| InvalidMoIndex
| InvalidArg9
| InvalidArg10
| InvalidArg11
| InvalidArg12
| InvalidArg13
| InvalidArg14
| CorruptionAttempt
#endif
#endif
deriving (Show, Eq, Ord, Generic)
instance Enum ExitCode where
fromEnum Failure = #const TREXIO_FAILURE
fromEnum Success = #const TREXIO_SUCCESS
fromEnum InvalidArg1 = #const TREXIO_INVALID_ARG_1
fromEnum InvalidArg2 = #const TREXIO_INVALID_ARG_2
fromEnum InvalidArg3 = #const TREXIO_INVALID_ARG_3
fromEnum InvalidArg4 = #const TREXIO_INVALID_ARG_4
fromEnum InvalidArg5 = #const TREXIO_INVALID_ARG_5
fromEnum End = #const TREXIO_END
fromEnum ReadOnly = #const TREXIO_READONLY
fromEnum Errno = #const TREXIO_ERRNO
fromEnum InvalidID = #const TREXIO_INVALID_ID
fromEnum AllocationFailed = #const TREXIO_ALLOCATION_FAILED
fromEnum HasNot = #const TREXIO_HAS_NOT
fromEnum InvalidNum = #const TREXIO_INVALID_NUM
fromEnum AttrAlreadyExists = #const TREXIO_ATTR_ALREADY_EXISTS
fromEnum DSetAlreadyExists = #const TREXIO_DSET_ALREADY_EXISTS
fromEnum OpenError = #const TREXIO_OPEN_ERROR
fromEnum LockError = #const TREXIO_LOCK_ERROR
fromEnum UnlockError = #const TREXIO_UNLOCK_ERROR
fromEnum FileError = #const TREXIO_FILE_ERROR
fromEnum GroupReadError = #const TREXIO_GROUP_READ_ERROR
fromEnum GroupWriteError = #const TREXIO_GROUP_WRITE_ERROR
fromEnum ElemReadError = #const TREXIO_ELEM_READ_ERROR
fromEnum ElemWriteError = #const TREXIO_ELEM_WRITE_ERROR
fromEnum UnsafeArrayDim = #const TREXIO_UNSAFE_ARRAY_DIM
fromEnum AttrMissing = #const TREXIO_ATTR_MISSING
fromEnum DSetMissing = #const TREXIO_DSET_MISSING
fromEnum BackEndMissing = #const TREXIO_BACK_END_MISSING
fromEnum InvalidArg6 = #const TREXIO_INVALID_ARG_6
fromEnum InvalidArg7 = #const TREXIO_INVALID_ARG_7
fromEnum InvalidArg8 = #const TREXIO_INVALID_ARG_8
fromEnum InvalidStrLen = #const TREXIO_INVALID_STR_LEN
fromEnum IntSizeOverflow = #const TREXIO_INT_SIZE_OVERFLOW
fromEnum SafeMode = #const TREXIO_SAFE_MODE
fromEnum InvalidElectronNum = #const TREXIO_INVALID_ELECTRON_NUM
fromEnum InvalidDeterminantNum = #const TREXIO_INVALID_DETERMINANT_NUM
fromEnum InvalidState = #const TREXIO_INVALID_STATE
fromEnum VersionParsingIssue = #const TREXIO_VERSION_PARSING_ISSUE
fromEnum PhaseChange = #const TREXIO_PHASE_CHANGE
#if TREXIO_VERSION_MAJOR >= 2
#if TREXIO_VERSION_MINOR >= 6
fromEnum InvalidMoIndex = #const TREXIO_INVALID_MO_INDEX
fromEnum InvalidArg9 = #const TREXIO_INVALID_ARG_9
fromEnum InvalidArg10 = #const TREXIO_INVALID_ARG_10
fromEnum InvalidArg11 = #const TREXIO_INVALID_ARG_11
fromEnum InvalidArg12 = #const TREXIO_INVALID_ARG_12
fromEnum InvalidArg13 = #const TREXIO_INVALID_ARG_13
fromEnum InvalidArg14 = #const TREXIO_INVALID_ARG_14
fromEnum CorruptionAttempt = #const TREXIO_CORRUPTION_ATTEMPT
#endif
#endif
toEnum (#const TREXIO_FAILURE) = Failure
toEnum (#const TREXIO_SUCCESS) = Success
toEnum (#const TREXIO_INVALID_ARG_1) = InvalidArg1
toEnum (#const TREXIO_INVALID_ARG_2) = InvalidArg2
toEnum (#const TREXIO_INVALID_ARG_3) = InvalidArg3
toEnum (#const TREXIO_INVALID_ARG_4) = InvalidArg4
toEnum (#const TREXIO_INVALID_ARG_5) = InvalidArg5
toEnum (#const TREXIO_END) = End
toEnum (#const TREXIO_READONLY) = ReadOnly
toEnum (#const TREXIO_ERRNO) = Errno
toEnum (#const TREXIO_INVALID_ID) = InvalidID
toEnum (#const TREXIO_ALLOCATION_FAILED) = AllocationFailed
toEnum (#const TREXIO_HAS_NOT) = HasNot
toEnum (#const TREXIO_INVALID_NUM) = InvalidNum
toEnum (#const TREXIO_ATTR_ALREADY_EXISTS) = AttrAlreadyExists
toEnum (#const TREXIO_DSET_ALREADY_EXISTS) = DSetAlreadyExists
toEnum (#const TREXIO_OPEN_ERROR) = OpenError
toEnum (#const TREXIO_LOCK_ERROR) = LockError
toEnum (#const TREXIO_UNLOCK_ERROR) = UnlockError
toEnum (#const TREXIO_FILE_ERROR) = FileError
toEnum (#const TREXIO_GROUP_READ_ERROR) = GroupReadError
toEnum (#const TREXIO_GROUP_WRITE_ERROR) = GroupWriteError
toEnum (#const TREXIO_ELEM_READ_ERROR) = ElemReadError
toEnum (#const TREXIO_ELEM_WRITE_ERROR) = ElemWriteError
toEnum (#const TREXIO_UNSAFE_ARRAY_DIM) = UnsafeArrayDim
toEnum (#const TREXIO_ATTR_MISSING) = AttrMissing
toEnum (#const TREXIO_DSET_MISSING) = DSetMissing
toEnum (#const TREXIO_BACK_END_MISSING) = BackEndMissing
toEnum (#const TREXIO_INVALID_ARG_6) = InvalidArg6
toEnum (#const TREXIO_INVALID_ARG_7) = InvalidArg7
toEnum (#const TREXIO_INVALID_ARG_8) = InvalidArg8
toEnum (#const TREXIO_INVALID_STR_LEN) = InvalidStrLen
toEnum (#const TREXIO_INT_SIZE_OVERFLOW) = IntSizeOverflow
toEnum (#const TREXIO_SAFE_MODE) = SafeMode
toEnum (#const TREXIO_INVALID_ELECTRON_NUM) = InvalidElectronNum
toEnum (#const TREXIO_INVALID_DETERMINANT_NUM) = InvalidDeterminantNum
toEnum (#const TREXIO_INVALID_STATE) = InvalidState
toEnum (#const TREXIO_VERSION_PARSING_ISSUE) = VersionParsingIssue
toEnum (#const TREXIO_PHASE_CHANGE) = PhaseChange
#if TREXIO_VERSION_MAJOR >= 2
#if TREXIO_VERSION_MINOR >= 6
toEnum (#const TREXIO_INVALID_MO_INDEX) = InvalidMoIndex
toEnum (#const TREXIO_INVALID_ARG_9) = InvalidArg9
toEnum (#const TREXIO_INVALID_ARG_10) = InvalidArg10
toEnum (#const TREXIO_INVALID_ARG_11) = InvalidArg11
toEnum (#const TREXIO_INVALID_ARG_12) = InvalidArg12
toEnum (#const TREXIO_INVALID_ARG_13) = InvalidArg13
toEnum (#const TREXIO_INVALID_ARG_14) = InvalidArg14
toEnum (#const TREXIO_CORRUPTION_ATTEMPT) = CorruptionAttempt
#endif
#endif
toEnum _ = error "toEnum(ExitCode): invalid argument"
instance Exception ExitCode where
displayException = stringOfError
exitCodeH :: ExitCodeC -> ExitCode
exitCodeH = toEnum . fromIntegral
-- | Helper to make a C function returning an exit code to an easier to handle
-- exception
checkEC :: (MonadIO m, MonadThrow m) => IO ExitCodeC -> m ()
checkEC f = do
ec <- exitCodeH <$> liftIO f
if ec == Success
then return ()
else throwIO ec
foreign import capi "trexio.h trexio_string_of_error" stringOfError_ :: (#type trexio_exit_code) -> IO (ConstPtr CChar)
stringOfError :: ExitCode -> String
stringOfError exitCode = unsafePerformIO $ do
stringOfError_ exitCodeInt >>= peekCString . unConstPtr
where
exitCodeInt = fromIntegral . fromEnum $ exitCode
--------------------------------------------------------------------------------
-- | TREXIO version: Major, Minor, Patch
version :: (Int, Int, Int)
version =
( #const TREXIO_VERSION_MAJOR
, #const TREXIO_VERSION_MINOR
, #const TREXIO_VERSION_PATCH
)
--------------------------------------------------------------------------------
data Backend
= Hdf5
| Text
| Invalid
| Auto
deriving (Eq, Ord, Show)
instance Enum Backend where
fromEnum Hdf5 = #const TREXIO_HDF5
fromEnum Text = #const TREXIO_TEXT
fromEnum Invalid = #const TREXIO_INVALID_BACK_END
fromEnum Auto = #const TREXIO_AUTO
toEnum (#const TREXIO_HDF5) = Hdf5
toEnum (#const TREXIO_TEXT) = Text
toEnum (#const TREXIO_INVALID_BACK_END) = Invalid
toEnum (#const TREXIO_AUTO) = Auto
toEnum _ = error "toEnum(Backend): invalid argument"
backendC :: Backend -> (#type back_end_t)
backendC = fromIntegral . fromEnum
foreign import capi "trexio.h trexio_has_backend" hasBackend_ :: (#type back_end_t) -> CBool
hasBackend :: Backend -> Bool
hasBackend backend = toBool . hasBackend_ . fromIntegral . fromEnum $ backend
--------------------------------------------------------------------------------
-- | TREXIO file handle
newtype Trexio = Trexio (Ptr Trexio)
-- | File access mode for 'Trexio'.
data FileMode
= FileRead
| FileWrite
| FileUnsafe -- ^ Allows to delete and override data
deriving (Eq, Show, Ord, Generic)
modeC :: FileMode -> CChar
modeC FileRead = castCharToCChar 'r'
modeC FileWrite = castCharToCChar 'w'
modeC FileUnsafe = castCharToCChar 'u'
foreign import capi "trexio.h trexio_open" open_ ::
CString ->
CChar ->
(#type back_end_t) ->
Ptr (#type trexio_exit_code) ->
IO Trexio
open :: (MonadIO m, MonadThrow m) => FilePath -> FileMode -> Backend -> m Trexio
open filepath mode backend = liftIO . withCString filepath $ \filepathC ->
alloca $ \ecPtr -> do
trexio <- open_ filepathC (modeC mode) (backendC backend) ecPtr
ec <- exitCodeH <$> peek ecPtr
if ec == Success
then return trexio
else throwM ec
foreign import capi "trexio.h trexio_close" close_ :: Trexio -> IO ExitCodeC
close :: (MonadIO m, MonadThrow m) => Trexio -> m ()
close trexio = checkEC $ close_ trexio
foreign import capi "trexio.h trexio_mark_safety" markSafety_ :: Trexio -> Int32 -> IO ExitCodeC
-- | After a file has been opened unsafely, it can be marked as safe by this function
-- forcefully. You are responsible for internal incosistencies that may arise from this.
markSafety :: (MonadIO m, MonadThrow m) => Trexio -> m ()
markSafety trexio = checkEC $ markSafety_ trexio 0
--------------------------------------------------------------------------------
-- | Bit field type for storing determinant information.
newtype BitFieldT = BitFieldT Int64
deriving (Eq, Ord, Show)
deriving Storable via (Int64)