git-phoenix-0.0.1: src/Data/Git/Phoenix/Io.hs
module Data.Git.Phoenix.Io where
import Data.ByteString.Lazy qualified as L
import Data.ByteString qualified as BS
import Data.Git.Phoenix.Prelude
import System.IO (openBinaryFile)
class HasInHandlesSem m where
getInHandlesSem :: m QSem
instance (Monad m, HasInHandlesSem m) => HasInHandlesSem (ResourceT m) where
getInHandlesSem = lift getInHandlesSem
data Compressed
withHandleX :: (NFData a, MonadUnliftIO m, HasInHandlesSem m) =>
IOMode -> FilePath -> (Handle -> m a) -> m a
withHandleX mode fp a = do
s <- getInHandlesSem
bracket_ (waitQSem s) (signalQSem s) $
-- withFile is not applicable because Handle might be closed twice
-- https://github.com/haskell/bytestring/issues/707
bracket (liftIO $ openBinaryFile fp mode)
(\h -> whenM (hIsOpen h) $ hClose h) go
where
go h = do
!r <- a h
case rnf r of
() -> pure r
withHandle :: (NFData a, MonadUnliftIO m, HasInHandlesSem m) =>
FilePath -> (Handle -> m a) -> m a
withHandle = withHandleX ReadMode
withCompressedH :: (NFData a, MonadUnliftIO m, HasInHandlesSem m) =>
FilePath ->
(Tagged Compressed LByteString -> LByteString -> m a) ->
m a
withCompressedH fp a =
withHandle ($(tr "/fp") fp) $ \inH -> hGetContents inH >>= (\cbs -> a (Tagged cbs) $ decompress cbs)
withCompressed :: (HasCallStack, NFData a, MonadUnliftIO m, HasInHandlesSem m) =>
FilePath -> (HasCallStack => L.ByteString -> m a) -> m a
withCompressed fp a = withCompressedH fp (\_cbs bs -> a bs)
hGet :: MonadIO m => Handle -> Int -> m ByteString
hGet h n = liftIO $ BS.hGet h n
hGetContents :: MonadIO m => Handle -> m LByteString
hGetContents h = liftIO $ L.hGetContents h
hPut :: MonadIO m => Handle -> LByteString -> m ()
hPut h bs = liftIO $ L.hPut h bs
-- | just 'copyFile' is not possible due to trash after archive
saveCompressedBs :: MonadUnliftIO m => FilePath -> LByteString -> m ()
saveCompressedBs fp bs = do
createDirectoryIfMissing False $ dropFileName fp
withBinaryFile ($(tr "/fp") fp) WriteMode $ \h -> hPut h $ compress bs
readNumber :: MonadIO m => Int -> Int -> m Int
readNumber minVal maxVal = go
where
go = do
s <- liftIO $ getLine
case readMaybe $ toString s of
Just n
| n >= minVal && n <= maxVal ->
pure n
| otherwise -> do
putStrLn "Value is out of range. Try again"
go
Nothing -> do
putStrLn "Value is number. Try again"
go