Uniform.hs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. {-# LANGUAGE ExistentialQuantification #-}
  2. -- {-# LANGUAGE OverloadedStrings #-}
  3. -- {-# LANGUAGE ForeignFunctionInterface #-}
  4. -- {-# LANGUAGE InterruptibleFFI #-}
  5. -- {-# LANGUAGE EmptyDataDecls #-}
  6. -- |
  7. -- Uniform-IO provides a typeclass for uniform access of different types of targets,
  8. -- and implementations for abstracting standard streams, files and network connections.
  9. -- This module also provides TLS wraping over other IO targets.
  10. module System.IO.Uniform (
  11. UniformIO(..),
  12. TlsSettings(..),
  13. SomeIO(..),
  14. mapOverInput
  15. ) where
  16. import Data.ByteString (ByteString)
  17. import Control.Exception
  18. import Control.Applicative ((<$>))
  19. import System.IO.Error
  20. import Data.Default.Class
  21. -- |
  22. -- Typeclass for uniform IO targets.
  23. class UniformIO a where
  24. -- | uRead fd n
  25. --
  26. -- Reads a block of at most n bytes of data from the IO target.
  27. -- Reading will block if there's no data available, but will return immediately
  28. -- if any amount of data is availble.
  29. --
  30. -- Must thow System.IO.Error.EOFError if reading beihond EOF.
  31. uRead :: a -> Int -> IO ByteString
  32. -- | uPut fd text
  33. --
  34. -- Writes all the bytes of text into the IO target. Takes care of retrying if needed.
  35. uPut :: a -> ByteString -> IO ()
  36. -- | fClose fd
  37. --
  38. -- Closes the IO target, releasing any allocated resource. Resources may leak if not called
  39. -- for every oppened fd.
  40. uClose :: a -> IO ()
  41. -- | startTLS fd
  42. --
  43. -- Starts a TLS connection over the IO target.
  44. startTls :: TlsSettings -> a -> IO a
  45. -- | isSecure fd
  46. --
  47. -- Indicates whether the data written or read from fd is secure at transport.
  48. isSecure :: a -> Bool
  49. -- | A type that wraps any type in the UniformIO class.
  50. data SomeIO = forall a. (UniformIO a) => SomeIO a
  51. instance UniformIO SomeIO where
  52. uRead (SomeIO s) n = uRead s n
  53. uPut (SomeIO s) t = uPut s t
  54. uClose (SomeIO s) = uClose s
  55. startTls set (SomeIO s) = SomeIO <$> startTls set s
  56. isSecure (SomeIO s) = isSecure s
  57. -- | Settings for starttls functions.
  58. data TlsSettings = TlsSettings {tlsPrivateKeyFile :: String, tlsCertificateChainFile :: String, tlsDHParametersFile :: String} deriving (Read, Show)
  59. instance Default TlsSettings where
  60. def = TlsSettings "" "" ""
  61. -- | mapOverInput io block_size f initial
  62. -- Reads io untill the end of file, evaluating a(i) <- f a(i-1) read_data
  63. -- where a(0) = initial and the last value after io reaches EOF is returned.
  64. --
  65. -- Notice that the length of read_data might not be equal block_size.
  66. mapOverInput :: forall a io. UniformIO io => io -> Int -> (a -> ByteString -> IO a) -> a -> IO a
  67. mapOverInput io block f initial = do
  68. a <- tryIOError $ uRead io block
  69. case a of
  70. Left e -> if isEOFError e then return initial else throw e -- EOF
  71. Right dt -> do
  72. i <- f initial dt
  73. mapOverInput io block f i