ByteString.hs 2.0 KB

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