-- | -- Stability : Ultra-Violence -- Portability : I'm too young to die -- Higher-level file patterns. Don't support read/write operations at offsets and handling stat changes as for now. {-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-} module Network.NineP.File ( chanFile , mVarFile , rwFile ) where import Control.Concurrent.Chan import Control.Concurrent.MVar import Control.Exception import Control.Monad.EmbedIO import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B import Data.Word import Prelude hiding (read) import Network.NineP.Error import Network.NineP.Internal.File simpleRead_ :: (Monad m, EmbedIO m) => m ByteString -> Word64 -> Word32 -> ErrorT NineError m ByteString simpleRead_ get offset count = case offset of _ -> do r <- lift $ tryE $ get either (throwError . OtherError . (show :: SomeException -> String)) (return . B.take (fromIntegral count)) r --_ -> throwError $ OtherError "can't read at offset" simpleWrite_ :: (Monad m, EmbedIO m) => (ByteString -> m ()) -> Word64 -> ByteString -> ErrorT NineError m Word32 simpleWrite_ put offset d = case offset of _ -> do r <- lift $ tryE $ put d either (throwError . OtherError . (show :: SomeException -> String)) (const $ return $ fromIntegral $ B.length d) r --_ -> throwError $ OtherError "can't write at offset" simpleRead :: (Monad m, EmbedIO m) => IO ByteString -> Word64 -> Word32 -> ErrorT NineError m ByteString simpleRead get offset count = case offset of _ -> do d <- lift $ liftIO $ get return $ B.take (fromIntegral count) $ d --_ -> throwError $ OtherError "can't read at offset" simpleWrite :: (Monad m, EmbedIO m) => (ByteString -> IO ()) -> Word64 -> ByteString -> ErrorT NineError m Word32 simpleWrite put offset d = case offset of _ -> do lift $ liftIO $ put d return $ fromIntegral $ B.length d --_ -> throwError $ OtherError "can't write at offset" -- |A file that reads and writes using simple user-specified callbacks rwFile :: forall m. (EmbedIO m) => String -- ^File name -> Maybe (m ByteString) -- ^Read handler -> Maybe (ByteString -> m ()) -- ^Write handler -> NineFile m rwFile name rc wc = (boringFile name :: NineFile m) { read = maybe (read $ (boringFile "" :: NineFile m)) (simpleRead_) rc, write = maybe (write $ (boringFile "" :: NineFile m)) (simpleWrite_) wc } -- |A file that reads from and writes to the specified Chans chanFile :: forall m. (Monad m, EmbedIO m) => String -- ^File name -> Maybe (Chan ByteString) -- ^@Chan@ to read from -> Maybe (Chan ByteString) -- ^@Chan@ to write to -> NineFile m chanFile name rc wc = (boringFile name :: NineFile m) { read = maybe (read $ (boringFile "" :: NineFile m)) (simpleRead . readChan) rc, write = maybe (write $ (boringFile "" :: NineFile m)) (simpleWrite . writeChan) wc } -- |A file that reads from and writes to the specified MVars mVarFile :: forall m. (Monad m, EmbedIO m) => String -- ^File name -> Maybe (MVar ByteString) -- ^@MVar@ to read from -> Maybe (MVar ByteString) -- ^@MVar@ to write to -> NineFile m mVarFile name rc wc = (boringFile name :: NineFile m) { read = maybe (read $ (boringFile "" :: NineFile m)) (simpleRead . takeMVar) rc, write = maybe (write $ (boringFile "" :: NineFile m)) (simpleWrite . putMVar) wc }