ByteString.hs 2.4 KB

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