{-# LINE 1 "src/Notmuch/Binding.chs" #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Notmuch.Binding where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.ForeignPtr as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import Control.Monad ((>=>), (<=<), void)
import Control.Monad.Except (MonadError(..))
import Control.Monad.IO.Class (MonadIO(..))
import Data.Coerce (coerce)
import Data.Foldable (traverse_)
import Data.Functor (($>))
import Data.Functor.Identity (Identity(..))
import Data.Proxy
import GHC.TypeLits (Nat, type (<=), type (+), type (-))
import Notmuch.Tag
import Notmuch.Util
{-# LINE 41 "src/Notmuch/Binding.chs" #-}
import Foreign
( ForeignPtr, Ptr, castForeignPtr
, alloca, newForeignPtr, nullFunPtr, nullPtr, peek
, touchForeignPtr
)
import Foreign.C
import Foreign.Storable (Storable)
import qualified System.IO.Unsafe
import qualified Data.ByteString as B
import Notmuch.Talloc
type MessageId = B.ByteString
type ThreadId = B.ByteString
data Status = StatusSuccess
| StatusOutOfMemory
| StatusReadOnlyDatabase
| StatusXapianException
| StatusFileError
| StatusFileNotEmail
| StatusDuplicateMessageId
| StatusNullPointer
| StatusTagTooLong
| StatusUnbalancedFreezeThaw
| StatusUnbalancedAtomic
| StatusUnsupportedOperation
| StatusUpgradeRequired
| StatusPathError
| StatusIgnored
| StatusIllegalArgument
| StatusMalformedCryptoProtocol
| StatusFailedCryptoContextCreation
| StatusUnknownCryptoProtocol
| StatusLastStatus
deriving (Eq)
instance Enum Status where
succ StatusSuccess = StatusOutOfMemory
succ StatusOutOfMemory = StatusReadOnlyDatabase
succ StatusReadOnlyDatabase = StatusXapianException
succ StatusXapianException = StatusFileError
succ StatusFileError = StatusFileNotEmail
succ StatusFileNotEmail = StatusDuplicateMessageId
succ StatusDuplicateMessageId = StatusNullPointer
succ StatusNullPointer = StatusTagTooLong
succ StatusTagTooLong = StatusUnbalancedFreezeThaw
succ StatusUnbalancedFreezeThaw = StatusUnbalancedAtomic
succ StatusUnbalancedAtomic = StatusUnsupportedOperation
succ StatusUnsupportedOperation = StatusUpgradeRequired
succ StatusUpgradeRequired = StatusPathError
succ StatusPathError = StatusIgnored
succ StatusIgnored = StatusIllegalArgument
succ StatusIllegalArgument = StatusMalformedCryptoProtocol
succ StatusMalformedCryptoProtocol = StatusFailedCryptoContextCreation
succ StatusFailedCryptoContextCreation = StatusUnknownCryptoProtocol
succ StatusUnknownCryptoProtocol = StatusLastStatus
succ StatusLastStatus = error "Status.succ: StatusLastStatus has no successor"
pred StatusOutOfMemory = StatusSuccess
pred StatusReadOnlyDatabase = StatusOutOfMemory
pred StatusXapianException = StatusReadOnlyDatabase
pred StatusFileError = StatusXapianException
pred StatusFileNotEmail = StatusFileError
pred StatusDuplicateMessageId = StatusFileNotEmail
pred StatusNullPointer = StatusDuplicateMessageId
pred StatusTagTooLong = StatusNullPointer
pred StatusUnbalancedFreezeThaw = StatusTagTooLong
pred StatusUnbalancedAtomic = StatusUnbalancedFreezeThaw
pred StatusUnsupportedOperation = StatusUnbalancedAtomic
pred StatusUpgradeRequired = StatusUnsupportedOperation
pred StatusPathError = StatusUpgradeRequired
pred StatusIgnored = StatusPathError
pred StatusIllegalArgument = StatusIgnored
pred StatusMalformedCryptoProtocol = StatusIllegalArgument
pred StatusFailedCryptoContextCreation = StatusMalformedCryptoProtocol
pred StatusUnknownCryptoProtocol = StatusFailedCryptoContextCreation
pred StatusLastStatus = StatusUnknownCryptoProtocol
pred StatusSuccess = error "Status.pred: StatusSuccess has no predecessor"
enumFromTo from to = go from
where
end = fromEnum to
go v = case compare (fromEnum v) end of
LT -> v : go (succ v)
EQ -> [v]
GT -> []
enumFrom from = enumFromTo from StatusLastStatus
fromEnum StatusSuccess = 0
fromEnum StatusOutOfMemory = 1
fromEnum StatusReadOnlyDatabase = 2
fromEnum StatusXapianException = 3
fromEnum StatusFileError = 4
fromEnum StatusFileNotEmail = 5
fromEnum StatusDuplicateMessageId = 6
fromEnum StatusNullPointer = 7
fromEnum StatusTagTooLong = 8
fromEnum StatusUnbalancedFreezeThaw = 9
fromEnum StatusUnbalancedAtomic = 10
fromEnum StatusUnsupportedOperation = 11
fromEnum StatusUpgradeRequired = 12
fromEnum StatusPathError = 13
fromEnum StatusIgnored = 14
fromEnum StatusIllegalArgument = 15
fromEnum StatusMalformedCryptoProtocol = 16
fromEnum StatusFailedCryptoContextCreation = 17
fromEnum StatusUnknownCryptoProtocol = 18
fromEnum StatusLastStatus = 19
toEnum 0 = StatusSuccess
toEnum 1 = StatusOutOfMemory
toEnum 2 = StatusReadOnlyDatabase
toEnum 3 = StatusXapianException
toEnum 4 = StatusFileError
toEnum 5 = StatusFileNotEmail
toEnum 6 = StatusDuplicateMessageId
toEnum 7 = StatusNullPointer
toEnum 8 = StatusTagTooLong
toEnum 9 = StatusUnbalancedFreezeThaw
toEnum 10 = StatusUnbalancedAtomic
toEnum 11 = StatusUnsupportedOperation
toEnum 12 = StatusUpgradeRequired
toEnum 13 = StatusPathError
toEnum 14 = StatusIgnored
toEnum 15 = StatusIllegalArgument
toEnum 16 = StatusMalformedCryptoProtocol
toEnum 17 = StatusFailedCryptoContextCreation
toEnum 18 = StatusUnknownCryptoProtocol
toEnum 19 = StatusLastStatus
toEnum unmatched = error ("Status.toEnum: Cannot match " ++ show unmatched)
{-# LINE 67 "src/Notmuch/Binding.chs" #-}
data DatabaseMode = DatabaseModeReadOnly
| DatabaseModeReadWrite
instance Enum DatabaseMode where
succ DatabaseModeReadOnly = DatabaseModeReadWrite
succ DatabaseModeReadWrite = error "DatabaseMode.succ: DatabaseModeReadWrite has no successor"
pred DatabaseModeReadWrite = DatabaseModeReadOnly
pred DatabaseModeReadOnly = error "DatabaseMode.pred: DatabaseModeReadOnly has no predecessor"
enumFromTo from to = go from
where
end = fromEnum to
go v = case compare (fromEnum v) end of
LT -> v : go (succ v)
EQ -> [v]
GT -> []
enumFrom from = enumFromTo from DatabaseModeReadWrite
fromEnum DatabaseModeReadOnly = 0
fromEnum DatabaseModeReadWrite = 1
toEnum 0 = DatabaseModeReadOnly
toEnum 1 = DatabaseModeReadWrite
toEnum unmatched = error ("DatabaseMode.toEnum: Cannot match " ++ show unmatched)
{-# LINE 68 "src/Notmuch/Binding.chs" #-}
data Sort = SortOldestFirst
| SortNewestFirst
| SortMessageId
| SortUnsorted
deriving (Enum)
{-# LINE 69 "src/Notmuch/Binding.chs" #-}
data MessageFlag = MessageFlagMatch
| MessageFlagExcluded
| MessageFlagGhost
deriving (Enum)
{-# LINE 70 "src/Notmuch/Binding.chs" #-}
newtype DatabaseHandle = DatabaseHandle (C2HSImp.ForeignPtr (DatabaseHandle))
withDatabaseHandle :: DatabaseHandle -> (C2HSImp.Ptr DatabaseHandle -> IO b) -> IO b
withDatabaseHandle (DatabaseHandle fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 71 "src/Notmuch/Binding.chs" #-}
newtype QueryHandle = QueryHandle (C2HSImp.ForeignPtr (QueryHandle))
withQueryHandle :: QueryHandle -> (C2HSImp.Ptr QueryHandle -> IO b) -> IO b
withQueryHandle (QueryHandle fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 72 "src/Notmuch/Binding.chs" #-}
newtype Threads = Threads (C2HSImp.Ptr (Threads))
{-# LINE 73 "src/Notmuch/Binding.chs" #-}
newtype ThreadHandle = ThreadHandle (C2HSImp.ForeignPtr (ThreadHandle))
withThreadHandle :: ThreadHandle -> (C2HSImp.Ptr ThreadHandle -> IO b) -> IO b
withThreadHandle (ThreadHandle fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 74 "src/Notmuch/Binding.chs" #-}
newtype Messages = Messages (C2HSImp.Ptr (Messages))
{-# LINE 75 "src/Notmuch/Binding.chs" #-}
newtype MessageHandle = MessageHandle (C2HSImp.ForeignPtr (MessageHandle))
withMessageHandle :: MessageHandle -> (C2HSImp.Ptr MessageHandle -> IO b) -> IO b
withMessageHandle (MessageHandle fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 76 "src/Notmuch/Binding.chs" #-}
newtype Tags = Tags (C2HSImp.Ptr (Tags))
{-# LINE 77 "src/Notmuch/Binding.chs" #-}
newtype Directory = Directory (C2HSImp.ForeignPtr (Directory))
withDirectory :: Directory -> (C2HSImp.Ptr Directory -> IO b) -> IO b
withDirectory (Directory fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 78 "src/Notmuch/Binding.chs" #-}
newtype Filenames = Filenames (C2HSImp.ForeignPtr (Filenames))
withFilenames :: Filenames -> (C2HSImp.Ptr Filenames -> IO b) -> IO b
withFilenames (Filenames fptr) = C2HSImp.withForeignPtr fptr
{-# LINE 79 "src/Notmuch/Binding.chs" #-}
deriving instance Storable Threads
deriving instance Storable Messages
instance Show Status where
show a = System.IO.Unsafe.unsafePerformIO $
notmuch_status_to_string (fromEnum' a) >>= peekCString
class AsNotmuchError s where
_NotmuchError :: Prism' s Status
instance AsNotmuchError Status where
_NotmuchError = id
throwOr :: (AsNotmuchError e, MonadError e m) => (a -> m b) -> Either Status a -> m b
throwOr = either (throwError . review _NotmuchError)
type RO = 'DatabaseModeReadOnly
type RW = 'DatabaseModeReadWrite
newtype Database (a :: DatabaseMode) = Database DatabaseHandle
withDatabase :: Database a -> (Ptr DatabaseHandle -> IO b) -> IO b
withDatabase (Database dbh) = withDatabaseHandle dbh
data Message (n :: Nat) (a :: DatabaseMode) = Message
![ForeignPtr () ]
{-# UNPACK #-} !MessageHandle
withMessage :: Message n a -> (Ptr MessageHandle -> IO b) -> IO b
withMessage (Message owners a) k = do
r <- withMessageHandle a k
traverse_ touchForeignPtr owners
pure r
data Thread (a :: DatabaseMode) = Thread
{-# UNPACK #-} !(ForeignPtr DatabaseHandle )
{-# UNPACK #-} !(ForeignPtr QueryHandle )
{-# UNPACK #-} !ThreadHandle
withThread :: Thread a -> (Ptr ThreadHandle -> IO b) -> IO b
withThread (Thread dfp qfp a) k = do
r <- withThreadHandle a k
touchForeignPtr dfp
touchForeignPtr qfp
pure r
data Query (a :: DatabaseMode) = Query
{-# UNPACK #-} !(ForeignPtr DatabaseHandle)
{-# UNPACK #-} !QueryHandle
withQuery :: Query a -> (Ptr QueryHandle -> IO b) -> IO b
withQuery (Query owner a) f = do
r <- withQueryHandle a f
touchForeignPtr owner
pure r
fromEnum' :: (Enum a, Integral b) => a -> b
fromEnum' = fromIntegral . fromEnum
status :: (Applicative f) => f a -> Status -> f (Either Status a)
status a StatusSuccess = Right <$> a
status _ e = pure $ Left e
toStatus :: (Integral a, Enum b) => a -> b
toStatus = toEnum . fromIntegral
class Mode a where
getMode :: Proxy a -> DatabaseMode
upgrade :: (AsNotmuchError e, MonadError e m, MonadIO m) => Database a -> m (Database a)
instance Mode 'DatabaseModeReadOnly where
getMode _ = DatabaseModeReadOnly
upgrade = pure
instance Mode 'DatabaseModeReadWrite where
getMode _ = DatabaseModeReadWrite
upgrade db =
liftIO (toEnum . fromIntegral <$> withDatabase db (\dbPtr ->
notmuch_database_upgrade dbPtr nullFunPtr nullPtr))
>>= \rv -> case rv of
StatusSuccess -> pure db
e -> throwError $ review _NotmuchError e
database_open
:: forall a e m. (AsNotmuchError e, Mode a, MonadError e m, MonadIO m)
=> FilePath
-> m (Database a)
database_open s =
liftIO (
withCString s (\s' -> (fmap . fmap) runIdentity $
constructF
Identity
(fmap (Database . DatabaseHandle) . newForeignPtr notmuch_database_destroy)
(notmuch_database_open s' (fromEnum' (getMode (Proxy :: Proxy a))))
))
>>= throwOr upgrade
database_get_path :: Database a -> IO FilePath
database_get_path db =
withDatabase db notmuch_database_get_path >>= peekCString
database_get_version :: Database a -> IO Int
database_get_version db =
fromIntegral <$> withDatabase db notmuch_database_get_version
{-# LINE 238 "src/Notmuch/Binding.chs" #-}
database_find_message
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> Database a
-> MessageId
-> m (Maybe (Message 0 a))
database_find_message =
database_find_message_x B.useAsCString notmuch_database_find_message
{-# LINE 257 "src/Notmuch/Binding.chs" #-}
database_find_message_by_filename
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> Database a
-> FilePath
-> m (Maybe (Message 0 a))
database_find_message_by_filename =
database_find_message_x withCString notmuch_database_find_message_by_filename
{-# LINE 265 "src/Notmuch/Binding.chs" #-}
database_find_message_x
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> (s -> (s' -> IO (Either Status (Maybe (Message 0 a)))) -> IO (Either Status (Maybe (Message 0 a))))
-> (Ptr DatabaseHandle -> s' -> Ptr (Ptr MessageHandle) -> IO CInt)
-> Database a
-> s
-> m (Maybe (Message 0 a))
database_find_message_x prep f db@(Database (DatabaseHandle dfp)) s =
liftIO (withDatabase db $ \db' ->
prep s $ \s' ->
constructF
(\ptr -> if ptr /= nullPtr then Just ptr else Nothing)
(fmap (Message [castForeignPtr dfp] . MessageHandle)
. (newForeignPtr notmuch_message_destroy <=< detachPtr))
(f db' s')
)
>>= throwOr pure
database_get_all_tags :: Database a -> IO [Tag]
database_get_all_tags ptr = withDatabase ptr $ \ptr' ->
notmuch_database_get_all_tags ptr' >>= tagsToList
query_create :: Database a -> String -> IO (Query a)
query_create db@(Database (DatabaseHandle dfp)) s = withCString s $ \s' ->
withDatabase db $ \db' ->
notmuch_query_create db' s'
>>= detachPtr
>>= fmap (Query dfp . QueryHandle) . newForeignPtr notmuch_query_destroy
query_get_query_string :: Query a -> IO String
query_get_query_string ptr =
withQuery ptr (notmuch_query_get_query_string >=> peekCString)
query_set_sort :: Query a -> Sort -> IO ()
query_set_sort ptr x = withQuery ptr $ \ptr' ->
notmuch_query_set_sort ptr' (fromEnum' x)
query_get_sort :: Query a -> IO Sort
query_get_sort ptr = withQuery ptr $
fmap (toEnum . fromIntegral) . notmuch_query_get_sort
{-# LINE 313 "src/Notmuch/Binding.chs" #-}
query_add_tag_exclude :: Query a -> Tag -> IO ()
query_add_tag_exclude ptr tag = void $
withQuery ptr $ \ptr' ->
tagUseAsCString tag $ \s' ->
notmuch_query_add_tag_exclude ptr' s'
query_search_threads
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> Query a -> m [Thread a]
query_search_threads q@(Query dfp (QueryHandle qfp)) =
liftIO ( withQuery q $ \qPtr ->
constructF
Identity
(threadsToList dfp qfp)
(notmuch_query_search_threads qPtr)
)
>>= throwOr (pure . runIdentity)
query_search_messages
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> Query a -> m [Message 0 a]
query_search_messages q@(Query dfp (QueryHandle qfp)) =
liftIO ( withQuery q $ \qPtr ->
constructF
Identity
(messagesToList [castForeignPtr dfp, castForeignPtr qfp])
(notmuch_query_search_messages qPtr)
)
>>= throwOr (pure . runIdentity)
query_count_x
:: (AsNotmuchError e, MonadError e m, MonadIO m)
=> (Ptr QueryHandle -> Ptr CUInt -> IO CInt)
-> Query a -> m Int
query_count_x f q = fmap fromIntegral $
liftIO (
withQuery q $ \qPtr ->
alloca $ \intPtr ->
toStatus <$> f qPtr intPtr
>>= status (peek intPtr)
) >>= throwOr pure
query_count_messages, query_count_threads
:: (AsNotmuchError e, MonadError e m, MonadIO m) => Query a -> m Int
query_count_messages = query_count_x notmuch_query_count_messages
{-# LINE 378 "src/Notmuch/Binding.chs" #-}
query_count_threads = query_count_x notmuch_query_count_threads
{-# LINE 379 "src/Notmuch/Binding.chs" #-}
thread_get_thread_id :: Thread a -> IO ThreadId
thread_get_thread_id ptr =
withThread ptr (notmuch_thread_get_thread_id >=> B.packCString)
thread_get_total_messages :: Thread a -> IO Int
thread_get_total_messages ptr =
fromIntegral <$> withThread ptr (notmuch_thread_get_total_messages)
thread_get_toplevel_messages :: MonadIO m => Thread a -> m [Message 0 a]
thread_get_toplevel_messages t@(Thread dfp qfp (ThreadHandle tfp))
= liftIO $ withThread t $ \ptr ->
notmuch_thread_get_toplevel_messages ptr
>>= messagesToList [castForeignPtr dfp, castForeignPtr qfp, castForeignPtr tfp]
thread_get_messages :: MonadIO m => Thread a -> m [Message 0 a]
thread_get_messages t@(Thread dfp qfp (ThreadHandle tfp))
= liftIO $ withThread t $ \ptr ->
notmuch_thread_get_messages ptr
>>= messagesToList [castForeignPtr dfp, castForeignPtr qfp, castForeignPtr tfp]
thread_get_authors :: Thread a -> IO (Maybe B.ByteString)
thread_get_authors ptr = withThread ptr $ \ptr' -> do
r <- notmuch_thread_get_authors ptr'
if r == nullPtr
then pure Nothing
else Just <$> B.packCString r
thread_get_subject :: Thread a -> IO B.ByteString
thread_get_subject ptr = withThread ptr (notmuch_thread_get_subject >=> B.packCString)
thread_get_newest_date :: Thread a -> IO CLong
thread_get_newest_date = flip withThread notmuch_thread_get_newest_date
{-# LINE 415 "src/Notmuch/Binding.chs" #-}
thread_get_tags :: Thread a -> IO [Tag]
thread_get_tags ptr = withThread ptr $
notmuch_thread_get_tags >=> tagsToList
message_get_message_id :: Message n a -> IO MessageId
message_get_message_id ptr =
withMessage ptr (notmuch_message_get_message_id >=> B.packCString)
message_get_thread_id :: Message n a -> IO ThreadId
message_get_thread_id ptr =
withMessage ptr (notmuch_message_get_thread_id >=> B.packCString)
message_get_replies :: MonadIO m => Message n a -> m [Message 0 a]
message_get_replies msg@(Message owners (MessageHandle mfp))
= liftIO $ withMessage msg $ \ptr ->
notmuch_message_get_replies ptr
>>= messagesToList (castForeignPtr mfp : owners)
message_get_filename :: Message n a -> IO FilePath
message_get_filename ptr =
withMessage ptr (notmuch_message_get_filename >=> peekCString)
message_get_flag :: Message n a -> MessageFlag -> IO Bool
message_get_flag ptr flag = withMessage ptr $ \ptr' -> do
(/= 0) <$> notmuch_message_get_flag ptr' (enumToCInt flag)
message_set_flag :: Message n a -> MessageFlag -> Bool -> IO ()
message_set_flag ptr flag v = withMessage ptr $ \ptr' ->
notmuch_message_set_flag ptr' (enumToCInt flag) (enumToCInt v)
message_get_date :: Message n a -> IO CLong
message_get_date = flip withMessage notmuch_message_get_date
{-# LINE 453 "src/Notmuch/Binding.chs" #-}
message_get_header :: Message n a -> B.ByteString -> IO (Maybe B.ByteString)
message_get_header ptr s =
B.useAsCString s $ \s' ->
withMessage ptr $ \ptr' -> do
r <- notmuch_message_get_header ptr' s'
if r == nullPtr
then pure Nothing
else Just <$> B.packCString r
message_get_tags :: Message n a -> IO [Tag]
message_get_tags ptr = withMessage ptr $
notmuch_message_get_tags >=> tagsToList
message_remove_all_tags :: Message n RW -> IO ()
message_remove_all_tags msg = void $ withMessage msg $
notmuch_message_remove_all_tags
{-# LINE 482 "src/Notmuch/Binding.chs" #-}
message_add_tag :: Message n RW -> Tag -> IO ()
message_add_tag msg tag = void $ withMessage msg $
tagUseAsCString tag . notmuch_message_add_tag
{-# LINE 494 "src/Notmuch/Binding.chs" #-}
message_remove_tag :: Message n RW -> Tag -> IO ()
message_remove_tag msg tag = void $ withMessage msg $
tagUseAsCString tag . notmuch_message_remove_tag
{-# LINE 506 "src/Notmuch/Binding.chs" #-}
message_freeze :: Message n RW -> IO (Message (n + 1) RW)
message_freeze msg = withMessage msg notmuch_message_freeze $> coerce msg
message_thaw :: (1 <= n) => Message n RW -> IO (Message (n - 1) RW)
message_thaw msg = withMessage msg notmuch_message_thaw $> coerce msg
enumToCInt :: Enum a => a -> CInt
enumToCInt = fromIntegral . fromEnum
constructF
:: (Storable ptr, Traversable t)
=> (ptr -> t ptr)
-> (ptr -> IO r)
-> (Ptr ptr -> IO CInt)
-> IO (Either Status (t r))
constructF mkF dcon constructor =
alloca $ \ptr ->
toEnum . fromIntegral <$> constructor ptr
>>= status (traverse dcon . mkF =<< peek ptr)
type PtrToList =
forall a b ptr.
(ptr -> IO CInt)
-> (ptr -> IO a)
-> (ptr -> IO ())
-> (a -> IO b)
-> ptr
-> IO [b]
ptrToList :: PtrToList
ptrToList = ptrToListIO id
lazyPtrToList :: PtrToList
lazyPtrToList = ptrToListIO System.IO.Unsafe.unsafeInterleaveIO
ptrToListIO :: (forall r. IO r -> IO r) -> PtrToList
ptrToListIO tweakIO test get next f ptr = go
where
go = test ptr >>= \valid -> case valid of
0 -> pure []
_ -> (:)
<$> (get ptr >>= f >>= \x -> next ptr $> x)
<*> tweakIO go
tagsToList :: Tags -> IO [Tag]
tagsToList = ptrToList
notmuch_tags_valid
{-# LINE 590 "src/Notmuch/Binding.chs" #-}
notmuch_tags_get
{-# LINE 591 "src/Notmuch/Binding.chs" #-}
notmuch_tags_move_to_next
{-# LINE 592 "src/Notmuch/Binding.chs" #-}
tagFromCString
threadsToList
:: ForeignPtr DatabaseHandle
-> ForeignPtr QueryHandle
-> Threads
-> IO [Thread mode]
threadsToList dfp qfp = lazyPtrToList
notmuch_threads_valid
{-# LINE 601 "src/Notmuch/Binding.chs" #-}
notmuch_threads_get
{-# LINE 602 "src/Notmuch/Binding.chs" #-}
notmuch_threads_move_to_next
{-# LINE 603 "src/Notmuch/Binding.chs" #-}
(fmap (Thread dfp qfp . ThreadHandle) . newForeignPtr notmuch_thread_destroy <=< detachPtr)
messagesToList :: [ForeignPtr ()] -> Messages -> IO [Message 0 mode]
messagesToList owners = lazyPtrToList
notmuch_messages_valid
{-# LINE 608 "src/Notmuch/Binding.chs" #-}
notmuch_messages_get
{-# LINE 609 "src/Notmuch/Binding.chs" #-}
notmuch_messages_move_to_next
{-# LINE 610 "src/Notmuch/Binding.chs" #-}
(fmap (Message owners . MessageHandle) . newForeignPtr notmuch_message_destroy <=< detachPtr)
foreign import ccall "Notmuch/Binding.chs.h ¬much_database_destroy"
notmuch_database_destroy :: C2HSImp.FinalizerPtr DatabaseHandle
foreign import ccall "Notmuch/Binding.chs.h ¬much_query_destroy"
notmuch_query_destroy :: C2HSImp.FinalizerPtr QueryHandle
foreign import ccall "Notmuch/Binding.chs.h ¬much_thread_destroy"
notmuch_thread_destroy :: C2HSImp.FinalizerPtr ThreadHandle
foreign import ccall "Notmuch/Binding.chs.h ¬much_message_destroy"
notmuch_message_destroy :: C2HSImp.FinalizerPtr MessageHandle
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_status_to_string"
notmuch_status_to_string :: (C2HSImp.CInt -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_upgrade"
notmuch_database_upgrade :: ((C2HSImp.Ptr (DatabaseHandle)) -> ((C2HSImp.FunPtr ((C2HSImp.Ptr ()) -> (C2HSImp.CDouble -> (IO ())))) -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_open"
notmuch_database_open :: ((C2HSImp.Ptr C2HSImp.CChar) -> (C2HSImp.CInt -> ((C2HSImp.Ptr (C2HSImp.Ptr (DatabaseHandle))) -> (IO C2HSImp.CInt))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_get_path"
notmuch_database_get_path :: ((C2HSImp.Ptr (DatabaseHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_get_version"
notmuch_database_get_version :: ((C2HSImp.Ptr (DatabaseHandle)) -> (IO C2HSImp.CUInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_find_message"
notmuch_database_find_message :: ((C2HSImp.Ptr (DatabaseHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> ((C2HSImp.Ptr (C2HSImp.Ptr (MessageHandle))) -> (IO C2HSImp.CInt))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_find_message_by_filename"
notmuch_database_find_message_by_filename :: ((C2HSImp.Ptr (DatabaseHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> ((C2HSImp.Ptr (C2HSImp.Ptr (MessageHandle))) -> (IO C2HSImp.CInt))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_database_get_all_tags"
notmuch_database_get_all_tags :: ((C2HSImp.Ptr (DatabaseHandle)) -> (IO (Tags)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_create"
notmuch_query_create :: ((C2HSImp.Ptr (DatabaseHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (IO (C2HSImp.Ptr (QueryHandle)))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_get_query_string"
notmuch_query_get_query_string :: ((C2HSImp.Ptr (QueryHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_set_sort"
notmuch_query_set_sort :: ((C2HSImp.Ptr (QueryHandle)) -> (C2HSImp.CInt -> (IO ())))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_get_sort"
notmuch_query_get_sort :: ((C2HSImp.Ptr (QueryHandle)) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_add_tag_exclude"
notmuch_query_add_tag_exclude :: ((C2HSImp.Ptr (QueryHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_search_threads"
notmuch_query_search_threads :: ((C2HSImp.Ptr (QueryHandle)) -> ((C2HSImp.Ptr (Threads)) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_search_messages"
notmuch_query_search_messages :: ((C2HSImp.Ptr (QueryHandle)) -> ((C2HSImp.Ptr (Messages)) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_count_messages"
notmuch_query_count_messages :: ((C2HSImp.Ptr (QueryHandle)) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_query_count_threads"
notmuch_query_count_threads :: ((C2HSImp.Ptr (QueryHandle)) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_thread_id"
notmuch_thread_get_thread_id :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_total_messages"
notmuch_thread_get_total_messages :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_toplevel_messages"
notmuch_thread_get_toplevel_messages :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (Messages)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_messages"
notmuch_thread_get_messages :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (Messages)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_authors"
notmuch_thread_get_authors :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_subject"
notmuch_thread_get_subject :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_newest_date"
notmuch_thread_get_newest_date :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO C2HSImp.CLong))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_thread_get_tags"
notmuch_thread_get_tags :: ((C2HSImp.Ptr (ThreadHandle)) -> (IO (Tags)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_message_id"
notmuch_message_get_message_id :: ((C2HSImp.Ptr (MessageHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_thread_id"
notmuch_message_get_thread_id :: ((C2HSImp.Ptr (MessageHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_replies"
notmuch_message_get_replies :: ((C2HSImp.Ptr (MessageHandle)) -> (IO (Messages)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_filename"
notmuch_message_get_filename :: ((C2HSImp.Ptr (MessageHandle)) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_flag"
notmuch_message_get_flag :: ((C2HSImp.Ptr (MessageHandle)) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_set_flag"
notmuch_message_set_flag :: ((C2HSImp.Ptr (MessageHandle)) -> (C2HSImp.CInt -> (C2HSImp.CInt -> (IO ()))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_date"
notmuch_message_get_date :: ((C2HSImp.Ptr (MessageHandle)) -> (IO C2HSImp.CLong))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_header"
notmuch_message_get_header :: ((C2HSImp.Ptr (MessageHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (IO (C2HSImp.Ptr C2HSImp.CChar))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_get_tags"
notmuch_message_get_tags :: ((C2HSImp.Ptr (MessageHandle)) -> (IO (Tags)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_remove_all_tags"
notmuch_message_remove_all_tags :: ((C2HSImp.Ptr (MessageHandle)) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_add_tag"
notmuch_message_add_tag :: ((C2HSImp.Ptr (MessageHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_remove_tag"
notmuch_message_remove_tag :: ((C2HSImp.Ptr (MessageHandle)) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (IO C2HSImp.CInt)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_freeze"
notmuch_message_freeze :: ((C2HSImp.Ptr (MessageHandle)) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_message_thaw"
notmuch_message_thaw :: ((C2HSImp.Ptr (MessageHandle)) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_tags_valid"
notmuch_tags_valid :: ((Tags) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_tags_get"
notmuch_tags_get :: ((Tags) -> (IO (C2HSImp.Ptr C2HSImp.CChar)))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_tags_move_to_next"
notmuch_tags_move_to_next :: ((Tags) -> (IO ()))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_threads_valid"
notmuch_threads_valid :: ((Threads) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_threads_get"
notmuch_threads_get :: ((Threads) -> (IO (C2HSImp.Ptr (ThreadHandle))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_threads_move_to_next"
notmuch_threads_move_to_next :: ((Threads) -> (IO ()))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_messages_valid"
notmuch_messages_valid :: ((Messages) -> (IO C2HSImp.CInt))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_messages_get"
notmuch_messages_get :: ((Messages) -> (IO (C2HSImp.Ptr (MessageHandle))))
foreign import ccall unsafe "Notmuch/Binding.chs.h notmuch_messages_move_to_next"
notmuch_messages_move_to_next :: ((Messages) -> (IO ()))