ByteString.hs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. -- {-# LANGUAGE OverloadedStrings #-}
  2. -- {-# LANGUAGE ExistentialQuantification #-}
  3. -- {-# LANGUAGE ForeignFunctionInterface #-}
  4. -- {-# LANGUAGE InterruptibleFFI #-}
  5. -- {-# LANGUAGE EmptyDataDecls #-}
  6. module System.IO.Uniform.ByteString (
  7. ByteStringIO,
  8. withByteStringIO, withByteStringIO'
  9. ) where
  10. import System.IO.Uniform
  11. import Data.ByteString (ByteString)
  12. import qualified Data.ByteString as BS
  13. import qualified Data.ByteString.Lazy as LBS
  14. import qualified Data.ByteString.Builder as BSBuild
  15. --import qualified Data.List as L
  16. --import Control.Exception
  17. --import Control.Applicative ((<$>))
  18. import Data.Monoid (mappend)
  19. --import qualified Network.Socket as Soc
  20. import System.IO.Error
  21. import Control.Concurrent.MVar
  22. --import Data.Default.Class
  23. --import System.Posix.Types (Fd(..))
  24. -- | Wrapper that does UniformIO that reads and writes on the memory.
  25. data ByteStringIO = ByteStringIO {bsioinput :: MVar (ByteString, Bool), bsiooutput :: MVar BSBuild.Builder}
  26. instance UniformIO ByteStringIO where
  27. uRead s n = do
  28. (i, eof) <- takeMVar . bsioinput $ s
  29. if eof
  30. then do
  31. putMVar (bsioinput s) (i, eof)
  32. ioError $ mkIOError eofErrorType "read past end of input" Nothing Nothing
  33. else do
  34. let (r, i') = BS.splitAt n i
  35. let eof' = (BS.null r && n > 0)
  36. putMVar (bsioinput s) (i', eof')
  37. return r
  38. uPut s t = do
  39. o <- takeMVar . bsiooutput $ s
  40. let o' = mappend o $ BSBuild.byteString t
  41. putMVar (bsiooutput s) o'
  42. uClose _ = return ()
  43. startTls _ a = return a
  44. isSecure _ = True
  45. -- | withByteStringIO input f
  46. -- Runs f with a ByteStringIO that has the given input, returns f's output and
  47. -- the ByteStringIO output.
  48. withByteStringIO :: ByteString -> (ByteStringIO -> IO a) -> IO (a, LBS.ByteString)
  49. withByteStringIO input f = do
  50. ivar <- newMVar (input, False)
  51. ovar <- newMVar . BSBuild.byteString $ BS.empty
  52. let bsio = ByteStringIO ivar ovar
  53. a <- f bsio
  54. out <- takeMVar . bsiooutput $ bsio
  55. return (a, BSBuild.toLazyByteString out)
  56. -- | The same as withByteStringIO, but returns an strict ByteString
  57. withByteStringIO' :: ByteString -> (ByteStringIO -> IO a) -> IO (a, ByteString)
  58. withByteStringIO' input f = do
  59. (a, t) <- withByteStringIO input f
  60. return (a, LBS.toStrict t)