------------------------------------------------------------------------
-- |
-- Module           : What4.Utils.Streams
-- Description      : IO stream utilities
-- Copyright        : (c) Galois, Inc 2013-2020
-- License          : BSD3
-- Maintainer       : Joe Hendrix <jhendrix@galois.com>
-- Stability        : provisional
------------------------------------------------------------------------
module What4.Utils.Streams
( logErrorStream
) where

import           Data.ByteString (ByteString)
import           Data.Text (unpack)
import           Data.Text.Encoding (decodeUtf8With)
import           Data.Text.Encoding.Error (lenientDecode)
import qualified System.IO.Streams as Streams

-- | Write from input stream to a logging function.
logErrorStream :: Streams.InputStream ByteString
               -> (String -> IO ()) -- ^ Logging function
               -> IO ()
logErrorStream :: InputStream ByteString -> (String -> IO ()) -> IO ()
logErrorStream InputStream ByteString
err_stream String -> IO ()
logFn = do
  -- Have err_stream log complete lines to logLn
  let write_err :: Maybe String -> IO ()
write_err Maybe String
Nothing = () -> IO ()
forall a. a -> IO a
forall (m :: Type -> Type) a. Monad m => a -> m a
return ()
      write_err (Just String
b) = String -> IO ()
logFn String
b
  OutputStream String
err_output <- (Maybe String -> IO ()) -> IO (OutputStream String)
forall a. (Maybe a -> IO ()) -> IO (OutputStream a)
Streams.makeOutputStream Maybe String -> IO ()
write_err
  InputStream String
lns <- (ByteString -> String)
-> InputStream ByteString -> IO (InputStream String)
forall a b. (a -> b) -> InputStream a -> IO (InputStream b)
Streams.map (Text -> String
unpack (Text -> String) -> (ByteString -> Text) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode) (InputStream ByteString -> IO (InputStream String))
-> IO (InputStream ByteString) -> IO (InputStream String)
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< InputStream ByteString -> IO (InputStream ByteString)
Streams.lines InputStream ByteString
err_stream
  InputStream String -> OutputStream String -> IO ()
forall a. InputStream a -> OutputStream a -> IO ()
Streams.connect InputStream String
lns OutputStream String
err_output