Uniform.hs 2.6 KB

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