{-# LANGUAGE Rank2Types, TypeFamilies #-}

-- This library emulates Data.ByteStream.Lazy but includes a monadic element
-- and thus at certain points uses a `Stream`/`FreeT` type in place of lists.

-- |
-- Module      : ByteStream
-- Copyright   : (c) Don Stewart 2006
--               (c) Duncan Coutts 2006-2011
--               (c) Michael Thompson 2015
--               (c) Udo Stenzel 2018
-- License     : BSD-style
--
-- Maintainer  : u.stenzel@web.de
-- Stability   : experimental
-- Portability : portable
--
-- See the simple examples of use <https://gist.github.com/michaelt/6c6843e6dd8030e95d58 here>.
-- We begin with a slight modification of the documentation to "Data.ByteStream.Lazy":
--
-- A time and space-efficient implementation of effectful byte streams
-- using a stream of packed 'Word8' arrays, suitable for high performance
-- use, both in terms of large data quantities, or high speed
-- requirements. ByteStreams are encoded as streams of strict chunks
-- of bytes.
--
-- A key feature of ByteStreams is the means to manipulate large or
-- unbounded streams of data without requiring the entire sequence to be
-- resident in memory. To take advantage of this you have to write your
-- functions in a streaming style, e.g. classic pipeline composition. The
-- default I\/O chunk size is 32k, which should be good in most circumstances.
--
-- Some operations, such as 'concat', 'append', 'reverse' and 'cons', have
-- better complexity than their "Data.ByteStream" equivalents, due to
-- optimisations resulting from the list spine structure. For other
-- operations streaming, like lazy, ByteStreams are usually within a few percent of
-- strict ones.
--
-- This module is intended to be imported @qualified@, to avoid name
-- clashes with "Prelude" functions.  eg.
--
-- > import qualified Bio.Streaming.Bytes as B
--
-- Original GHC implementation by Bryan O\'Sullivan.
-- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.
-- Rewritten to support slices and use 'Foreign.ForeignPtr.ForeignPtr'
-- by David Roundy.
-- Rewritten again and extended by Don Stewart and Duncan Coutts.
-- Lazy variant by Duncan Coutts and Don Stewart.
-- Streaming variant by Michael Thompson, following the ideas of Gabriel Gonzales' pipes-bytestring
-- Adapted for use in biohazard by Udo Stenzel.
--
module Bio.Streaming.Bytes (
    -- * The @ByteStream@ type
    ByteStream(..)

    -- * Introducing and eliminating 'ByteStream's
    , empty            -- empty :: ByteStream m ()
    , singleton        -- singleton :: Monad m => Word8 -> ByteStream m ()
    , fromLazy         -- fromLazy :: Monad m => ByteStream -> ByteStream m ()
    , fromChunks       -- fromChunks :: Monad m => Stream (Of Bytes) m r -> ByteStream m r
    , toLazy           -- toLazy :: Monad m => ByteStream m () -> m ByteStream
    , toStrict         -- toStrict :: Monad m => ByteStream m () -> m ByteStream
    , effects
    , mwrap

    -- * Basic interface
    , cons             -- cons :: Monad m => Word8 -> ByteStream m r -> ByteStream m r
    , nextByte         -- nextByte :: Monad m => ByteStream m r -> m (Either r (Word8, ByteStream m r))
    , nextByteOff      -- nextByteOff :: Monad m => ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))

    -- * Substrings

    -- ** Breaking strings
    , break            -- break :: Monad m => (Word8 -> Bool) -> ByteStream m r -> ByteStream m (ByteStream m r)
    , drop             -- drop :: Monad m => GHC.Int.Int64 -> ByteStream m r -> ByteStream m r
    , dropWhile
    , splitAt          -- splitAt :: Monad m => GHC.Int.Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
    , splitAt'         -- splitAt' :: Monad m => Int -> ByteStream m r -> m (Of Bytes (ByteStream m r))
    , trim

    -- ** Breaking into many substrings
    , lines
    , lines'

    -- ** Special folds
    , concat          -- concat :: Monad m => Stream (ByteStream m) m r -> ByteStream m r

    -- * Builders
    , toByteStream
    , toByteStreamWith
    , concatBuilders

    -- * I\/O with 'ByteStream's

    -- ** Files
    , withOutputFile
    , writeFile        -- writeFile :: FilePath -> ByteStream IO r -> IO r

    -- ** I\/O with Handles
    , hGetContents     -- hGetContents :: Handle -> ByteStream IO ()
    , hGetContentsN    -- hGetContentsN :: Int -> Handle -> ByteStream IO ()
    , hPut             -- hPut :: Handle -> ByteStream IO r -> IO r

    -- * Simple chunkwise operations
    , nextChunk
    , nextChunkOff
    , consChunk             -- :: Bytes -> ByteStream m r -> ByteStream m r
    , consChunkOff          -- :: Bytes -> Int64 -> ByteStream m r -> ByteStream m r
    , chunk
    , copy
    , mapChunksM_

    -- * compression support
    , gzip
    , gunzip
    , gunzipWith

  ) where

import Bio.Prelude                      hiding (break,concat,drop,dropWhile,lines,splitAt,writeFile,empty,loop)
import Data.ByteString.Builder.Internal
        (Builder,builder,runBuilder,runBuilderWith,bufferSize
        ,AllocationStrategy,ChunkIOStream(..),buildStepToCIOS
        ,byteStringFromBuffer,safeStrategy,defaultChunkSize)
import GHC.Exts                                (SpecConstrAnnotation(..))
import Streaming                               (MFunctor(..),Of(..),Identity(..),destroy)
import Streaming.Internal                      (Stream (..))
import System.Directory                        (renameFile)

import qualified Codec.Compression.Zlib.Internal as Z
import qualified Data.ByteString                 as B
import qualified Data.ByteString.Internal        as B
import qualified Data.ByteString.Lazy.Internal   as L (foldrChunks,ByteString(..),smallChunkSize,defaultChunkSize)
import qualified Data.ByteString.Unsafe          as B
import qualified Streaming.Prelude               as Q

-- | A space-efficient representation of a succession of 'Word8' vectors, supporting many
-- efficient operations.
--
-- An effectful 'ByteStream' contains 8-bit bytes, or by using certain
-- operations can be interpreted as containing 8-bit characters.  It
-- also contains an offset, which will be needed to track the virtual
-- offsets in the BGZF decode.

data ByteStream m r
  = Empty r
  | Chunk {-# UNPACK #-} !Bytes {-# UNPACK #-} !Int64 (ByteStream m r)
  | Go (m (ByteStream m r))

instance Monad m => Functor (ByteStream m) where
  fmap :: (a -> b) -> ByteStream m a -> ByteStream m b
fmap f :: a -> b
f x :: ByteStream m a
x = case ByteStream m a
x of
    Empty a :: a
a        -> b -> ByteStream m b
forall (m :: * -> *) r. r -> ByteStream m r
Empty (a -> b
f a
a)
    Chunk bs :: Bytes
bs o :: Int64
o bss :: ByteStream m a
bss -> Bytes -> Int64 -> ByteStream m b -> ByteStream m b
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs Int64
o ((a -> b) -> ByteStream m a -> ByteStream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f ByteStream m a
bss)
    Go mbss :: m (ByteStream m a)
mbss        -> m (ByteStream m b) -> ByteStream m b
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m a -> ByteStream m b)
-> m (ByteStream m a) -> m (ByteStream m b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((a -> b) -> ByteStream m a -> ByteStream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) m (ByteStream m a)
mbss)

instance Monad m => Applicative (ByteStream m) where
  pure :: a -> ByteStream m a
