module System.IO.Uniform (
UniformIO(..),
TlsSettings(..),
SomeIO(..),
mapOverInput,
uGetContents
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as LBS
import Control.Exception
import System.IO.Error
import Data.Default.Class
class UniformIO a where
uRead :: a -> Int -> IO ByteString
uPut :: a -> ByteString -> IO ()
uClose :: a -> IO ()
startTls :: TlsSettings -> a -> IO a
isSecure :: a -> Bool
data SomeIO = forall a. (UniformIO a) => SomeIO a
instance UniformIO SomeIO where
uRead (SomeIO s) = uRead s
uPut (SomeIO s) = uPut s
uClose (SomeIO s) = uClose s
startTls set (SomeIO s) = SomeIO <$> startTls set s
isSecure (SomeIO s) = isSecure s
data TlsSettings = TlsSettings {tlsPrivateKeyFile :: String, tlsCertificateChainFile :: String, tlsDHParametersFile :: String} deriving (Read, Show)
instance Default TlsSettings where
def = TlsSettings "" "" ""
mapOverInput :: forall a io. UniformIO io => io -> Int -> (a -> ByteString -> IO a) -> a -> IO a
mapOverInput io block f initial = do
a <- tryIOError $ uRead io block
case a of
Left e -> if isEOFError e then return initial else throw e
Right dt -> do
i <- f initial dt
mapOverInput io block f i
uGetContents :: UniformIO io => io -> Int -> IO LBS.ByteString
uGetContents io block = LBS.fromChunks <$> mapOverInput io block atEnd []
where
atEnd :: [ByteString] -> ByteString -> IO [ByteString]
atEnd bb b = return $ bb ++ [b]