packages feed

streaming-bytestring 0.1.2.2 → 0.1.3.0

raw patch · 4 files changed

+139/−49 lines, 4 filesdep +exceptionsdep +resourcetdep +transformers-basedep ~streaming

Dependencies added: exceptions, resourcet, transformers-base

Dependency ranges changed: streaming

Files

Data/ByteString/Streaming.hs view
@@ -169,6 +169,7 @@     -- * Etc.     , zipWithStream    -- zipWithStream :: Monad m => (forall x. a -> ByteString m x -> ByteString m x) -> [a] -> Stream (ByteString m) m r -> Stream (ByteString m) m r      , distribute       -- distribute :: ByteString (t m) a -> t (ByteString m) a +   ) where  import Prelude hiding@@ -207,6 +208,8 @@ import Foreign.Ptr import Data.Functor.Compose import Data.Functor.Sum+import Control.Monad.Trans.Resource+ -- | /O(n)/ Concatenate a stream of byte streams. concat :: Monad m => Stream (ByteString m) m r -> ByteString m r concat x = destroy x join Go Empty @@ -311,9 +314,9 @@  {-| /O(n)/ Convert a monadic byte stream into a single strict 'ByteString',    retaining the return value of the original pair. This operation is-   for use with 'mapsM'.+   for use with 'mapped'. -> mapsM R.toStrict :: Monad m => Stream (ByteString m) m r -> Stream (Of ByteString) m r +> mapped R.toStrict :: Monad m => Stream (ByteString m) m r -> Stream (Of ByteString) m r       It is subject to all the objections one makes to Data.ByteString.Lazy 'toStrict';     all of these are devastating. @@ -361,9 +364,9 @@     followed by the memory of the succession of bytes.       Because one preserves the return value, @toLazy@ is a suitable argument-    for 'Streaming.mapsM'+    for 'Streaming.mapped' ->   S.mapsM Q.toLazy :: Stream (ByteString m) m r -> Stream (Of L.ByteString) m r+>   S.mapped Q.toLazy :: Stream (ByteString m) m r -> Stream (Of L.ByteString) m r  >>> Q.toLazy "hello" "hello" :> ()@@ -410,7 +413,7 @@  -} denull :: Monad m => Stream (ByteString m) m r -> Stream (ByteString m) m r -denull = hoist (run . maps effects) . separate . mapsM nulls+denull = hoist (run . maps effects) . separate . mapped nulls {-#INLINE denull #-}  {- | /O(1)/ Test whether a ByteString is empty, collecting its return value;@@ -420,7 +423,7 @@ False :> () >>> Q.null "" True :> ()->>> S.print $ mapsM R.null $ Q.lines "yours,\nMeredith"+>>> S.print $ mapped R.null $ Q.lines "yours,\nMeredith" False False @@ -443,11 +446,11 @@     There are many ways to remove null bytestrings from a      @Stream (ByteString m) m r@ (besides using @denull@). If we pass next to ->>> mapsM nulls bs :: Stream (Sum (ByteString m) (ByteString m)) m r+>>> mapped nulls bs :: Stream (Sum (ByteString m) (ByteString m)) m r      then can then apply @Streaming.separate@ to get ->>> separate (mapsM nulls bs) :: Stream (ByteString m) (Stream (ByteString m) m) r+>>> separate (mapped nulls bs) :: Stream (ByteString m) (Stream (ByteString m) m) r      The inner monad is now made of the empty bytestrings; we act on this      with @hoist@ , considering that @@ -458,7 +461,7 @@      we have  ->>> hoist (Q.effects . Q.concat) . separate . mapsM Q.nulls+>>> hoist (Q.effects . Q.concat) . separate . mapped Q.nulls   :: Monad n =>  Stream (Q.ByteString n) n b -> Stream (Q.ByteString n) n b  @@ -483,7 +486,7 @@  >>> Q.length "one\ntwo\three\nfour\nfive\n" 23 :> ()->>> S.print $ S.take 3 $ mapsM Q.length $ Q.lines "one\ntwo\three\nfour\nfive\n" +>>> S.print $ S.take 3 $ mapped Q.length $ Q.lines "one\ntwo\three\nfour\nfive\n"  3 8 4@@ -1104,16 +1107,19 @@   where  -- comb :: [P.ByteString] -> [P.ByteString] -> ByteString -> [ByteString] --  comb acc (s:[]) (Empty r)    = Step (revChunks (s:acc) (Return r))-  comb acc [s] (Empty r)    = Step $ L.foldl' (flip Chunk) -                                              (Empty (Return r)) -                                              (s:acc) -  comb acc [s] (Chunk c cs) = comb (s:acc) (S.splitWith p c) cs-  comb acc b (Go m)         = Effect (liftM (comb acc b) m)-  comb acc (s:ss) cs        = Step $ L.foldl' (flip Chunk)  -                                              (Empty (comb [] ss cs)) -                                              (s:acc)-                                              ---  comb acc (s:ss) cs           = Step (revChunks (s:acc) (comb [] ss cs))+  comb acc [s]    (Empty r)    = Step $ L.foldl' (flip Chunk) +                                                 (Empty (Return r)) +                                                 (s:acc) +  comb acc [s]    (Chunk c cs) = comb (s:acc) (S.splitWith p c) cs+  comb acc b      (Go m)       = Effect (liftM (comb acc b) m)+  comb acc (s:ss) cs           = Step $ L.foldl' (flip Chunk)  +                                                 (Empty (comb [] ss cs)) +                                                 (s:acc)+  comb acc []  (Empty r)    = Step $ L.foldl' (flip Chunk) +                                                 (Empty (Return r)) +                                                 acc +  comb acc []  (Chunk c cs) = comb acc (S.splitWith p c) cs                             + --  comb acc (s:ss) cs           = Step (revChunks (s:acc) (comb [] ss cs))  {-# INLINABLE splitWith #-} @@ -1469,29 +1475,67 @@ hGetNonBlocking = hGetNonBlockingN defaultChunkSize {-#INLINE hGetNonBlocking #-} --- | Read an entire file into a chunked 'ByteString IO ()'.--- The Handle will be held open until EOF is encountered.----readFile ::  MonadIO m => FilePath -> ByteString m ()-readFile f = Go $ liftM hGetContents (liftIO (openBinaryFile f ReadMode))-{-#INLINE readFile #-}+{-| Write a 'ByteString' to a file. Use 'Control.Monad.Trans.ResourceT.runResourceT'+    to ensure that the handle is closed.  --- | Write a 'ByteString' to a file.----writeFile :: FilePath -> ByteString IO r -> IO r-writeFile f txt = bracket-    (openBinaryFile f WriteMode)-    hClose-    (\hdl -> hPut hdl txt)+>>> :set -XOverloadedStrings+>>> runResourceT $ Q.writeFile "hello.txt" "Hello world.\nGoodbye world.\n" +>>> :! cat "hello.txt"+Hello world.+Goodbye world.+>>> runResourceT $ Q.writeFile "hello2.txt" $ Q.readFile "hello.txt"+>>> :! cat hello2.txt +Hello world.+Goodbye world.++ -}+writeFile :: MonadResource m => FilePath -> ByteString m r -> m r+writeFile f str = do+  (key, handle) <- allocate (openBinaryFile f WriteMode) hClose+  r <- hPut handle str+  release key+  return r {-# INLINE writeFile #-} --- | Append a 'ByteString' to a file.----appendFile :: FilePath -> ByteString IO r -> IO r-appendFile f txt = bracket-    (openBinaryFile f AppendMode)-    hClose-    (\hdl -> hPut hdl txt)+{-| Read an entire file into a chunked 'ByteString IO ()'.+    The Handle will be held open until EOF is encountered.+    The block governed by 'Control.Monad.Trans.Resource.runResourceT'+    will end with the closing of any handles opened.++>>> :! cat hello.txt+Hello world.+Goodbye world. +>>> runResourceT $ Q.stdout $ Q.readFile "hello.txt"+Hello world.+Goodbye world. +  -}++readFile :: MonadResource m => FilePath -> ByteString m ()+readFile f = bracketByteString (openBinaryFile f ReadMode) hClose hGetContents+{-#INLINE readFile #-}++++{-| Append a 'ByteString' to a file. Use 'Control.Monad.Trans.ResourceT.runResourceT'+    to ensure that the handle is closed. ++>>> runResourceT $ Q.writeFile "hello.txt" "Hello world.\nGoodbye world.\n"+>>> runResourceT $ Q.stdout $ Q.readFile "hello.txt"+Hello world.+Goodbye world.+>>> runResourceT $ Q.appendFile "hello.txt" "sincerely yours,\nArthur\n"+>>> runResourceT $ Q.stdout $  Q.readFile "hello.txt"+Hello world.+Goodbye world.+sincerely yours,+Arthur+  -}+appendFile :: MonadResource m => FilePath -> ByteString m r -> m r+appendFile f str = do+  (key, handle) <- allocate (openBinaryFile f AppendMode) hClose+  r <- hPut handle str+  release key+  return r {-# INLINE appendFile #-}  -- | getContents. Equivalent to hGetContents stdin. Will read /lazily/
Data/ByteString/Streaming/Char8.hs view
@@ -216,7 +216,7 @@ -- | /O(n)/ Convert a stream of separate characters into a packed byte stream. pack :: Monad m => Stream (Of Char) m r -> ByteString m r pack  = fromChunks -        . mapsM (liftM (\(str :> r) -> Char8.pack str :> r) . S.toList) +        . mapped (liftM (\(str :> r) -> Char8.pack str :> r) . S.toList)          . chunksOf 32  {-# INLINABLE pack #-} @@ -502,7 +502,7 @@ --   the genuinely streaming 'words'. A function that returns individual --   strict bytestrings would concatenate even infinitely --   long words like @cycle "y"@ in memory. It is best for the user who---   has reflected on her materials to write `mapsM toStrict . words` or the like,+--   has reflected on her materials to write `mapped toStrict . words` or the like, --   if strict bytestrings are needed. words :: Monad m => ByteString m r -> Stream (ByteString m) m r words =  filtered . R.splitWith B.isSpaceWord8 
Data/ByteString/Streaming/Internal.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE CPP, BangPatterns #-}-{-#LANGUAGE RankNTypes, GADTs #-}+{-# LANGUAGE CPP, BangPatterns, RankNTypes, GADTs #-} {-# LANGUAGE UnliftedFFITypes, MagicHash, UnboxedTuples #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-} +-- for resourcet etc. module Data.ByteString.Streaming.Internal (    ByteString (..)     , consChunk             -- :: S.ByteString -> ByteString m r -> ByteString m r@@ -26,6 +27,9 @@    , reread    , inlinePerformIO    , unsafeLast+   +   -- * ResourceT help+   , bracketByteString   ) where  import Prelude hiding@@ -60,6 +64,9 @@ import GHC.Base                 (realWorld#,unsafeChr) import GHC.IO                   (IO(IO)) +import Control.Monad.Base+import Control.Monad.Trans.Resource+import Control.Monad.Catch (MonadCatch (..)) -- | A space-efficient representation of a succession of 'Word8' vectors, supporting many -- efficient operations. --@@ -133,9 +140,45 @@   {-# INLINE mempty #-}   mappend = liftM2 mappend   {-# INLINE mappend #-}-      --- data Word8_ r = Word8_ {-#UNPACK#-} !Word8 r --- This might be preferable to (Of Word8 r), but the present approach is simpler.++instance (MonadBase b m) => MonadBase b (ByteString m) where+  liftBase  = mwrap . fmap return . liftBase+  {-#INLINE liftBase #-}++instance (MonadThrow m) => MonadThrow (ByteString m) where+  throwM = lift . throwM +  {-#INLINE throwM #-}+++instance (MonadCatch m) => MonadCatch (ByteString m) where+  catch str f = go str+    where+    go p = case p of+      Chunk bs rest  -> Chunk bs (go rest)+      Empty  r       -> Empty r+      Go  m          -> Go (catch (do+          p' <- m+          return (go p'))  +       (\e -> return (f e)) )+  {-#INLINABLE catch #-}+     +instance (MonadResource m) => MonadResource (ByteString m) where+  liftResourceT = lift . liftResourceT+  {-#INLINE liftResourceT #-}++bracketByteString :: (MonadResource m) =>+       IO a -> (a -> IO ()) -> (a -> ByteString m b) -> ByteString m b+bracketByteString alloc free inside = do+        (key, seed) <- lift (allocate alloc free)+        clean key (inside seed)+  where+    clean key = loop where+      loop str = case str of +        Empty r        -> Go (release key >> return (Empty r))+        Go m           -> Go (liftM loop m)+        Chunk bs rest  -> Chunk bs (loop rest)+{-#INLINABLE bracketByteString #-}+  data SPEC = SPEC | SPEC2 {-# ANN type SPEC ForceSpecConstr #-}
streaming-bytestring.cabal view
@@ -1,5 +1,5 @@ name:                streaming-bytestring-version:             0.1.2.2+version:             0.1.3.0 synopsis:            effectful byte steams, or: bytestring io done right.  description:         This is an implementation of effectful, memory-constrained @@ -189,7 +189,10 @@                      , mtl >=2.1 && <2.3                      , mmorph >=1.0 && <1.2                      , transformers >=0.3 && <0.5-                     , streaming >  0.1.2.0 && < 0.1.2.4+                     , transformers-base+                     , streaming >=  0.1.3.0 && <= 0.1.3.5+                     , resourcet+                     , exceptions   if impl(ghc < 7.8)      build-depends:                      bytestring < 0.10.4.0