module System.IO.Fake where
import Control.DeepSeq
import Control.Exception
import GHC.IO.Handle
import System.Directory
import System.IO
withTempFile
    :: FilePath                     
    -> String                       
    -> ((FilePath,Handle) -> IO a)  
    -> IO a
withTempFile :: FilePath -> FilePath -> ((FilePath, Handle) -> IO a) -> IO a
withTempFile FilePath
tmpDir FilePath
base (FilePath, Handle) -> IO a
k = IO (FilePath, Handle)
-> ((FilePath, Handle) -> IO ())
-> ((FilePath, Handle) -> IO a)
-> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    (FilePath -> FilePath -> IO (FilePath, Handle)
openTempFile FilePath
tmpDir FilePath
base)
    (\(FilePath
file,Handle
h) -> Handle -> IO ()
hClose Handle
h IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> FilePath -> IO ()
removeFile FilePath
file)
    (FilePath, Handle) -> IO a
k
withRedirect
    :: Handle  
    -> Handle  
    -> IO a    
    -> IO a
withRedirect :: Handle -> Handle -> IO a -> IO a
withRedirect Handle
new Handle
old IO a
act = IO (Handle, BufferMode)
-> ((Handle, BufferMode) -> IO ())
-> ((Handle, BufferMode) -> IO a)
-> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    (do BufferMode
buffering <- Handle -> IO BufferMode
hGetBuffering Handle
old
        Handle
dupH      <- Handle -> IO Handle
hDuplicate Handle
old
        Handle -> Handle -> IO ()
hDuplicateTo Handle
new Handle
old
        (Handle, BufferMode) -> IO (Handle, BufferMode)
forall (m :: * -> *) a. Monad m => a -> m a
return (Handle
dupH,BufferMode
buffering)
    )
    (\(Handle
dupH,BufferMode
buffering) -> do
        Handle -> Handle -> IO ()
hDuplicateTo Handle
dupH Handle
old
        Handle -> BufferMode -> IO ()
hSetBuffering Handle
old BufferMode
buffering
        Handle -> IO ()
hClose Handle
dupH
    )
    (\(Handle, BufferMode)
_ -> IO a
act)
fakeIO
    :: IO a       
    -> String     
    -> IO String  
fakeIO :: IO a -> FilePath -> IO FilePath
fakeIO IO a
act FilePath
inp = do
    FilePath
tmpDir <- IO FilePath
getTemporaryDirectory
    FilePath
-> FilePath -> ((FilePath, Handle) -> IO FilePath) -> IO FilePath
forall a.
FilePath -> FilePath -> ((FilePath, Handle) -> IO a) -> IO a
withTempFile FilePath
tmpDir FilePath
"fakeInput" (((FilePath, Handle) -> IO FilePath) -> IO FilePath)
-> ((FilePath, Handle) -> IO FilePath) -> IO FilePath
forall a b. (a -> b) -> a -> b
$ \(FilePath
inpFile,Handle
inpH) ->
      FilePath
-> FilePath -> ((FilePath, Handle) -> IO FilePath) -> IO FilePath
forall a.
FilePath -> FilePath -> ((FilePath, Handle) -> IO a) -> IO a
withTempFile FilePath
tmpDir FilePath
"fakeOutput" (((FilePath, Handle) -> IO FilePath) -> IO FilePath)
-> ((FilePath, Handle) -> IO FilePath) -> IO FilePath
forall a b. (a -> b) -> a -> b
$ \(FilePath
outFile,Handle
outH) -> do
        Handle -> Handle -> IO FilePath -> IO FilePath
forall a. Handle -> Handle -> IO a -> IO a
withRedirect Handle
outH Handle
stdout (IO FilePath -> IO FilePath) -> IO FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$
          Handle -> Handle -> IO FilePath -> IO FilePath
forall a. Handle -> Handle -> IO a -> IO a
withRedirect Handle
inpH Handle
stdin (IO FilePath -> IO FilePath) -> IO FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ do
            Handle -> FilePath -> IO ()
hPutStr Handle
inpH FilePath
inp
            Handle -> SeekMode -> Integer -> IO ()
hSeek Handle
inpH SeekMode
AbsoluteSeek Integer
0
            IO a
act
            Handle -> IO ()
hFlush Handle
stdout
            Handle -> SeekMode -> Integer -> IO ()
hSeek Handle
outH SeekMode
AbsoluteSeek Integer
0
            FilePath
str <- Handle -> IO FilePath
hGetContents Handle
outH
            FilePath
str FilePath -> IO FilePath -> IO FilePath
forall a b. NFData a => a -> b -> b
`deepseq` FilePath -> IO FilePath
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
str