ByteString.hs 1.9 KB

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