pure = a -> ByteStream m a
forall (m :: * -> *) r. r -> ByteStream m r
Empty
  {-# INLINE pure #-}
  bf :: ByteStream m (a -> b)
bf <*> :: ByteStream m (a -> b) -> ByteStream m a -> ByteStream m b
<*> bx :: ByteStream m a
bx = do {a -> b
f <- ByteStream m (a -> b)
bf; a
x <- ByteStream m a
bx; b -> ByteStream m b
forall (m :: * -> *) r. r -> ByteStream m r
Empty (a -> b
f a
x)}
  {-# INLINE (<*>) #-}
  *> :: ByteStream m a -> ByteStream m b -> ByteStream m b
(*>) = ByteStream m a -> ByteStream m b -> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>)
  {-# INLINE (*>) #-}

instance Monad m => Monad (ByteStream m) where
  return :: a -> ByteStream m a
return = a -> ByteStream m a
forall (m :: * -> *) r. r -> ByteStream m r
Empty
  {-# INLINE return #-}
  x0 :: ByteStream m a
x0 >> :: ByteStream m a -> ByteStream m b -> ByteStream m b
>> y :: ByteStream m b
y = SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC ByteStream m a
x0 where
    loop :: SPEC -> ByteStream m a -> ByteStream m b
loop !SPEC
_ x :: ByteStream m a
x = case ByteStream m a
x of   -- this seems to be insanely effective
      Empty _     -> ByteStream m b
y
      Chunk a :: Bytes
a o :: Int64
o b :: ByteStream m a
b -> Bytes -> Int64 -> ByteStream m b -> ByteStream m b
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
a Int64
o (SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC ByteStream m a
b)
      Go m :: m (ByteStream m a)
m        -> m (ByteStream m b) -> ByteStream m b
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m a -> ByteStream m b)
-> m (ByteStream m a) -> m (ByteStream m b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC) m (ByteStream m a)
m)
  {-# INLINEABLE (>>) #-}
  x :: ByteStream m a
x >>= :: ByteStream m a -> (a -> ByteStream m b) -> ByteStream m b
>>= f :: a -> ByteStream m b
f =
    SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC2 ByteStream m a
x where -- unlike >> this SPEC seems pointless
      loop :: SPEC -> ByteStream m a -> ByteStream m b
loop !SPEC
_ y :: ByteStream m a
y = case ByteStream m a
y of
        Empty a :: a
a        -> a -> ByteStream m b
f a
a
        Chunk bs :: Bytes
bs o :: Int64
o bss :: ByteStream m a
bss -> Bytes -> Int64 -> ByteStream m b -> ByteStream m b
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs Int64
o (SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC ByteStream m a
bss)
        Go mbss :: m (ByteStream m a)
mbss        -> m (ByteStream m b) -> ByteStream m b
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m a -> ByteStream m b)
-> m (ByteStream m a) -> m (ByteStream m b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SPEC -> ByteStream m a -> ByteStream m b
loop SPEC
SPEC) m (ByteStream m a)
mbss)
  {-# INLINEABLE (>>=) #-}

instance MonadIO m => MonadIO (ByteStream m) where
  liftIO :: IO a -> ByteStream m a
liftIO io :: IO a
io = m (ByteStream m a) -> ByteStream m a
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((a -> ByteStream m a) -> m a -> m (ByteStream m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> ByteStream m a
forall (m :: * -> *) r. r -> ByteStream m r
Empty (IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
io))
  {-# INLINE liftIO #-}

instance MonadTrans ByteStream where
  lift :: m a -> ByteStream m a
lift ma :: m a
ma = m (ByteStream m a) -> ByteStream m a
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go (m (ByteStream m a) -> ByteStream m a)
-> m (ByteStream m a) -> ByteStream m a
forall a b. (a -> b) -> a -> b
$ (a -> ByteStream m a) -> m a -> m (ByteStream m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> ByteStream m a
forall (m :: * -> *) r. r -> ByteStream m r
Empty m a
ma
  {-# INLINE lift #-}

instance MFunctor ByteStream where
  hoist :: (forall a. m a -> n a) -> ByteStream m b -> ByteStream n b
hoist f :: forall a. m a -> n a
f = ByteStream m b -> ByteStream n b
loop where
    loop :: ByteStream m b -> ByteStream n b
loop (Empty     r :: b
r) = b -> ByteStream n b
forall (m :: * -> *) r. r -> ByteStream m r
Empty b
r
    loop (Chunk c :: Bytes
c o :: Int64
o s :: ByteStream m b
s) = Bytes -> Int64 -> ByteStream n b -> ByteStream n b
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (ByteStream m b -> ByteStream n b
loop ByteStream m b
s)
    loop (Go        m :: m (ByteStream m b)
m) = n (ByteStream n b) -> ByteStream n b
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go (m (ByteStream n b) -> n (ByteStream n b)
forall a. m a -> n a
f ((ByteStream m b -> ByteStream n b)
-> m (ByteStream m b) -> m (ByteStream n b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteStream m b -> ByteStream n b
loop m (ByteStream m b)
m))
  {-# INLINEABLE hoist #-}

instance (r ~ ()) => IsString (ByteStream m r) where
  fromString :: String -> ByteStream m r
fromString = Bytes -> ByteStream m ()
forall (m :: * -> *). Bytes -> ByteStream m ()
chunk (Bytes -> ByteStream m ())
-> (String -> Bytes) -> String -> ByteStream m ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Bytes
forall a. IsString a => String -> a
fromString
  {-# INLINE fromString #-}

instance (m ~ Identity, Show r) => Show (ByteStream m r) where
  show :: ByteStream m r -> String
show bs0 :: ByteStream m r
bs0 = case ByteStream m r
bs0 of  -- the implementation this instance deserves ...
    Empty r :: r
r           -> "Empty (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ r -> String
forall a. Show a => a -> String
show r
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ ")"
    Go (Identity bs') -> "Go (Identity (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteStream m r -> String
forall a. Show a => a -> String
show ByteStream m r
bs' String -> ShowS
forall a. [a] -> [a] -> [a]
++ "))"
    Chunk bs'' :: Bytes
bs'' o :: Int64
o bs :: ByteStream m r
bs   -> "Chunk " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bytes -> String
forall a. Show a => a -> String
show Bytes
bs'' String -> ShowS
forall a. [a] -> [a] -> [a]
++ " " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int64 -> String
forall a. Show a => a -> String
show Int64
o String -> ShowS
forall a. [a] -> [a] -> [a]
++ " (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteStream m r -> String
forall a. Show a => a -> String
show ByteStream m r
bs String -> ShowS
forall a. [a] -> [a] -> [a]
++ ")"

instance (Semigroup r, Monad m) => Semigroup (ByteStream m r) where
  <> :: ByteStream m r -> ByteStream m r -> ByteStream m r
(<>) = (r -> r -> r) -> ByteStream m r -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 r -> r -> r
forall a. Semigroup a => a -> a -> a
(<>)
  {-# INLINE (<>) #-}

instance (Semigroup r, Monoid r, Monad m) => Monoid (ByteStream m r) where
  mempty :: ByteStream m r
mempty = r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
forall a. Monoid a => a
mempty
  {-# INLINE mempty #-}
  mappend :: ByteStream m r -> ByteStream m r -> ByteStream m r
mappend = ByteStream m r -> ByteStream m r -> ByteStream m r
forall a. Semigroup a => a -> a -> a
(<>)
  {-# INLINE mappend #-}


data SPEC = SPEC | SPEC2
{-# ANN type SPEC ForceSpecConstr #-}

-- --------------------------------------------------------------------------

-- | Smart constructor for 'Chunk'.
consChunk :: Bytes -> ByteStream m r -> ByteStream m r
consChunk :: Bytes -> ByteStream m r -> ByteStream m r
consChunk c :: Bytes
c = Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
consChunkOff Bytes
c 0
{-# INLINE consChunk #-}

consChunkOff :: Bytes -> Int64 -> ByteStream m r -> ByteStream m r
consChunkOff :: Bytes -> Int64 -> ByteStream m r -> ByteStream m r
consChunkOff c :: Bytes
c@(B.PS _ _ len :: Int
len) off :: Int64
off cs :: ByteStream m r
cs
  | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0  = ByteStream m r
cs
  | Bool
otherwise = Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
off ByteStream m r
cs
{-# INLINE consChunkOff #-}

-- | Yield-style smart constructor for 'Chunk'.
chunk :: Bytes -> ByteStream m ()
chunk :: Bytes -> ByteStream m ()
chunk bs :: Bytes
bs = Bytes -> ByteStream m () -> ByteStream m ()
forall (m :: * -> *) r. Bytes -> ByteStream m r -> ByteStream m r
consChunk Bytes
bs ByteStream m ()
forall (m :: * -> *). ByteStream m ()
empty
{-# INLINE chunk #-}


{- | Reconceive an effect that results in an effectful bytestring as an effectful bytestring.
    Compare Streaming.mwrap. The closes equivalent of

>>> Streaming.wrap :: f (Stream f m r) -> Stream f m r

    is here  @consChunk@. @mwrap@ is the smart constructor for the internal @Go@ constructor.
-}
mwrap :: m (ByteStream m r) -> ByteStream m r
mwrap :: m (ByteStream m r) -> ByteStream m r
mwrap = m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go
{-# INLINE mwrap #-}

-- | Construct a succession of chunks from its Church encoding (compare @GHC.Exts.build@)
materialize :: (forall x . (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x)
            -> ByteStream m r
materialize :: (forall x.
 (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x)
-> ByteStream m r
materialize phi :: forall x. (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
phi = (r -> ByteStream m r)
-> (Bytes -> Int64 -> ByteStream m r -> ByteStream m r)
-> (m (ByteStream m r) -> ByteStream m r)
-> ByteStream m r
forall x. (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
phi r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go
{-# INLINE[0] materialize #-}

-- | Resolve a succession of chunks into its Church encoding; this is
-- not a safe operation; it is equivalent to exposing the constructors
dematerialize :: Monad m
              => ByteStream m r
              -> (forall x . (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x)
dematerialize :: ByteStream m r
-> forall x.
   (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
dematerialize x0 :: ByteStream m r
x0 nil :: r -> x
nil con :: Bytes -> Int64 -> x -> x
con fin :: m x -> x
fin = SPEC -> ByteStream m r -> x
loop SPEC
SPEC ByteStream m r
x0
  where
  loop :: SPEC -> ByteStream m r -> x
loop !SPEC
_ x :: ByteStream m r
x = case ByteStream m r
x of
     Empty r :: r
r      -> r -> x
nil r
r
     Chunk b :: Bytes
b o :: Int64
o bs :: ByteStream m r
bs -> Bytes -> Int64 -> x -> x
con Bytes
b Int64
o (SPEC -> ByteStream m r -> x
loop SPEC
SPEC ByteStream m r
bs )
     Go ms :: m (ByteStream m r)
ms        -> m x -> x
fin ((ByteStream m r -> x) -> m (ByteStream m r) -> m x
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SPEC -> ByteStream m r -> x
loop SPEC
SPEC) m (ByteStream m r)
ms)
{-# INLINE [1] dematerialize #-}

{-# RULES
  "dematerialize/materialize" forall (phi :: forall b . (r -> b) -> (Bytes -> Int64 -> b -> b) -> (m b -> b) -> b) . dematerialize (materialize phi) = phi ;
  #-}
------------------------------------------------------------------------

copy :: Monad m => ByteStream m r -> ByteStream (ByteStream m) r
copy :: ByteStream m r -> ByteStream (ByteStream m) r
copy = ByteStream m r -> ByteStream (ByteStream m) r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> ByteStream (ByteStream m) r
loop where
  loop :: ByteStream m r -> ByteStream (ByteStream m) r
loop str :: ByteStream m r
str = case ByteStream m r
str of
    Empty r :: r
r         -> r -> ByteStream (ByteStream m) r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r
    Go m :: m (ByteStream m r)
m            -> ByteStream m (ByteStream (ByteStream m) r)
-> ByteStream (ByteStream m) r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m r -> ByteStream (ByteStream m) r)
-> ByteStream m (ByteStream m r)
-> ByteStream m (ByteStream (ByteStream m) r)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteStream m r -> ByteStream (ByteStream m) r
loop (m (ByteStream m r) -> ByteStream m (ByteStream m r)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (ByteStream m r)
m))
    Chunk bs :: Bytes
bs o :: Int64
o rest :: ByteStream m r
rest -> Bytes
-> Int64
-> ByteStream (ByteStream m) r
-> ByteStream (ByteStream m) r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs Int64
o (ByteStream m (ByteStream (ByteStream m) r)
-> ByteStream (ByteStream m) r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go (Bytes
-> Int64
-> ByteStream m (ByteStream (ByteStream m) r)
-> ByteStream m (ByteStream (ByteStream m) r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs Int64
o (ByteStream (ByteStream m) r
-> ByteStream m (ByteStream (ByteStream m) r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (ByteStream m r -> ByteStream (ByteStream m) r
loop ByteStream m r
rest))))
{-# INLINABLE copy #-}

-- | /O(n)/ Concatenate a stream of byte streams.
concat :: Monad m => Stream (ByteStream m) m r -> ByteStream m r
concat :: Stream (ByteStream m) m r -> ByteStream m r
concat x :: Stream (ByteStream m) m r
x = Stream (ByteStream m) m r
-> (ByteStream m (ByteStream m r) -> ByteStream m r)
-> (m (ByteStream m r) -> ByteStream m r)
-> (r -> ByteStream m r)
-> ByteStream m r
forall (f :: * -> *) (m :: * -> *) r b.
(Functor f, Monad m) =>
Stream f m r -> (f b -> b) -> (m b -> b) -> (r -> b) -> b
destroy Stream (ByteStream m) m r
x ByteStream m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty
{-# INLINE concat #-}

-- | Perform the effects contained in an effectful bytestring, ignoring the bytes.
effects :: Monad m => ByteStream m r -> m r
effects :: ByteStream m r -> m r
effects bs :: ByteStream m r
bs = case ByteStream m r
bs of
  Empty r :: r
r        -> r -> m r
forall (m :: * -> *) a. Monad m => a -> m a
return r
r
  Go m :: m (ByteStream m r)
m           -> m (ByteStream m r)
m m (ByteStream m r) -> (ByteStream m r -> m r) -> m r
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteStream m r -> m r
forall (m :: * -> *) r. Monad m => ByteStream m r -> m r
effects
  Chunk _ _ rest :: ByteStream m r
rest -> ByteStream m r -> m r
forall (m :: * -> *) r. Monad m => ByteStream m r -> m r
effects ByteStream m r
rest
{-# INLINABLE effects #-}


-- -----------------------------------------------------------------------------
-- Introducing and eliminating 'ByteStream's

{-| /O(1)/ The empty 'ByteStream' -- i.e. @return ()@ Note that @ByteStream m w@ is
  generally a monoid for monoidal values of @w@, like @()@
-}
empty :: ByteStream m ()
empty :: ByteStream m ()
empty = () -> ByteStream m ()
forall (m :: * -> *) r. r -> ByteStream m r
Empty ()
{-# INLINE empty #-}

{-| /O(1)/ Yield a 'Word8' as a minimal 'ByteStream'
-}
singleton :: Word8 -> ByteStream m ()
singleton :: Word8 -> ByteStream m ()
singleton w :: Word8
w = Bytes -> Int64 -> ByteStream m () -> ByteStream m ()
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton Word8
w) 0 (() -> ByteStream m ()
forall (m :: * -> *) r. r -> ByteStream m r
Empty ())
{-# INLINE singleton #-}

-- | /O(c)/ Converts a byte stream into a stream of individual strict bytestrings.
--   This of course exposes the internal chunk structure.
toChunks :: Monad m => ByteStream m r -> Stream (Of Bytes) m r
toChunks :: ByteStream m r -> Stream (Of Bytes) m r
toChunks bs :: ByteStream m r
bs = ByteStream m r
-> (r -> Stream (Of Bytes) m r)
-> (Bytes
    -> Int64 -> Stream (Of Bytes) m r -> Stream (Of Bytes) m r)
-> (m (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r)
-> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r
-> forall x.
   (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
dematerialize ByteStream m r
bs r -> Stream (Of Bytes) m r
forall (m :: * -> *) a. Monad m => a -> m a
return (\b :: Bytes
b _ mx :: Stream (Of Bytes) m r
mx -> Of Bytes (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r
forall (f :: * -> *) (m :: * -> *) r.
f (Stream f m r) -> Stream f m r
Step (Bytes
b Bytes -> Stream (Of Bytes) m r -> Of Bytes (Stream (Of Bytes) m r)
forall a b. a -> b -> Of a b
:> Stream (Of Bytes) m r
mx)) m (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r
forall (f :: * -> *) (m :: * -> *) r.
m (Stream f m r) -> Stream f m r
Effect
{-# INLINE toChunks #-}

mapChunksM_ :: Monad m => (Bytes -> m ()) -> ByteStream m r -> m r
mapChunksM_ :: (Bytes -> m ()) -> ByteStream m r -> m r
mapChunksM_ f :: Bytes -> m ()
f bs :: ByteStream m r
bs = ByteStream m r
-> (r -> m r)
-> (Bytes -> Int64 -> m r -> m r)
-> (m (m r) -> m r)
-> m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r
-> forall x.
   (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
dematerialize ByteStream m r
bs r -> m r
forall (m :: * -> *) a. Monad m => a -> m a
return (\c :: Bytes
c _ k :: m r
k -> Bytes -> m ()
f Bytes
c m () -> m r -> m r
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m r
k) m (m r) -> m r
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join
{-# INLINE mapChunksM_ #-}


-- | /O(c)/ Converts a stream of strict bytestrings into a byte stream.
fromChunks :: Monad m => Stream (Of Bytes) m r -> ByteStream m r
fromChunks :: Stream (Of Bytes) m r -> ByteStream m r
fromChunks bs :: Stream (Of Bytes) m r
bs = Stream (Of Bytes) m r
-> (Of Bytes (Int64 -> ByteStream m r) -> Int64 -> ByteStream m r)
-> (m (Int64 -> ByteStream m r) -> Int64 -> ByteStream m r)
-> (r -> Int64 -> ByteStream m r)
-> Int64
-> ByteStream m r
forall (f :: * -> *) (m :: * -> *) r b.
(Functor f, Monad m) =>
Stream f m r -> (f b -> b) -> (m b -> b) -> (r -> b) -> b
destroy Stream (Of Bytes) m r
bs
      (\(b :: Bytes
b :> mx :: Int64 -> ByteStream m r
mx) !Int64
i -> Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
b Int64
i (Int64 -> ByteStream m r
mx (Int64
i Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
b))))
      (\k :: m (Int64 -> ByteStream m r)
k !Int64
i -> m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go (m (Int64 -> ByteStream m r)
k m (Int64 -> ByteStream m r)
-> ((Int64 -> ByteStream m r) -> m (ByteStream m r))
-> m (ByteStream m r)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \f :: Int64 -> ByteStream m r
f -> ByteStream m r -> m (ByteStream m r)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int64 -> ByteStream m r
f Int64
i)))
      (\r :: r
r !Int64
_ -> r -> ByteStream m r
forall (m :: * -> *) a. Monad m => a -> m a
return r
r) 0
{-# INLINE fromChunks #-}

{-| /O(n)/ Convert a monadic byte stream into a single strict 'ByteStream',
   retaining the return value of the original pair. This operation is
   for use with 'mapped'.

> mapped R.toStrict :: Monad m => Stream (ByteStream m) m r -> Stream (Of ByteStream) m r

   It is subject to all the objections one makes to Data.ByteStream.Lazy 'toStrict';
   all of these are devastating.
-}
toStrict :: Monad m => ByteStream m r -> m (Of Bytes r)
toStrict :: ByteStream m r -> m (Of Bytes r)
toStrict bs :: ByteStream m r
bs = do
  (bss :: [Bytes]
bss :> r :: r
r) <- Stream (Of Bytes) m r -> m (Of [Bytes] r)
forall (m :: * -> *) a r.
Monad m =>
Stream (Of a) m r -> m (Of [a] r)
Q.toList (ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> Stream (Of Bytes) m r
toChunks ByteStream m r
bs)
  Of Bytes r -> m (Of Bytes r)
forall (m :: * -> *) a. Monad m => a -> m a
return (Of Bytes r -> m (Of Bytes r)) -> Of Bytes r -> m (Of Bytes r)
forall a b. (a -> b) -> a -> b
$ ([Bytes] -> Bytes
B.concat [Bytes]
bss Bytes -> r -> Of Bytes r
forall a b. a -> b -> Of a b
:> r
r)
{-# INLINE toStrict #-}

{-| /O(c)/ Transmute a pseudo-pure lazy bytestring to its representation
    as a monadic stream of chunks.

>>> Q.putStrLn $ Q.fromLazy "hi"
hi
>>>  Q.fromLazy "hi"
Chunk "hi" (Empty (()))  -- note: a 'show' instance works in the identity monad
>>>  Q.fromLazy $ BL.fromChunks ["here", "are", "some", "chunks"]
Chunk "here" (Chunk "are" (Chunk "some" (Chunk "chunks" (Empty (())))))

-}
fromLazy :: LazyBytes -> ByteStream m ()
fromLazy :: LazyBytes -> ByteStream m ()
fromLazy = (Bytes -> ByteStream m () -> ByteStream m ())
-> ByteStream m () -> LazyBytes -> ByteStream m ()
forall a. (Bytes -> a -> a) -> a -> LazyBytes -> a
L.foldrChunks Bytes -> ByteStream m () -> ByteStream m ()
forall (m :: * -> *) r. Bytes -> ByteStream m r -> ByteStream m r
consChunk ByteStream m ()
forall (m :: * -> *). ByteStream m ()
empty
{-# INLINE fromLazy #-}

{-| /O(n)/ Convert an effectful byte stream into a single lazy 'ByteStream'
    with the same internal chunk structure, retaining the original
    return value.

    This is the canonical way of breaking streaming (@toStrict@ and the
    like are far more demonic). Essentially one is dividing the interleaved
    layers of effects and bytes into one immense layer of effects,
    followed by the memory of the succession of bytes.

    Because one preserves the return value, @toLazy@ is a suitable argument
    for 'Streaming.mapped'

>   B.mapped Q.toLazy :: Stream (ByteStream m) m r -> Stream (Of LazyBytes) m r

>>> Q.toLazy "hello"
"hello" :> ()
>>> B.toListM $ traverses Q.toLazy $ Q.lines "one\ntwo\nthree\nfour\nfive\n"
["one","two","three","four","five",""]  -- [LazyBytes]

-}
toLazy :: Monad m => ByteStream m r -> m (Of LazyBytes r)
toLazy :: ByteStream m r -> m (Of LazyBytes r)
toLazy bs0 :: ByteStream m r
bs0 = ByteStream m r
-> (r -> m (Of LazyBytes r))
-> (Bytes -> Int64 -> m (Of LazyBytes r) -> m (Of LazyBytes r))
-> (m (m (Of LazyBytes r)) -> m (Of LazyBytes r))
-> m (Of LazyBytes r)
forall (m :: * -> *) r.
Monad m =>
ByteStream m r
-> forall x.
   (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
dematerialize ByteStream m r
bs0
                (\r :: r
r -> Of LazyBytes r -> m (Of LazyBytes r)
forall (m :: * -> *) a. Monad m => a -> m a
return (LazyBytes
L.Empty LazyBytes -> r -> Of LazyBytes r
forall a b. a -> b -> Of a b
:> r
r))
                (\b :: Bytes
b _ mx :: m (Of LazyBytes r)
mx -> do
                      (bs :: LazyBytes
bs :> x :: r
x) <- m (Of LazyBytes r)
mx
                      Of LazyBytes r -> m (Of LazyBytes r)
forall (m :: * -> *) a. Monad m => a -> m a
return (Of LazyBytes r -> m (Of LazyBytes r))
-> Of LazyBytes r -> m (Of LazyBytes r)
forall a b. (a -> b) -> a -> b
$ Bytes -> LazyBytes -> LazyBytes
L.Chunk Bytes
b LazyBytes
bs LazyBytes -> r -> Of LazyBytes r
forall a b. a -> b -> Of a b
:> r
x
                      )
                m (m (Of LazyBytes r)) -> m (Of LazyBytes r)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join
{-# INLINE toLazy #-}

-- | /O(1)/ 'cons' is analogous to '(:)' for lists.
cons :: Word8 -> ByteStream m r -> ByteStream m r
cons :: Word8 -> ByteStream m r -> ByteStream m r
cons c :: Word8
c cs :: ByteStream m r
cs = Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton Word8
c) 0 ByteStream m r
cs
{-# INLINE cons #-}

-- | /O(1)/ Extract the head and tail of a 'ByteStream', or its return value
-- if it is empty. This is the \'natural\' uncons for an effectful byte stream.
nextByte :: Monad m => ByteStream m r -> m (Either r (Word8, ByteStream m r))
nextByte :: ByteStream m r -> m (Either r (Word8, ByteStream m r))
nextByte = (Either r (Word8, Int64, ByteStream m r)
 -> Either r (Word8, ByteStream m r))
-> m (Either r (Word8, Int64, ByteStream m r))
-> m (Either r (Word8, ByteStream m r))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((r -> Either r (Word8, ByteStream m r))
-> ((Word8, Int64, ByteStream m r)
    -> Either r (Word8, ByteStream m r))
-> Either r (Word8, Int64, ByteStream m r)
-> Either r (Word8, ByteStream m r)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either r -> Either r (Word8, ByteStream m r)
forall a b. a -> Either a b
Left (\(a :: Word8
a,_,b :: ByteStream m r
b) -> (Word8, ByteStream m r) -> Either r (Word8, ByteStream m r)
forall a b. b -> Either a b
Right (Word8
a,ByteStream m r
b))) (m (Either r (Word8, Int64, ByteStream m r))
 -> m (Either r (Word8, ByteStream m r)))
-> (ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r)))
-> ByteStream m r
-> m (Either r (Word8, ByteStream m r))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff
{-# INLINE nextByte #-}

nextByteOff :: Monad m => ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff :: ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff (Empty r :: r
r) = Either r (Word8, Int64, ByteStream m r)
-> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (r -> Either r (Word8, Int64, ByteStream m r)
forall a b. a -> Either a b
Left r
r)
nextByteOff (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs)
    = if Bytes -> Bool
B.null Bytes
c
        then ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff ByteStream m r
cs
        else Either r (Word8, Int64, ByteStream m r)
-> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (Either r (Word8, Int64, ByteStream m r)
 -> m (Either r (Word8, Int64, ByteStream m r)))
-> Either r (Word8, Int64, ByteStream m r)
-> m (Either r (Word8, Int64, ByteStream m r))
forall a b. (a -> b) -> a -> b
$ (Word8, Int64, ByteStream m r)
-> Either r (Word8, Int64, ByteStream m r)
forall a b. b -> Either a b
Right (Bytes -> Word8
B.unsafeHead Bytes
c, Int64
o
                     , if Bytes -> Int
B.length Bytes
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1
                         then ByteStream m r
cs
                         else Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Bytes -> Bytes
B.unsafeTail Bytes
c) (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+1) ByteStream m r
cs)
nextByteOff (Go m :: m (ByteStream m r)
m) = m (ByteStream m r)
m m (ByteStream m r)
-> (ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r)))
-> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff
{-# INLINABLE nextByteOff #-}

nextChunk :: Monad m => ByteStream m r -> m (Either r (Bytes, ByteStream m r))
nextChunk :: ByteStream m r -> m (Either r (Bytes, ByteStream m r))
nextChunk = (Either r (Bytes, Int64, ByteStream m r)
 -> Either r (Bytes, ByteStream m r))
-> m (Either r (Bytes, Int64, ByteStream m r))
-> m (Either r (Bytes, ByteStream m r))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((r -> Either r (Bytes, ByteStream m r))
-> ((Bytes, Int64, ByteStream m r)
    -> Either r (Bytes, ByteStream m r))
-> Either r (Bytes, Int64, ByteStream m r)
-> Either r (Bytes, ByteStream m r)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either r -> Either r (Bytes, ByteStream m r)
forall a b. a -> Either a b
Left (\(a :: Bytes
a,_,b :: ByteStream m r
b) -> (Bytes, ByteStream m r) -> Either r (Bytes, ByteStream m r)
forall a b. b -> Either a b
Right (Bytes
a,ByteStream m r
b))) (m (Either r (Bytes, Int64, ByteStream m r))
 -> m (Either r (Bytes, ByteStream m r)))
-> (ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r)))
-> ByteStream m r
-> m (Either r (Bytes, ByteStream m r))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
nextChunkOff
{-# INLINE nextChunk #-}

nextChunkOff :: Monad m => ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
nextChunkOff :: ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
nextChunkOff (Empty r :: r
r)      = Either r (Bytes, Int64, ByteStream m r)
-> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (r -> Either r (Bytes, Int64, ByteStream m r)
forall a b. a -> Either a b
Left r
r)
nextChunkOff (Go m :: m (ByteStream m r)
m)         = m (ByteStream m r)
m m (ByteStream m r)
-> (ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r)))
-> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
nextChunkOff
nextChunkOff (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs)
    | Bytes -> Bool
B.null Bytes
c              = ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Bytes, Int64, ByteStream m r))
nextChunkOff ByteStream m r
cs
    | Bool
otherwise             = Either r (Bytes, Int64, ByteStream m r)
-> m (Either r (Bytes, Int64, ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return ((Bytes, Int64, ByteStream m r)
-> Either r (Bytes, Int64, ByteStream m r)
forall a b. b -> Either a b
Right (Bytes
c,Int64
o,ByteStream m r
cs))
{-# INLINABLE nextChunkOff #-}

{-| /O(n\/c)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@
    elements, or @[]@ if @n > 'length' xs@.

>>> Q.putStrLn $ Q.drop 6 "Wisconsin"
sin
>>> Q.putStrLn $ Q.drop 16 "Wisconsin"

>>>
-}
drop  :: Monad m => Int64 -> ByteStream m r -> ByteStream m r
drop :: Int64 -> ByteStream m r -> ByteStream m r
drop i :: Int64
i p :: ByteStream m r
p | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = ByteStream m r
p
drop i :: Int64
i cs0 :: ByteStream m r
cs0 = Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Monad m =>
Int64 -> ByteStream m r -> ByteStream m r
drop' Int64
i ByteStream m r
cs0
  where drop' :: Int64 -> ByteStream m r -> ByteStream m r
drop' 0 cs :: ByteStream m r
cs           = ByteStream m r
cs
        drop' _ (Empty r :: r
r)    = r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r
        drop' n :: Int64
n (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs) =
          if Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
c)
            then Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n) Bytes
c) (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+Int64
n) ByteStream m r
cs
            else Int64 -> ByteStream m r -> ByteStream m r
drop' (Int64
n Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
c)) ByteStream m r
cs
        drop' n :: Int64
n (Go m :: m (ByteStream m r)
m) = m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m r -> ByteStream m r)
-> m (ByteStream m r) -> m (ByteStream m r)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Int64 -> ByteStream m r -> ByteStream m r
drop' Int64
n) m (ByteStream m r)
m)
{-# INLINABLE drop #-}


{-| /O(n\/c)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.

>>> rest <- Q.putStrLn $ Q.splitAt 3 "therapist is a danger to good hyphenation, as Knuth notes"
the
>>> Q.putStrLn $ Q.splitAt 19 rest
rapist is a danger

-}
splitAt :: Monad m => Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
splitAt :: Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
splitAt i :: Int64
i cs0 :: ByteStream m r
cs0 | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty ByteStream m r
cs0
splitAt i :: Int64
i cs0 :: ByteStream m r
cs0 = Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r.
Monad m =>
Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
go Int64
i ByteStream m r
cs0
  where go :: Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
go 0 cs :: ByteStream m r
cs             = ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty ByteStream m r
cs
        go _ (Empty r :: r
r)      = ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r)
        go n :: Int64
n (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs) =
          if Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
c)
            then Bytes
-> Int64
-> ByteStream m (ByteStream m r)
-> ByteStream m (ByteStream m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.take (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n) Bytes
c) Int64
o (ByteStream m (ByteStream m r) -> ByteStream m (ByteStream m r))
-> ByteStream m (ByteStream m r) -> ByteStream m (ByteStream m r)
forall a b. (a -> b) -> a -> b
$
                     ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n) Bytes
c) (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+Int64
n) ByteStream m r
cs)
            else Bytes
-> Int64
-> ByteStream m (ByteStream m r)
-> ByteStream m (ByteStream m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
go (Int64
n Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
c)) ByteStream m r
cs)
        go n :: Int64
n (Go m :: m (ByteStream m r)
m) = m (ByteStream m (ByteStream m r)) -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m r -> ByteStream m (ByteStream m r))
-> m (ByteStream m r) -> m (ByteStream m (ByteStream m r))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Int64 -> ByteStream m r -> ByteStream m (ByteStream m r)
go Int64
n) m (ByteStream m r)
m)
{-# INLINABLE splitAt #-}

-- | Strictly splits off a piece.  This breaks streaming, so reserve its
-- use for small strings or when conversion to strict 'Bytes' is needed
-- anyway.
splitAt' :: Monad m => Int -> ByteStream m r -> m (Of Bytes (ByteStream m r))
splitAt' :: Int -> ByteStream m r -> m (Of Bytes (ByteStream m r))
splitAt' i :: Int
i cs0 :: ByteStream m r
cs0 | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r)))
-> Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall a b. (a -> b) -> a -> b
$! Bytes
B.empty Bytes -> ByteStream m r -> Of Bytes (ByteStream m r)
forall a b. a -> b -> Of a b
:> ByteStream m r
cs0
splitAt' i :: Int
i cs0 :: ByteStream m r
cs0 = Int -> [Bytes] -> ByteStream m r -> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
Int -> [Bytes] -> ByteStream m r -> m (Of Bytes (ByteStream m r))
go Int
i [] ByteStream m r
cs0
  where go :: Int -> [Bytes] -> ByteStream m r -> m (Of Bytes (ByteStream m r))
go 0 acc :: [Bytes]
acc cs :: ByteStream m r
cs             = Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r)))
-> Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall a b. (a -> b) -> a -> b
$! [Bytes] -> Bytes
B.concat ([Bytes] -> [Bytes]
forall a. [a] -> [a]
reverse [Bytes]
acc) Bytes -> ByteStream m r -> Of Bytes (ByteStream m r)
forall a b. a -> b -> Of a b
:> ByteStream m r
cs
        go _ acc :: [Bytes]
acc (Empty r :: r
r)      = Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r)))
-> Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall a b. (a -> b) -> a -> b
$! [Bytes] -> Bytes
B.concat ([Bytes] -> [Bytes]
forall a. [a] -> [a]
reverse [Bytes]
acc) Bytes -> ByteStream m r -> Of Bytes (ByteStream m r)
forall a b. a -> b -> Of a b
:> r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r
        go n :: Int
n acc :: [Bytes]
acc (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs) =
          if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bytes -> Int
B.length Bytes
c
            then Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) a. Monad m => a -> m a
return (Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r)))
-> Of Bytes (ByteStream m r) -> m (Of Bytes (ByteStream m r))
forall a b. (a -> b) -> a -> b
$! [Bytes] -> Bytes
B.concat ([Bytes] -> [Bytes]
forall a. [a] -> [a]
reverse (Int -> Bytes -> Bytes
B.take Int
n Bytes
c Bytes -> [Bytes] -> [Bytes]
forall a. a -> [a] -> [a]
: [Bytes]
acc))
                        Bytes -> ByteStream m r -> Of Bytes (ByteStream m r)
forall a b. a -> b -> Of a b
:> Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop Int
n Bytes
c) (Int64
o Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) ByteStream m r
cs
            else Int -> [Bytes] -> ByteStream m r -> m (Of Bytes (ByteStream m r))
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Bytes -> Int
B.length Bytes
c) (Bytes
cBytes -> [Bytes] -> [Bytes]
forall a. a -> [a] -> [a]
:[Bytes]
acc) ByteStream m r
cs
        go n :: Int
n acc :: [Bytes]
acc (Go m :: m (ByteStream m r)
m) = m (ByteStream m r)
m m (ByteStream m r)
-> (ByteStream m r -> m (Of Bytes (ByteStream m r)))
-> m (Of Bytes (ByteStream m r))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> [Bytes] -> ByteStream m r -> m (Of Bytes (ByteStream m r))
go Int
n [Bytes]
acc
{-# INLINABLE splitAt' #-}

trim :: Monad m => Int64 -> ByteStream m () -> ByteStream m ()
trim :: Int64 -> ByteStream m () -> ByteStream m ()
trim eoff :: Int64
eoff = ByteStream m () -> ByteStream m ()
go
  where
    go :: ByteStream m () -> ByteStream m ()
go (Empty     _)             = () -> ByteStream m ()
forall (m :: * -> *) r. r -> ByteStream m r
Empty ()
    go (Go        m :: m (ByteStream m ())
m)             = m (ByteStream m ()) -> ByteStream m (ByteStream m ())
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (ByteStream m ())
m ByteStream m (ByteStream m ())
-> (ByteStream m () -> ByteStream m ()) -> ByteStream m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteStream m () -> ByteStream m ()
go
    go (Chunk c :: Bytes
c o :: Int64
o s :: ByteStream m ()
s) | Int64
o Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<  Int64
eoff = Bytes -> Int64 -> ByteStream m () -> ByteStream m ()
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (ByteStream m () -> ByteStream m ()
go ByteStream m ()
s)
                     | Bool
otherwise = () -> ByteStream m ()
forall (m :: * -> *) r. r -> ByteStream m r
Empty ()
{-# INLINABLE trim #-}

-- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.
dropWhile :: Monad m => (Word8 -> Bool) -> ByteStream m r -> ByteStream m r
dropWhile :: (Word8 -> Bool) -> ByteStream m r -> ByteStream m r
dropWhile pr :: Word8 -> Bool
pr = ByteStream m r -> ByteStream m r
drop' where
  drop' :: ByteStream m r -> ByteStream m r
drop' bs :: ByteStream m r
bs = case ByteStream m r
bs of
    Empty r :: r
r      -> r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r
    Go m :: m (ByteStream m r)
m         -> m (ByteStream m r) -> ByteStream m r
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m r -> ByteStream m r)
-> m (ByteStream m r) -> m (ByteStream m r)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteStream m r -> ByteStream m r
drop' m (ByteStream m r)
m)
    Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs -> case (Word8 -> Bool) -> Bytes -> Int
findIndexOrEnd (Bool -> Bool
not(Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
.Word8 -> Bool
pr) Bytes
c of
        0                  -> Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o ByteStream m r
cs
        n :: Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bytes -> Int
B.length Bytes
c -> Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop Int
n Bytes
c) (Int64
o Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) ByteStream m r
cs
          | Bool
otherwise      -> ByteStream m r -> ByteStream m r
drop' ByteStream m r
cs
{-# INLINABLE dropWhile #-}

-- | 'break' @p@ is equivalent to @'span' ('not' . p)@.
break :: Monad m => (Word8 -> Bool) -> ByteStream m r -> ByteStream m (ByteStream m r)
break :: (Word8 -> Bool) -> ByteStream m r -> ByteStream m (ByteStream m r)
break f :: Word8 -> Bool
f cs0 :: ByteStream m r
cs0 = ByteStream m r -> ByteStream m (ByteStream m r)
break' ByteStream m r
cs0
  where break' :: ByteStream m r -> ByteStream m (ByteStream m r)
break' (Empty r :: r
r)        = ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r)
        break' (Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs) =
          case (Word8 -> Bool) -> Bytes -> Int
findIndexOrEnd Word8 -> Bool
f Bytes
c of
            0                  -> ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o ByteStream m r
cs)
            n :: Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Bytes -> Int
B.length Bytes
c -> Bytes
-> Int64
-> ByteStream m (ByteStream m r)
-> ByteStream m (ByteStream m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.take Int
n Bytes
c) Int64
o (ByteStream m (ByteStream m r) -> ByteStream m (ByteStream m r))
-> ByteStream m (ByteStream m r) -> ByteStream m (ByteStream m r)
forall a b. (a -> b) -> a -> b
$
                                      ByteStream m r -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop Int
n Bytes
c) (Int64
o Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) ByteStream m r
cs)
              | Bool
