packages feed

pipe-enumerator (empty) → 0.1.0.0

raw patch · 4 files changed

+196/−0 lines, 4 filesdep +basedep +enumeratordep +pipessetup-changed

Dependencies added: base, enumerator, pipes, transformers

Files

+ LICENSE view
@@ -0,0 +1,28 @@++  Pipe/Iteratee Bridge+  ====================++    Copyright © 2015 Patryk Zadarnowski «pat@jantar.org».+    All rights reserved.++  Redistribution and use in source and binary forms, with or without+  modification, are permitted provided that the following conditions+  are met: ➀ Redistributions of source code must retain the above+  copyright notice, this list of conditions and the following disclaimer.+  ➁ Redistributions in binary form must reproduce the above copyright notice,+  this list of conditions and the following disclaimer in the documentation+  and/or other materials provided with the distribution. ➂ The name of any+  author may not be used to endorse or promote products derived from this+  software without their specific prior written permission.++  THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY+  AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL+  THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS;+  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Setup.hs view
@@ -0,0 +1,3 @@+#! /usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ pipe-enumerator.cabal view
@@ -0,0 +1,43 @@+name:           pipe-enumerator+version:        0.1.0.0+synopsis:       Pipes/iteratees bridge library+homepage:       https://github.com/zadarnowski/pipe-enumerator+category:       Control, Pipes+stability:      alpha++author:         Patryk Zadarnowski+maintainer:     Patryk Zadarnowski <pat@jantar.org>++copyright:      Copyright (c) 2015 Patryk Zadarnowski++description:++    This library provides a bridge between pipe-based and iteratee-based programs.++cabal-version:  >= 1.18+build-type:     Simple+license:        BSD3+license-file:   LICENSE++source-repository head+  type:         git+  location:     https://github.com/zadarnowski/pipe-enumerator.git++source-repository this+  type:         git+  location:     https://github.com/zadarnowski/pipe-enumerator.git+  tag:          0.1.0.0++library+  hs-source-dirs:   src+  default-language: Haskell2010+  ghc-options:      -Wall -fno-warn-unused-do-bind -fno-warn-unused-binds++  exposed-modules:+    Pipes.Enumerator++  build-depends:+    base                    >= 4.8 && < 5,+    enumerator              >= 0.4.20,+    pipes                   >= 4.1.5,+    transformers            >= 0.4.2.0
+ src/Pipes/Enumerator.lhs view
@@ -0,0 +1,122 @@+> module Pipes.Enumerator (+>   pipeToEnumerator+> ) where++> import Control.Monad.Trans.Class+> import qualified Pipes.Internal as P+> import qualified Data.Enumerator as E++  Data Type Reference+  ===================++    data Proxy a' a b' b m r+        = Request a' (a  -> Proxy a' a b' b m r )+        | Respond b  (b' -> Proxy a' a b' b m r )+        | M          (m    (Proxy a' a b' b m r))+        | Pure    r++    type Pipe a b = Proxy () a () b++    type Enumerator a m b = Step a m b -> Iteratee a m b++    data Step a m b =+        Continue (Stream a -> Iteratee a m b)+      | Yield b (Stream a)+      | Error SomeException++    newtype Iteratee a m b = Iteratee { runIteratee :: m (Step a m b) }++    data Stream a =+        Chunks [a]+      | EOF++  Connect a pipe to an iteratee, effectively converting it into an enumerator,+  generalised slightly to allow distinct input and output types. The chunks of+  the input stream are fed into the pipe one element at the time, and the pipe's+  output is fed to the iteratee one element per chunk. Once the input reaches+  @E.EOF@, the pipe is fed an infinite stream of @Nothing@ until it ends with+  a pure value. In effect, both the pipe and the iteratee are always consumed+  fully, with the resulting enumerator returning the results of both.++> pipeToEnumerator :: Monad m => P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)+> pipeToEnumerator = advanceIteratee []+>  where++    State Machine 1+    ===============++    Advance a single iteratee step, keeping track of any input @cs@ that has been+    supplied by the upstream enumerator but not yet used. If the target iteratee blocks,+    we will supply it with input obtained by advancing source pipe; otherwise, we'll+    simply drain the pipe to completion, in order to retrieve the remainder of the+    upstream input and the pipe's return value:++>   advanceIteratee :: Monad m => [a] -> P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)+>   advanceIteratee cs p (E.Continue ik)      = advancePipe cs ik p+>   advanceIteratee cs p s                    = drainPipe cs s p++    Advance a pipe, feeding its response into a blocked iteratee @ik@.++>   advancePipe :: Monad m => [a] -> (E.Stream b -> E.Iteratee b m r) -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)+>   advancePipe cs ik (P.Request _ pk)        = advancePipeWithChunks ik pk cs+>   advancePipe cs ik (P.Respond x pk)        = ik (E.Chunks [x]) E.>>== advanceIteratee cs (pk ())+>   advancePipe cs ik (P.M m)                 = lift m >>= advancePipe cs ik+>   advancePipe cs ik (P.Pure q)              = ik (E.EOF) E.>>== finish q (E.Chunks cs)++>   advancePipeWithChunks :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> [a] -> E.Iteratee a m (q, r)+>   advancePipeWithChunks ik pk (c:cs)        = advancePipe cs ik (pk (Just c))+>   advancePipeWithChunks ik pk []            = E.continue (advancePipeWithStream ik pk)++>   advancePipeWithStream :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Stream a -> E.Iteratee a m (q, r)+>   advancePipeWithStream ik pk (E.Chunks cs) = advancePipeWithChunks ik pk cs+>   advancePipeWithStream ik pk (E.EOF)       = advancePipeWithEOF ik pk++>   drainPipe :: Monad m => [a] -> E.Step b m r -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)+>   drainPipe cs s (P.Request _ pk)           = drainPipeWithChunks s pk cs+>   drainPipe cs s (P.Respond _ pk)           = drainPipe cs s (pk ())+>   drainPipe cs s (P.M m)                    = lift m >>= drainPipe cs s+>   drainPipe cs s (P.Pure q)                 = finish q (E.Chunks cs) s++>   drainPipeWithChunks :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> [a] -> E.Iteratee a m (q, r)+>   drainPipeWithChunks s pk (c:cs)           = drainPipe cs s (pk (Just c))+>   drainPipeWithChunks s pk []               = E.continue (drainPipeWithStream s pk)++>   drainPipeWithStream :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Stream a -> E.Iteratee a m (q, r)+>   drainPipeWithStream s pk (E.Chunks cs)    = drainPipeWithChunks s pk cs+>   drainPipeWithStream s pk (E.EOF)          = drainPipeWithEOF s pk+++    State Machine 2+    ===============++>   advanceIteratee' :: Monad m => P.Proxy a' (Maybe a) () b m q -> E.Step b m r -> E.Iteratee a m (q, r)+>   advanceIteratee' p (E.Continue ik)        = advancePipe' ik p+>   advanceIteratee' p s                      = drainPipe' s p++>   advancePipe' :: Monad m => (E.Stream b -> E.Iteratee b m r) -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)+>   advancePipe' ik (P.Request _ pk)          = advancePipeWithEOF ik pk+>   advancePipe' ik (P.Respond x pk)          = ik (E.Chunks [x]) E.>>== advanceIteratee' (pk ())+>   advancePipe' ik (P.M m)                   = lift m >>= advancePipe' ik+>   advancePipe' ik (P.Pure q)                = ik (E.EOF) E.>>== finish q (E.EOF)++>   advancePipeWithEOF :: Monad m => (E.Stream b -> E.Iteratee b m r) -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Iteratee a m (q, r)+>   advancePipeWithEOF ik pk                  = advancePipe' ik (pk Nothing)++>   drainPipe' :: Monad m => E.Step b m r -> P.Proxy a' (Maybe a) () b m q -> E.Iteratee a m (q, r)+>   drainPipe' s (P.Request _ pk)             = drainPipeWithEOF s pk+>   drainPipe' s (P.Respond _ pk)             = drainPipe' s (pk ())+>   drainPipe' s (P.M m)                      = lift m >>= drainPipe' s+>   drainPipe' s (P.Pure q)                   = finish q (E.EOF) s++>   drainPipeWithEOF :: Monad m => E.Step b m r -> (Maybe a -> P.Proxy a' (Maybe a) () b m q) -> E.Iteratee a m (q, r)+>   drainPipeWithEOF s pk                     = drainPipe' s (pk Nothing)+++    Final Step+    ==========++>   finish :: Monad m => q -> E.Stream a -> E.Step b m r -> E.Iteratee a m (q, r)+>   finish q xs (E.Yield r _)                 = E.yield (q, r) xs+>   finish _ _  (E.Error e)                   = E.throwError e+>   finish _ _  (E.Continue _)                = error "divergent iteratee" -- iteratees aren't allowed to continue on EOF+