packages feed

streaming-binary (empty) → 0.1.0.0

raw patch · 8 files changed

+184/−0 lines, 8 filesdep +basedep +binarydep +bytestringsetup-changed

Dependencies added: base, binary, bytestring, hspec, streaming, streaming-binary, streaming-bytestring

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Mathieu Boespflug (c) 2017++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.++    * Neither the name of Mathieu Boespflug nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"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 COPYRIGHT+OWNER OR CONTRIBUTORS 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.
+ README.md view
@@ -0,0 +1,6 @@+# streaming-binary++This library offers incremental serialization and deserialization of+Haskell values using the `binary` package. Under the hood, we wrap the+incremental decoders from `binary`'s Incremental API as first-class+streams as defined in `streaming`.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Streaming/Binary.hs view
@@ -0,0 +1,57 @@+-- | This module implements a method to ingest a sequence of "Data.Binary"+-- encoded records using bounded memory. Minimal example:+--+-- > {-# LANGUAGE TypeApplications #-}+-- >+-- > import Data.Function ((&))+-- > import qualified Data.ByteString.Streaming as Q+-- > import Streaming+-- > import Streaming.Binary+-- > import qualified Streaming.Prelude as S+-- >+-- > -- Interpret all bytes on stdin as a sequence of integers.+-- > -- Print them on-the-fly on stdout.+-- > main = Q.getContents & decoded @Int & S.print++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++module Streaming.Binary (decoded) where++import qualified Data.Binary.Get as Binary+import Data.Binary (Binary, get)+import qualified Data.ByteString.Streaming as Q+import Data.ByteString.Streaming (ByteString)+import Data.Int (Int64)+import Streaming+import qualified Streaming.Prelude as S++_decode+  :: (Binary a, Monad m)+  => ByteString m r+  -> m (ByteString m r, Int64, Either String a)+_decode = undefined -- TODO implement this.++decoded+  :: (Binary a, Monad m)+  => ByteString m r+  -> Stream (Of a) m (ByteString m r, Int64, Either String r)+decoded = go 0 decoder0+  where+    decoder0 = Binary.runGetIncremental get+    go !total (Binary.Fail leftover nconsumed err) p = do+        return (Q.chunk leftover >> p, total + nconsumed, Left err)+    go !total (Binary.Done "" nconsumed x) p = do+        S.yield x+        lift (Q.nextChunk p) >>= \case+          Left res -> return (return res, total + nconsumed, Right res)+          Right (bs, p') -> do+            go (total + nconsumed) decoder0 (Q.chunk bs >> p')+    go !total (Binary.Done leftover nconsumed x) p = do+        S.yield x+        go (total + nconsumed) decoder0 (Q.chunk leftover >> p)+    go !total (Binary.Partial k) p = do+      lift (Q.nextChunk p) >>= \case+        Left res -> go total (k Nothing) (return res)+        Right (bs, p') -> go total (k (Just bs)) p'
+ streaming-binary.cabal view
@@ -0,0 +1,45 @@+name: streaming-binary+version: 0.1.0.0+synopsis: Streaming interface to binary.+homepage: https://github.com/mboes/streaming-binary#readme+license: BSD3+license-file: LICENSE+author: Mathieu Boespflug+maintainer: m@tweag.io+copyright: (c) 2017 Mathieu Boespflug+category: Streaming, Parsing+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++source-repository head+  type: git+  location: https://github.com/mboes/streaming-binary++library+  hs-source-dirs: src+  exposed-modules: Streaming.Binary+  build-depends:+    base >= 4.7 && < 5,+    binary >= 0.8,+    streaming >= 0.1.4,+    streaming-bytestring >= 0.1.4+  default-language: Haskell2010++test-suite tests+  type: exitcode-stdio-1.0+  hs-source-dirs: test+  main-is: Main.hs+  other-modules:+    Spec+    Streaming.BinarySpec+  build-depends:+    base,+    binary,+    bytestring >= 0.10,+    hspec >= 2.4,+    streaming,+    streaming-binary,+    streaming-bytestring+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  default-language: Haskell2010
+ test/Main.hs view
@@ -0,0 +1,7 @@+module Main where++import qualified Spec+import Test.Hspec++main :: IO ()+main = hspec Spec.spec
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-}
+ test/Streaming/BinarySpec.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE TypeApplications #-}++module Streaming.BinarySpec where++import Control.Monad (replicateM_, void)+import Data.Binary (put)+import Data.Binary.Put (runPut)+import Data.Function ((&))+import qualified Data.ByteString.Streaming as Q+import Streaming.Binary+import qualified Streaming.Prelude as S+import Test.Hspec++spec :: Spec+spec = do+    let input n = Q.fromLazy $ runPut $ replicateM_ n $ put (42 :: Int)+    describe "decoded" $ do+      it "succeeds on empty inputs" $ do+        output <- void (decoded @Int (input 0)) & S.toList_+        output `shouldBe` []+      it "decodes single integers" $ do+        output <- void (decoded @Int (input 1)) & S.toList_+        output `shouldBe` [42]+      it "decodes multiple integers" $ do+        output <- void (decoded @Int (input 10)) & S.toList_+        output `shouldBe` (replicate 10 42)+      it "decodes multiple integers even when the input is incomplete" $ do+        n <- fromIntegral <$> Q.length_ (input 10)+        let input' = Q.take (n - 1) (input 10)+        output <- void (decoded @Int input') & S.toList_+        output `shouldBe` (replicate 9 42)+      it "leaves the right amount of leftover on incomplete input" $ do+        n <- Q.length_ (input 10)+        let input' = Q.take (fromIntegral (n - 1)) (input 10)+        (leftover, _, _) <- S.effects (decoded @Int input')+        Q.length_ leftover `shouldReturn` (n `div` 10) - 1