otherwise      -> Bytes
-> Int64
-> ByteStream m (ByteStream m r)
-> ByteStream m (ByteStream m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (ByteStream m r -> ByteStream m (ByteStream m r)
break' ByteStream m r
cs)
        break' (Go m :: m (ByteStream m r)
m) = m (ByteStream m (ByteStream m r)) -> ByteStream m (ByteStream m r)
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go ((ByteStream m r -> ByteStream m (ByteStream m r))
-> m (ByteStream m r) -> m (ByteStream m (ByteStream m r))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteStream m r -> ByteStream m (ByteStream m r)
break' m (ByteStream m r)
m)
{-# INLINABLE break #-}

{- | Read entire handle contents /lazily/ into a 'ByteStream'. Chunks
    are read on demand, in at most @k@-sized chunks. It does not block
    waiting for a whole @k@-sized chunk, so if less than @k@ bytes are
    available then they will be returned immediately as a smaller chunk.

    The handle is closed on EOF.

    Note: the 'Handle' should be placed in binary mode with
    'System.IO.hSetBinaryMode' for 'hGetContentsN' to
    work correctly.
-}
hGetContentsN :: MonadIO m => Int -> Handle -> ByteStream m ()
hGetContentsN :: Int -> Handle -> ByteStream m ()
hGetContentsN k :: Int
k h :: Handle
h = Int64 -> ByteStream m ()
loop 0
  where
    loop :: Int64 -> ByteStream m ()
loop !Int64
o = do
        Bytes
c <- IO Bytes -> ByteStream m Bytes
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Int -> IO Bytes
B.hGetSome Handle
h Int
k)
        -- only blocks if there is no data available
        if Bytes -> Bool
