ByteString.hs 1.9 KB

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