B.null Bytes
c
          then () -> ByteStream m ()
forall (m :: * -> *) r. r -> ByteStream m r
Empty ()
          else Bytes -> Int64 -> ByteStream m () -> ByteStream m ()
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (Int64 -> ByteStream m ()
loop (Int64
o Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
c)))
{-# INLINABLE hGetContentsN #-} -- very effective inline pragma

{-| Read entire handle contents /lazily/ into a 'ByteStream'. Chunks
    are read on demand, using the default chunk size.

    Note: the 'Handle' should be placed in binary mode with
    'System.IO.hSetBinaryMode' for 'hGetContents' to
    work correctly.
-}
hGetContents :: MonadIO m => Handle -> ByteStream m ()
hGetContents :: Handle -> ByteStream m ()
hGetContents = Int -> Handle -> ByteStream m ()
forall (m :: * -> *). MonadIO m => Int -> Handle -> ByteStream m ()
hGetContentsN Int
defaultChunkSize
{-# INLINE hGetContents #-}


withOutputFile :: (MonadIO m, MonadMask m) => FilePath -> (Handle -> m a) -> m a
withOutputFile :: String -> (Handle -> m a) -> m a
withOutputFile "-" k :: Handle -> m a
k = Handle -> m a
k Handle
stdout
withOutputFile  f :: String
f  k :: Handle -> m a
k = m Handle -> (Handle -> m ()) -> (Handle -> m a) -> m a
forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket (IO Handle -> m Handle
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ String -> IOMode -> IO Handle
openBinaryFile (String
fString -> ShowS
forall a. [a] -> [a] -> [a]
++".#~#") IOMode
WriteMode) (IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (Handle -> IO ()) -> Handle -> m ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Handle -> IO ()
hClose) ((Handle -> m a) -> m a) -> (Handle -> m a) -> m a
forall a b. (a -> b) -> a -> b
$ \hdl :: Handle
hdl ->
                       Handle -> m a
k Handle
hdl m a -> (a -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r :: a
r -> IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> String -> IO ()
renameFile (String
fString -> ShowS
forall a. [a] -> [a] -> [a]
++".#~#") String
f) m () -> m a -> m a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
r
{-# INLINE withOutputFile #-}

{-| Writes a 'ByteStream' to a file.  Actually writes to a temporary
    file and renames it on successful completion.  The filename \"-\"
    causes it to write to stdout instead.
 -}
writeFile :: (MonadIO m, MonadMask m) => FilePath -> ByteStream m r -> m r
writeFile :: String -> ByteStream m r -> m r
writeFile f :: String
f str :: ByteStream m r
str = String -> (Handle -> m r) -> m r
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
String -> (Handle -> m a) -> m a
withOutputFile String
f ((Handle -> m r) -> m r) -> (Handle -> m r) -> m r
forall a b. (a -> b) -> a -> b
$ \hdl :: Handle
hdl -> Handle -> ByteStream m r -> m r
forall (m :: * -> *) r.
MonadIO m =>
Handle -> ByteStream m r -> m r
hPut Handle
hdl ByteStream m r
str
{-# INLINE writeFile #-}

-- | Outputs a 'ByteStream' to the specified 'Handle'.
hPut ::  MonadIO m => Handle -> ByteStream m r -> m r
hPut :: Handle -> ByteStream m r -> m r
hPut h :: Handle
h cs :: ByteStream m r
cs = ByteStream m r
-> (r -> m r)
-> (Bytes -> Int64 -> m r -> m r)
-> (m (m r) -> m r)
-> m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r
-> forall x.
   (r -> x) -> (Bytes -> Int64 -> x -> x) -> (m x -> x) -> x
dematerialize ByteStream m r
cs r -> m r
forall (m :: * -> *) a. Monad m => a -> m a
return (\x :: Bytes
x _ y :: m r
y -> IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Bytes -> IO ()
B.hPut Handle
h Bytes
x) m () -> m r -> m r
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m r
y) (m (m r) -> (m r -> m r) -> m r
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m r -> m r
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id)
{-# INLINE hPut #-}

-- -- ---------------------------------------------------------------------
-- -- Internal utilities

-- | 'findIndexOrEnd' is a variant of findIndex, that returns the length
-- of the string if no element is found, rather than Nothing.
findIndexOrEnd :: (Word8 -> Bool) -> Bytes -> Int
findIndexOrEnd :: (Word8 -> Bool) -> Bytes -> Int
findIndexOrEnd k :: Word8 -> Bool
k (B.PS x :: ForeignPtr Word8
x s :: Int
s l :: Int
l) =
    IO Int -> Int
forall a. IO a -> a
unsafeDupablePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
    ForeignPtr Word8 -> (Ptr Word8 -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
x ((Ptr Word8 -> IO Int) -> IO Int)
-> (Ptr Word8 -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \f :: Ptr Word8
f -> Ptr Word8 -> Int -> IO Int
go (Ptr Word8
f Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
s) 0
  where
    go :: Ptr Word8 -> Int -> IO Int
go !Ptr Word8
ptr !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
               | Bool
otherwise = do Word8
w <- Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
ptr
                                if Word8 -> Bool
k Word8
w
                                  then Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
                                  else Ptr Word8 -> Int -> IO Int
go (Ptr Word8
ptr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` 1) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1)
{-# INLINABLE findIndexOrEnd #-}

{- Take a builder constructed otherwise and convert it to a genuine
   streaming bytestring.

>>>  Q.putStrLn $ Q.toByteStream $ stringUtf8 "哈斯克尔" <> stringUtf8 " " <> integerDec 98
哈斯克尔 98

    <https://gist.github.com/michaelt/6ea89ca95a77b0ef91f3 This benchmark> shows its
    indistinguishable performance is indistinguishable from @toLazyByteStream@
-}

toByteStream :: MonadIO m => Builder -> ByteStream m ()
toByteStream :: Builder -> ByteStream m ()
toByteStream = AllocationStrategy -> Builder -> ByteStream m ()
forall (m :: * -> *).
MonadIO m =>
AllocationStrategy -> Builder -> ByteStream m ()
toByteStreamWith (Int -> Int -> AllocationStrategy
safeStrategy Int
L.smallChunkSize Int
L.defaultChunkSize)
{-# INLINE toByteStream #-}

{-| Take a builder and convert it to a genuine
   streaming bytestring, using a specific allocation strategy.
-}
toByteStreamWith :: MonadIO m => AllocationStrategy -> Builder -> ByteStream m ()
toByteStreamWith :: AllocationStrategy -> Builder -> ByteStream m ()
toByteStreamWith strategy :: AllocationStrategy
strategy builder0 :: Builder
builder0 = do
       ChunkIOStream ()
cios <- IO (ChunkIOStream ()) -> ByteStream m (ChunkIOStream ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (AllocationStrategy -> BuildStep () -> IO (ChunkIOStream ())
forall a. AllocationStrategy -> BuildStep a -> IO (ChunkIOStream a)
buildStepToCIOS AllocationStrategy
strategy (Builder -> BuildStep ()
runBuilder Builder
builder0))
       let loop :: Int64 -> ChunkIOStream r -> ByteStream m r
loop !Int64
o cios0 :: ChunkIOStream r
cios0 = case ChunkIOStream r
cios0 of
              Yield1 bs :: Bytes
bs io :: IO (ChunkIOStream r)
io   -> Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs Int64
o (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ do
                    ChunkIOStream r
cios1 <- IO (ChunkIOStream r) -> ByteStream m (ChunkIOStream r)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (ChunkIOStream r)
io
                    Int64 -> ChunkIOStream r -> ByteStream m r
loop (Int64
o Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
bs)) ChunkIOStream r
cios1
              Finished buf :: Buffer
buf r :: r
r -> Int64 -> Buffer -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Int64 -> Buffer -> ByteStream m r -> ByteStream m r
trimmedChunkFromBuffer Int64
o Buffer
buf (r -> ByteStream m r
forall (m :: * -> *) r. r -> ByteStream m r
Empty r
r)
           trimmedChunkFromBuffer :: Int64 -> Buffer -> ByteStream m r -> ByteStream m r
trimmedChunkFromBuffer o :: Int64
o buffer :: Buffer
buffer k :: ByteStream m r
k
              | Bytes -> Bool
B.null Bytes
bs                            = ByteStream m r
k
              |  2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Bytes -> Int
B.length Bytes
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Buffer -> Int
bufferSize Buffer
buffer = Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Bytes -> Bytes
B.copy Bytes
bs) Int64
o ByteStream m r
k
              | Bool
otherwise                            = Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
bs          Int64
o ByteStream m r
k
              where
                bs :: Bytes
bs = Buffer -> Bytes
byteStringFromBuffer Buffer
buffer
       Int64 -> ChunkIOStream () -> ByteStream m ()
forall (m :: * -> *) r.
MonadIO m =>
Int64 -> ChunkIOStream r -> ByteStream m r
loop 0 ChunkIOStream ()
cios
{-# INLINABLE toByteStreamWith #-}
{-# SPECIALIZE toByteStreamWith :: AllocationStrategy -> Builder -> ByteStream IO () #-}


{- Concatenate a stream of builders (not a streaming bytestring!) into a single builder.

>>> let aa = yield (integerDec 10000) >> yield (string8 " is a number.") >> yield (char8 '\n')
>>>  hPutBuilder  IO.stdout $ concatBuilders aa
10000 is a number.

-}
concatBuilders :: Stream (Of Builder) IO () -> Builder
concatBuilders :: Stream (Of Builder) IO () -> Builder
concatBuilders p :: Stream (Of Builder) IO ()
p = (forall r. BuildStep r -> BuildStep r) -> Builder
builder ((forall r. BuildStep r -> BuildStep r) -> Builder)
-> (forall r. BuildStep r -> BuildStep r) -> Builder
forall a b. (a -> b) -> a -> b
$ \bstep :: BuildStep r
bstep r :: BufferRange
r -> do
  case Stream (Of Builder) IO ()
p of
    Return _          -> Builder -> BuildStep r -> BuildStep r
forall a. Builder -> BuildStep a -> BuildStep a
runBuilderWith Builder
forall a. Monoid a => a
mempty BuildStep r
bstep BufferRange
r
    Step (b :: Builder
b :> rest :: Stream (Of Builder) IO ()
rest)  -> Builder -> BuildStep r -> BuildStep r
forall a. Builder -> BuildStep a -> BuildStep a
runBuilderWith (Builder
b Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Stream (Of Builder) IO () -> Builder
concatBuilders Stream (Of Builder) IO ()
rest) BuildStep r
bstep BufferRange
r
    Effect m :: IO (Stream (Of Builder) IO ())
m            -> IO (Stream (Of Builder) IO ())
m IO (Stream (Of Builder) IO ())
-> (Stream (Of Builder) IO () -> IO (BuildSignal r))
-> IO (BuildSignal r)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \p' :: Stream (Of Builder) IO ()
p' -> Builder -> BuildStep r -> BuildStep r
forall a. Builder -> BuildStep a -> BuildStep a
runBuilderWith (Stream (Of Builder) IO () -> Builder
concatBuilders Stream (Of Builder) IO ()
p') BuildStep r
bstep BufferRange
r
{-# INLINABLE concatBuilders #-}

{- | Turns a ByteStream into a connected stream of ByteStreams that
     divide at newline characters. The resulting strings do not contain
     newlines.  This is the genuinely streaming 'lines' which only
     breaks chunks, and thus never increases the use of memory.

     Because 'ByteStream's are usually read in binary mode, with no line
     ending conversion, this function recognizes both @\\n@ and @\\r\\n@
     endings (regardless of the current platform). -}

lines :: Monad m => ByteStream m r -> Stream (ByteStream m) m r
lines :: ByteStream m r -> Stream (ByteStream m) m r
lines text0 :: ByteStream m r
text0 = ByteStream m r -> Stream (ByteStream m) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> Stream (ByteStream m) m r
loop1 ByteStream m r
text0
  where
    loop1 :: Monad m => ByteStream m r -> Stream (ByteStream m) m r
    loop1 :: ByteStream m r -> Stream (ByteStream m) m r
loop1 text :: ByteStream m r
text =
      case ByteStream m r
text of
        Empty r :: r
r -> r -> Stream (ByteStream m) m r
forall (f :: * -> *) (m :: * -> *) r. r -> Stream f m r
Return r
r
        Go m :: m (ByteStream m r)
m -> m (Stream (ByteStream m) m r) -> Stream (ByteStream m) m r
forall (f :: * -> *) (m :: * -> *) r.
m (Stream f m r) -> Stream f m r
Effect (m (Stream (ByteStream m) m r) -> Stream (ByteStream m) m r)
-> m (Stream (ByteStream m) m r) -> Stream (ByteStream m) m r
forall a b. (a -> b) -> a -> b
$ (ByteStream m r -> Stream (ByteStream m) m r)
-> m (ByteStream m r) -> m (Stream (ByteStream m) m r)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteStream m r -> Stream (ByteStream m) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> Stream (ByteStream m) m r
loop1 m (ByteStream m r)
m
        Chunk c :: Bytes
c _ cs :: ByteStream m r
cs
          | Bytes -> Bool
B.null Bytes
c -> ByteStream m r -> Stream (ByteStream m) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> Stream (ByteStream m) m r
loop1 ByteStream m r
cs
          | Bool
otherwise -> ByteStream m (Stream (ByteStream m) m r)
-> Stream (ByteStream m) m r
forall (f :: * -> *) (m :: * -> *) r.
f (Stream f m r) -> Stream f m r
Step (Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Monad m =>
Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 Maybe Int64
forall a. Maybe a
Nothing ByteStream m r
text)
    loop2 :: Monad m => Maybe Int64 -> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
    loop2 :: Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 prevCr :: Maybe Int64
prevCr text :: ByteStream m r
text =
      case ByteStream m r
text of
        Empty r :: r
r -> case Maybe Int64
prevCr of
          Just  o :: Int64
o -> Bytes
-> Int64
-> ByteStream m (Stream (ByteStream m) m r)
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton 13) Int64
o (Stream (ByteStream m) m r
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (r -> Stream (ByteStream m) m r
forall (f :: * -> *) (m :: * -> *) r. r -> Stream f m r
Return r
r))
          Nothing -> Stream (ByteStream m) m r
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (r -> Stream (ByteStream m) m r
forall (f :: * -> *) (m :: * -> *) r. r -> Stream f m r
Return r
r)
        Go m :: m (ByteStream m r)
m -> m (ByteStream m (Stream (ByteStream m) m r))
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r. m (ByteStream m r) -> ByteStream m r
Go (m (ByteStream m (Stream (ByteStream m) m r))
 -> ByteStream m (Stream (ByteStream m) m r))
-> m (ByteStream m (Stream (ByteStream m) m r))
-> ByteStream m (Stream (ByteStream m) m r)
forall a b. (a -> b) -> a -> b
$ (ByteStream m r -> ByteStream m (Stream (ByteStream m) m r))
-> m (ByteStream m r)
-> m (ByteStream m (Stream (ByteStream m) m r))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Monad m =>
Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 Maybe Int64
prevCr) m (ByteStream m r)
m
        Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs ->
          case Word8 -> Bytes -> Maybe Int
B.elemIndex 10 Bytes
c of
            Nothing -> case Bytes -> Int
B.length Bytes
c of
              0 -> Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Monad m =>
Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 Maybe Int64
prevCr ByteStream m r
cs
              l :: Int
l -> if Bytes -> Word8
B.unsafeLast Bytes
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 13
                     then Bytes
-> Int64
-> ByteStream m (Stream (ByteStream m) m r)
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Bytes -> Bytes
B.unsafeInit Bytes
c) Int64
o (Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Monad m =>
Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 (Int64 -> Maybe Int64
forall a. a -> Maybe a
Just (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
-1 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)) ByteStream m r
cs)
                     else Bytes
-> Int64
-> ByteStream m (Stream (ByteStream m) m r)
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
c Int64
o (Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Monad m =>
Maybe Int64
-> ByteStream m r -> ByteStream m (Stream (ByteStream m) m r)
loop2 Maybe Int64
forall a. Maybe a
Nothing ByteStream m r
cs)
            Just i :: Int
i -> do
              let prefixLength :: Int
prefixLength =
                    if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 1 Bool -> Bool -> Bool
&& Bytes -> Int -> Word8
B.unsafeIndex Bytes
c (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 13 -- \r\n (dos)
                      then Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-1
                      else Int
i
                  rest :: ByteStream m r
rest =
                    if Bytes -> Int
B.length Bytes
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+1
                      then Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Bytes
c) (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+1 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i) ByteStream m r
cs
                      else ByteStream m r
cs
                  result :: ByteStream m (Stream (ByteStream m) m r)
result = Bytes
-> Int64
-> ByteStream m (Stream (ByteStream m) m r)
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.unsafeTake Int
prefixLength Bytes
c) Int64
o (Stream (ByteStream m) m r
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r. r -> ByteStream m r
Empty (ByteStream m r -> Stream (ByteStream m) m r
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> Stream (ByteStream m) m r
loop1 ByteStream m r
rest))
              case Maybe Int64
prevCr of
                Just oo :: Int64
oo | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 -> Bytes
-> Int64
-> ByteStream m (Stream (ByteStream m) m r)
-> ByteStream m (Stream (ByteStream m) m r)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton 13) Int64
oo ByteStream m (Stream (ByteStream m) m r)
result
                _               -> ByteStream m (Stream (ByteStream m) m r)
result
{-# INLINABLE lines #-}

{- | Turns a 'ByteStream' into a stream of strict 'Bytes' that divide at
     newline characters. The resulting strings do not contain newlines.
     This will cost memory if the lines are very long.  -}

lines' :: Monad m => ByteStream m r -> Stream (Of Bytes) m r
lines' :: ByteStream m r -> Stream (Of Bytes) m r
lines' = [Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
[Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 []
  where
    loop1 :: Monad m => [Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
    loop1 :: [Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 acc :: [Bytes]
acc text :: ByteStream m r
text =
      case ByteStream m r
text of
        Empty r :: r
r -> r
r r -> Stream (Of Bytes) m () -> Stream (Of Bytes) m r
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Bool -> Stream (Of Bytes) m () -> Stream (Of Bytes) m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Bytes] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Bytes]
acc) (Bytes -> Stream (Of Bytes) m ()
forall (m :: * -> *) a. Monad m => a -> Stream (Of a) m ()
Q.yield (Bytes -> Bytes
checkCR (Bytes -> Bytes) -> Bytes -> Bytes
forall a b. (a -> b) -> a -> b
$ [Bytes] -> Bytes
B.concat ([Bytes] -> [Bytes]
forall a. [a] -> [a]
reverse [Bytes]
acc)))
        Go m :: m (ByteStream m r)
m    -> m (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r
forall (f :: * -> *) (m :: * -> *) r.
m (Stream f m r) -> Stream f m r
Effect (m (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r)
-> m (Stream (Of Bytes) m r) -> Stream (Of Bytes) m r
forall a b. (a -> b) -> a -> b
$ (ByteStream m r -> Stream (Of Bytes) m r)
-> m (ByteStream m r) -> m (Stream (Of Bytes) m r)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ([Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
[Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 [Bytes]
acc) m (ByteStream m r)
m
        Chunk c :: Bytes
c o :: Int64
o cs :: ByteStream m r
cs
          | Bytes -> Bool
B.null Bytes
c  -> [Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
[Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 [Bytes]
acc ByteStream m r
cs
          | Bool
otherwise ->
              case Word8 -> Bytes -> Maybe Int
B.elemIndex 10 Bytes
c of
                Just  i :: Int
i -> Bytes -> Stream (Of Bytes) m r -> Stream (Of Bytes) m r
forall (m :: * -> *) a r.
Monad m =>
a -> Stream (Of a) m r -> Stream (Of a) m r
Q.cons (Bytes -> Bytes
checkCR (Bytes -> Bytes) -> Bytes -> Bytes
forall a b. (a -> b) -> a -> b
$ if [Bytes] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Bytes]
acc then Int -> Bytes -> Bytes
B.take Int
i Bytes
c else [Bytes] -> Bytes
B.concat ([Bytes] -> [Bytes]
forall a. [a] -> [a]
reverse (Int -> Bytes -> Bytes
B.take Int
i Bytes
c Bytes -> [Bytes] -> [Bytes]
forall a. a -> [a] -> [a]
: [Bytes]
acc)))
                                  ([Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
[Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 [] (Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Int -> Bytes -> Bytes
B.drop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Bytes
c) (Int64
oInt64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+1 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i) ByteStream m r
cs))
                Nothing -> [Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
forall (m :: * -> *) r.
Monad m =>
[Bytes] -> ByteStream m r -> Stream (Of Bytes) m r
loop1 (Bytes
cBytes -> [Bytes] -> [Bytes]
forall a. a -> [a] -> [a]
:[Bytes]
acc) ByteStream m r
cs
    checkCR :: Bytes -> Bytes
checkCR s :: Bytes
s
        | Bytes -> Bool
B.null Bytes
s        =  Bytes
s
        | Bytes -> Word8
B.last Bytes
s Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 13  =  Bytes -> Bytes
B.init Bytes
s
        | Bool
otherwise       =  Bytes
s
{-# INLINABLE lines' #-}

-- --------------------------------------------------------------------------

{-| Decompresses GZip if present.  If any GZip stream is found, all
    such streams are decompressed and any remaining data is discarded.
    Else, the input is returned unchanged.  If the input is BGZF, the
    result will contain meaningful virtual offsets.  If the input
    contains exactly one GZip stream, the result will have meaningfull
    offsets into the uncompressed data.  Else, the offsets will be
    bogus. -}

gunzip :: MonadIO m => ByteStream m r -> ByteStream m r
gunzip :: ByteStream m r -> ByteStream m r
gunzip = (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
MonadIO m =>
(ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
gunzipWith ByteStream m r -> ByteStream m r
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
{-# INLINABLE gunzip #-}

{-| Checks if the input is GZip at all, and runs gunzip if it is.  If
    it isn't, it runs 'k' on the input. -}

gunzipWith :: MonadIO m => (ByteStream m r -> ByteStream m r)
                        -> ByteStream m r -> ByteStream m r
gunzipWith :: (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
gunzipWith k :: ByteStream m r -> ByteStream m r
k s0 :: ByteStream m r
s0 = m (Either r (Word8, Int64, ByteStream m r))
-> ByteStream m (Either r (Word8, Int64, ByteStream m r))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Word8, Int64, ByteStream m r))
nextByteOff ByteStream m r
s0) ByteStream m (Either r (Word8, Int64, ByteStream m r))
-> (Either r (Word8, Int64, ByteStream m r) -> ByteStream m r)
-> ByteStream m r
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Right (31, o :: Int64
o, s' :: ByteStream m r
s') -> m (Either r (Word8, ByteStream m r))
-> ByteStream m (Either r (Word8, ByteStream m r))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteStream m r -> m (Either r (Word8, ByteStream m r))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Word8, ByteStream m r))
nextByte ByteStream m r
s') ByteStream m (Either r (Word8, ByteStream m r))
-> (Either r (Word8, ByteStream m r) -> ByteStream m r)
-> ByteStream m r
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Right (139,s'' :: ByteStream m r
s'') -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
MonadIO m =>
Int64 -> ByteStream m r -> ByteStream m r
gunzipLoop Int64
o (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk ([Word8] -> Bytes
B.pack [31,139]) Int64
o ByteStream m r
s''
        Right ( c :: Word8
c, s'' :: ByteStream m r
s'') -> ByteStream m r -> ByteStream m r
k (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk ([Word8] -> Bytes
B.pack [31,Word8
c]) Int64
o ByteStream m r
s''
        Left     r :: r
r      -> ByteStream m r -> ByteStream m r
k (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton 31) Int64
o (r -> ByteStream m r
forall (f :: * -> *) a. Applicative f => a -> f a
pure r
r)
    Right ( c :: Word8
c, o :: Int64
o, s' :: ByteStream m r
s')   -> ByteStream m r -> ByteStream m r
k (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Bytes -> Int64 -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk (Word8 -> Bytes
B.singleton Word8
c) Int64
o ByteStream m r
s'
    Left       r :: r
r        -> ByteStream m r -> ByteStream m r
k (ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ r -> ByteStream m r
forall (f :: * -> *) a. Applicative f => a -> f a
pure r
r
{-# INLINABLE gunzipWith #-}

{-| Decompresses a gzip stream.  If the leftovers look like another
    gzip stream, it recurses (some files, notably those produced by
    bgzip, contain multiple streams).  Otherwise, the leftovers are
    discarded (some compressed HETFA files appear to have junk at the
    end). -}

gunzipLoop :: MonadIO m => Int64 -> ByteStream m r -> ByteStream m r
gunzipLoop :: Int64 -> ByteStream m r -> ByteStream m r
gunzipLoop o :: Int64
o = Int64
-> Int64 -> DecompressStream IO -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) b.
MonadIO m =>
Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go Int64
o (Int64 -> Int -> Int64
forall a. Bits a => a -> Int -> a
shiftL Int64
o 16) (DecompressStream IO -> ByteStream m r -> ByteStream m r)
-> DecompressStream IO -> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Format -> DecompressParams -> DecompressStream IO
Z.decompressIO Format
Z.gzipOrZlibFormat DecompressParams
Z.defaultDecompressParams
  where
    -- get next chunk, make sure it is empty iff the input ended
    go :: Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go inoff :: Int64
inoff outoff :: Int64
outoff (Z.DecompressInputRequired next :: Bytes -> IO (DecompressStream IO)
next) inp :: ByteStream m b
inp =
        m (Either b (Bytes, ByteStream m b))
-> ByteStream m (Either b (Bytes, ByteStream m b))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteStream m b -> m (Either b (Bytes, ByteStream m b))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Bytes, ByteStream m r))
nextChunk ByteStream m b
inp) ByteStream m (Either b (Bytes, ByteStream m b))
-> (Either b (Bytes, ByteStream m b) -> ByteStream m b)
-> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            Left r :: b
r          -> do DecompressStream IO
z <- IO (DecompressStream IO) -> ByteStream m (DecompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Bytes -> IO (DecompressStream IO)
next Bytes
B.empty)
                                  Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go Int64
inoff Int64
outoff DecompressStream IO
z (b -> ByteStream m b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
r)
            Right (ck :: Bytes
ck,inp' :: ByteStream m b
inp')
                | Bytes -> Bool
B.null Bytes
ck ->    Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go Int64
inoff Int64
outoff ((Bytes -> IO (DecompressStream IO)) -> DecompressStream IO
forall (m :: * -> *).
(Bytes -> m (DecompressStream m)) -> DecompressStream m
Z.DecompressInputRequired Bytes -> IO (DecompressStream IO)
next) ByteStream m b
inp'
                | Bool
otherwise -> do DecompressStream IO
z <- IO (DecompressStream IO) -> ByteStream m (DecompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Bytes -> IO (DecompressStream IO)
next Bytes
ck)
                                  Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go (Int64
inoff Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
ck)) Int64
outoff DecompressStream IO
z ByteStream m b
inp'

    go inoff :: Int64
inoff outoff :: Int64
outoff (Z.DecompressOutputAvailable outchunk :: Bytes
outchunk next :: IO (DecompressStream IO)
next) inp :: ByteStream m b
inp = do
        DecompressStream IO
z <- Bytes
-> Int64
-> ByteStream m (DecompressStream IO)
-> ByteStream m (DecompressStream IO)
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
outchunk Int64
outoff (IO (DecompressStream IO) -> ByteStream m (DecompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (DecompressStream IO)
next)
        Int64
-> Int64 -> DecompressStream IO -> ByteStream m b -> ByteStream m b
go Int64
inoff (Int64
outoff Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
outchunk)) DecompressStream IO
z ByteStream m b
inp

    go inoff :: Int64
inoff _outoff :: Int64
_outoff (Z.DecompressStreamEnd inchunk :: Bytes
inchunk) inp :: ByteStream m b
inp =
        -- decompress leftovers if possible, else return
        (ByteStream m b -> ByteStream m b)
-> ByteStream m b -> ByteStream m b
forall (m :: * -> *) r.
MonadIO m =>
(ByteStream m r -> ByteStream m r)
-> ByteStream m r -> ByteStream m r
gunzipWith (m b -> ByteStream m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m b -> ByteStream m b)
-> (ByteStream m b -> m b) -> ByteStream m b -> ByteStream m b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteStream m b -> m b
forall (m :: * -> *) r. Monad m => ByteStream m r -> m r
effects) (Bytes -> Int64 -> ByteStream m b -> ByteStream m b
forall (m :: * -> *) r.
Bytes -> Int64 -> ByteStream m r -> ByteStream m r
Chunk Bytes
inchunk (Int64
inoff Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
B.length Bytes
inchunk)) ByteStream m b
inp)

    go _inoff :: Int64
_inoff _outoff :: Int64
_outoff (Z.DecompressStreamError derr :: DecompressError
derr) _inp :: ByteStream m b
_inp =
        IO b -> ByteStream m b
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO b -> ByteStream m b) -> IO b -> ByteStream m b
forall a b. (a -> b) -> a -> b
$ DecompressError -> IO b
forall e a. Exception e => e -> IO a
throwIO DecompressError
derr

-- | Compresses a byte stream using GZip with default parameters.
gzip :: MonadIO m => ByteStream m r -> ByteStream m r
gzip :: ByteStream m r -> ByteStream m r
gzip = CompressStream IO -> ByteStream m r -> ByteStream m r
forall (m :: * -> *) b.
MonadIO m =>
CompressStream IO -> ByteStream m b -> ByteStream m b
go (CompressStream IO -> ByteStream m r -> ByteStream m r)
-> CompressStream IO -> ByteStream m r -> ByteStream m r
forall a b. (a -> b) -> a -> b
$ Format -> CompressParams -> CompressStream IO
Z.compressIO Format
Z.gzipFormat CompressParams
Z.defaultCompressParams
  where
    -- get next chunk, make sure it is empty iff the input ended
    go :: CompressStream IO -> ByteStream m b -> ByteStream m b
go (Z.CompressInputRequired next :: Bytes -> IO (CompressStream IO)
next) inp :: ByteStream m b
inp =
        m (Either b (Bytes, ByteStream m b))
-> ByteStream m (Either b (Bytes, ByteStream m b))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteStream m b -> m (Either b (Bytes, ByteStream m b))
forall (m :: * -> *) r.
Monad m =>
ByteStream m r -> m (Either r (Bytes, ByteStream m r))
nextChunk ByteStream m b
inp) ByteStream m (Either b (Bytes, ByteStream m b))
-> (Either b (Bytes, ByteStream m b) -> ByteStream m b)
-> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            Left r :: b
r          -> IO (CompressStream IO) -> ByteStream m (CompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Bytes -> IO (CompressStream IO)
next Bytes
B.empty) ByteStream m (CompressStream IO)
-> (CompressStream IO -> ByteStream m b) -> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CompressStream IO -> ByteStream m b -> ByteStream m b)
-> ByteStream m b -> CompressStream IO -> ByteStream m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip CompressStream IO -> ByteStream m b -> ByteStream m b
go (b -> ByteStream m b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
r)
            Right (ck :: Bytes
ck,inp' :: ByteStream m b
inp')
                | Bytes -> Bool
B.null Bytes
ck -> CompressStream IO -> ByteStream m b -> ByteStream m b
go ((Bytes -> IO (CompressStream IO)) -> CompressStream IO
forall (m :: * -> *).
(Bytes -> m (CompressStream m)) -> CompressStream m
Z.CompressInputRequired Bytes -> IO (CompressStream IO)
next) ByteStream m b
inp'
                | Bool
otherwise -> IO (CompressStream IO) -> ByteStream m (CompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Bytes -> IO (CompressStream IO)
next Bytes
ck) ByteStream m (CompressStream IO)
-> (CompressStream IO -> ByteStream m b) -> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CompressStream IO -> ByteStream m b -> ByteStream m b)
-> ByteStream m b -> CompressStream IO -> ByteStream m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip CompressStream IO -> ByteStream m b -> ByteStream m b
go ByteStream m b
inp'

    go (Z.CompressOutputAvailable outchunk :: Bytes
outchunk next :: IO (CompressStream IO)
next) inp :: ByteStream m b
inp =
        Bytes -> ByteStream m ()
forall (m :: * -> *). Bytes -> ByteStream m ()
chunk Bytes
outchunk ByteStream m ()
-> ByteStream m (CompressStream IO)
-> ByteStream m (CompressStream IO)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO (CompressStream IO) -> ByteStream m (CompressStream IO)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (CompressStream IO)
next ByteStream m (CompressStream IO)
-> (CompressStream IO -> ByteStream m b) -> ByteStream m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CompressStream IO -> ByteStream m b -> ByteStream m b)
-> ByteStream m b -> CompressStream IO -> ByteStream m b
forall a b c. (a -> b -> c) -> b -> a -> c
flip CompressStream IO -> ByteStream m b -> ByteStream m b
go ByteStream m b
inp

    go Z.CompressStreamEnd inp :: ByteStream m b
inp = m b -> ByteStream m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ByteStream m b -> m b
forall (m :: * -> *) r. Monad m => ByteStream m r -> m r
effects ByteStream m b
inp)