packages feed

binary 0.7.6.1 → 0.8.0.0

raw patch · 16 files changed

+606/−178 lines, 16 filesdep +tardep +unordered-containersdep +zlibdep ~Cabaldep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: tar, unordered-containers, zlib

Dependency ranges changed: Cabal, base, bytestring, criterion

API changes (from Hackage documentation)

- Data.Binary: class GBinary f
- Data.Binary.Get.Internal: instance Alternative Get
- Data.Binary.Get.Internal: instance Applicative Get
- Data.Binary.Get.Internal: instance Functor Decoder
- Data.Binary.Get.Internal: instance Functor Get
- Data.Binary.Get.Internal: instance Monad Get
- Data.Binary.Get.Internal: instance MonadPlus Get
- Data.Binary.Get.Internal: instance Show a => Show (Decoder a)
- Data.Binary.Put: instance [safe] Applicative PutM
- Data.Binary.Put: instance [safe] Functor PutM
- Data.Binary.Put: instance [safe] Monad PutM
- Data.Binary.Put: unPut :: PutM a -> PairS a
+ Data.Binary: class GBinaryGet f
+ Data.Binary: class GBinaryPut f
+ Data.Binary.Get.Internal: instance GHC.Base.Alternative Data.Binary.Get.Internal.Get
+ Data.Binary.Get.Internal: instance GHC.Base.Applicative Data.Binary.Get.Internal.Get
+ Data.Binary.Get.Internal: instance GHC.Base.Functor Data.Binary.Get.Internal.Decoder
+ Data.Binary.Get.Internal: instance GHC.Base.Functor Data.Binary.Get.Internal.Get
+ Data.Binary.Get.Internal: instance GHC.Base.Monad Data.Binary.Get.Internal.Get
+ Data.Binary.Get.Internal: instance GHC.Base.MonadPlus Data.Binary.Get.Internal.Get
+ Data.Binary.Get.Internal: instance GHC.Show.Show a => GHC.Show.Show (Data.Binary.Get.Internal.Decoder a)
+ Data.Binary.Put: [unPut] :: PutM a -> PairS a
+ Data.Binary.Put: instance GHC.Base.Applicative Data.Binary.Put.PutM
+ Data.Binary.Put: instance GHC.Base.Functor Data.Binary.Put.PutM
+ Data.Binary.Put: instance GHC.Base.Monad Data.Binary.Put.PutM
- Data.Binary: gget :: GBinary f => Get (f t)
+ Data.Binary: gget :: GBinaryGet f => Get (f t)
- Data.Binary: gput :: GBinary f => f t -> Put
+ Data.Binary: gput :: GBinaryPut f => f t -> Put

Files

benchmarks/Builder.hs view
@@ -6,15 +6,17 @@  module Main (main) where +#if ! MIN_VERSION_base(4,8,0)+import Data.Monoid (Monoid(mappend, mempty))+#endif+ import Control.DeepSeq import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO) import Criterion.Main import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Lazy as L import Data.Char (ord)-import Data.Monoid (Monoid(mappend, mempty)) import Data.Word (Word8)  import Data.Binary.Builder@@ -84,7 +86,7 @@  -- Write 100 short, length-prefixed ByteStrings. lengthPrefixedBS :: S.ByteString -> Builder-lengthPrefixedBS bs = loop 100+lengthPrefixedBS bs = loop (100 :: Int)   where loop n | n `seq` False = undefined         loop 0 = mempty         loop n =
+ benchmarks/GenericsBench.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE DeriveGeneric, StandaloneDeriving, BangPatterns #-}+module Main where++import qualified Data.ByteString.Lazy            as L+import           Distribution.PackageDescription++import           Criterion.Main++import qualified Data.Binary                     as Binary+import           Data.Binary.Get                 (Get)+import qualified Data.Binary.Get                 as Binary++import           GenericsBenchCache++main :: IO ()+main = benchmark =<< readPackageDescriptionCache 100++benchmark :: [PackageDescription] -> IO ()+benchmark pds = do+  let lbs = encode pds+      !_ = L.length lbs+      str = show pds+      !_ = length str+  defaultMain [+      bench "encode" (nf encode pds)+    , bench "decode" (nf decode lbs)+    , bench "decode null" (nf decodeNull lbs)+    , bgroup "embarrassment" [+          bench "read" (nf readPackageDescription str)+        , bench "show" (nf show pds)+      ]+    ]++encode :: [PackageDescription] -> L.ByteString+encode = Binary.encode++decode :: L.ByteString -> Int+decode = length . (Binary.decode :: L.ByteString -> [PackageDescription])++decodeNull :: L.ByteString -> ()+decodeNull =+  Binary.runGet $ do+    n <- Binary.get :: Get Int+    go n+  where+    go 0 = return ()+    go i = do+      x <- Binary.get :: Get PackageDescription+      x `seq` go (i-1)++readPackageDescription :: String -> Int+readPackageDescription = length . (read :: String -> [PackageDescription])
+ benchmarks/GenericsBenchCache.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE DeriveGeneric, StandaloneDeriving, BangPatterns, CPP #-}+module GenericsBenchCache (readPackageDescriptionCache) where++import qualified Text.ParserCombinators.ReadP                  as Read++import qualified Data.ByteString.Lazy                          as L+import qualified Data.ByteString.Lazy.Char8                    as LC8++import           Data.Version                                  (parseVersion)+import           Distribution.PackageDescription+import           Distribution.PackageDescription.Configuration+import           Distribution.PackageDescription.Parse+import           Distribution.Version                          (Version)++import qualified Codec.Archive.Tar                             as Tar+import qualified Codec.Compression.GZip                        as GZip+import qualified Data.HashMap.Lazy                             as Map+import           System.Directory+import           System.Exit++import           GenericsBenchTypes                            ()++#if ! MIN_VERSION_base(4,8,0)+import           Control.Applicative                           ((<$>))+#endif++readTar :: String -> Int -> IO [PackageDescription]+readTar tarPath limit = do+  entries <- Tar.read . GZip.decompress <$> L.readFile tarPath+  let contents = Tar.foldEntries unpack [] (error "tar error") entries+  let !pkgs = Map.fromListWith pick+                      [ (pkg, (version, content))+                      | (path, content) <- contents+                      , Just (pkg, version) <- return (readFilePath path) ]++  return $ take limit [ flattenPackageDescription gpd+                      | (_, (_, content)) <- Map.toList pkgs+                      , ParseOk _warns gpd <- return (parsePackageDescription (LC8.unpack content)) ]+    where+      pick (v,a) (w,b) | v >= w = (v,a)+                       | otherwise = (w,b)+      unpack e acc =+        case Tar.entryContent e of+          Tar.NormalFile content _ -> (Tar.entryPath e, content):acc+          _ -> acc++readFilePath :: String -> Maybe (String, Version)+readFilePath str = extract (Read.readP_to_S parse str)+  where+    extract [(result,_)] = Just result+    extract _ = Nothing+    parse = do+      packageName <- Read.many1 (Read.satisfy (/='/'))+      _ <- Read.char '/'+      version <- parseVersion+      _ <- Read.char '/'+      return (packageName, version)++writePackageDescriptionCache :: String -> [PackageDescription] -> IO ()+writePackageDescriptionCache path = writeFile path . show++readPackageDescriptionCache :: Int -> IO [PackageDescription]+readPackageDescriptionCache amount = do+  let cacheFilePath' = cacheFilePath ++ "-" ++ (show amount)+  createPackageDescriptionCache cacheFilePath' amount+  pds <- read <$> readFile cacheFilePath'+  -- PackageDescription doesn't implement NFData, let's force with the following line+  (length (show pds)) `seq` return pds++cacheFilePath :: String+cacheFilePath = "generics-bench.cache"++createPackageDescriptionCache :: String -> Int -> IO ()+createPackageDescriptionCache path amount = do+  cacheExists <- doesFileExist path+  if cacheExists+    then putStrLn "reusing cache from previous run"+    else do+      putStr "creating cabal cache file... "+      tarFilePath <- (++"/.cabal/packages/hackage.haskell.org/00-index.tar.gz") <$> getHomeDirectory+      fileExists <- doesFileExist tarFilePath+      if fileExists+        then do+          pds <- readTar tarFilePath amount+          writePackageDescriptionCache path pds+          putStrLn "done"+        else do+          putStrLn (tarFilePath ++ " missing, aborting")+          exitFailure
+ benchmarks/GenericsBenchTypes.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE DeriveGeneric, StandaloneDeriving #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module GenericsBenchTypes where++import           Distribution.Compiler+import           Distribution.License+import           Distribution.ModuleName         hiding (main)+import           Distribution.Package+import           Distribution.PackageDescription+import           Distribution.Version+import           Language.Haskell.Extension++import           GHC.Generics                    (Generic)++import           Data.Binary+++deriving instance Generic Version++instance Binary Benchmark+instance Binary BenchmarkInterface+instance Binary BenchmarkType+instance Binary BuildInfo+instance Binary BuildType+instance Binary CompilerFlavor+instance Binary Dependency+instance Binary Executable+instance Binary Extension+instance Binary FlagName+instance Binary KnownExtension+instance Binary Language+instance Binary Library+instance Binary License+instance Binary ModuleName+instance Binary ModuleReexport+instance Binary ModuleRenaming+instance Binary PackageDescription+instance Binary PackageIdentifier+instance Binary PackageName+instance Binary RepoKind+instance Binary RepoType+instance Binary SourceRepo+instance Binary TestSuite+instance Binary TestSuiteInterface+instance Binary TestType+instance Binary VersionRange
benchmarks/Get.hs view
@@ -8,21 +8,19 @@  import Control.DeepSeq import Control.Exception (evaluate)-import Control.Monad.Trans (liftIO) import Criterion.Main import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as C8 import qualified Data.ByteString.Lazy as L+import Data.Bits import Data.Char (ord)-import Data.Monoid (Monoid(mappend, mempty))-import Data.Word (Word8, Word16, Word32)+import Data.List (foldl')  import Control.Applicative+import Data.Binary import Data.Binary.Get-import Data.Binary ( get )  import qualified Data.Serialize.Get as Cereal-import qualified Data.Serialize as Cereal  import qualified Data.Attoparsec.ByteString as A import qualified Data.Attoparsec.ByteString.Lazy as AL@@ -40,62 +38,88 @@     rnf bracketsInChunks,     rnf bracketCount,     rnf oneMegabyte,-    rnf oneMegabyteLBS+    rnf oneMegabyteLBS,+    rnf manyBytes,+    rnf encodedBigInteger      ]   defaultMain-    [-      bench "brackets 100kb one chunk input" $-        whnf (checkBracket . runTest bracketParser) brackets-    , bench "brackets 100kb in 100 byte chunks" $-        whnf (checkBracket . runTest bracketParser) bracketsInChunks-    , bench "Attoparsec lazy-bs brackets 100kb one chunk" $-        whnf (checkBracket . runAttoL bracketParser_atto) brackets-    , bench "Attoparsec lazy-bs brackets 100kb in 100 byte chunks" $-        whnf (checkBracket . runAttoL bracketParser_atto) bracketsInChunks-    , bench "Attoparsec strict-bs brackets 100kb" $-        whnf (checkBracket . runAtto bracketParser_atto) $ S.concat (L.toChunks brackets)-    , bench "Cereal strict-bs brackets 100kb" $-        whnf (checkBracket . runCereal bracketParser_cereal) $ S.concat (L.toChunks brackets)-    , bench "Binary getStruct4 1MB struct of 4 word8" $-        whnf (runTest (getStruct4 mega)) oneMegabyteLBS-    , bench "Cereal getStruct4 1MB struct of 4 word8" $-        whnf (runCereal (getStruct4_cereal mega)) oneMegabyte-    , bench "Attoparsec getStruct4 1MB struct of 4 word8" $-        whnf (runAtto (getStruct4_atto mega)) oneMegabyte-    , bench "Binary getWord8 1MB chunk size 1 byte" $-        whnf (runTest (getWord8N1 mega)) oneMegabyteLBS-    , bench "Cereal getWord8 1MB chunk size 1 byte" $-        whnf (runCereal (getWord8N1_cereal mega)) oneMegabyte-    , bench "Attoparsec getWord8 1MB chunk size 1 byte" $-        whnf (runAtto (getWord8N1_atto mega)) oneMegabyte-    , bench "getWord8 1MB chunk size 2 bytes" $-        whnf (runTest (getWord8N2 mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 4 bytes" $-        whnf (runTest (getWord8N4 mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 8 bytes" $-        whnf (runTest (getWord8N8 mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 16 bytes" $-        whnf (runTest (getWord8N16 mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 2 bytes Applicative" $-        whnf (runTest (getWord8N2A mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 4 bytes Applicative" $-        whnf (runTest (getWord8N4A mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 8 bytes Applicative" $-        whnf (runTest (getWord8N8A mega)) oneMegabyteLBS-    , bench "getWord8 1MB chunk size 16 bytes Applicative" $-        whnf (runTest (getWord8N16A mega)) oneMegabyteLBS+    [ bgroup "brackets"+        [ bench "Binary 100kb, one chunk" $+            whnf (checkBracket . runTest bracketParser) brackets+        , bench "Binary 100kb, 100 byte chunks" $+            whnf (checkBracket . runTest bracketParser) bracketsInChunks+        , bench "Attoparsec lazy-bs 100kb, one chunk" $+            whnf (checkBracket . runAttoL bracketParser_atto) brackets+        , bench "Attoparsec lazy-bs 100kb, 100 byte chunks" $+            whnf (checkBracket . runAttoL bracketParser_atto) bracketsInChunks+        , bench "Attoparsec strict-bs 100kb" $+            whnf (checkBracket . runAtto bracketParser_atto) $ S.concat (L.toChunks brackets)+        , bench "Cereal strict-bs 100kb" $+            whnf (checkBracket . runCereal bracketParser_cereal) $ S.concat (L.toChunks brackets)+        ]+    , bgroup "comparison getStruct4, 1MB of struct of 4 Word8s"+      [ bench "Attoparsec" $+          whnf (runAtto (getStruct4_atto mega)) oneMegabyte+      , bench "Binary" $+          whnf (runTest (getStruct4 mega)) oneMegabyteLBS+      , bench "Cereal" $+          whnf (runCereal (getStruct4_cereal mega)) oneMegabyte+      ]+    , bgroup "comparison getWord8, 1MB"+        [ bench "Attoparsec" $+            whnf (runAtto (getWord8N1_atto mega)) oneMegabyte+        , bench "Binary" $+            whnf (runTest (getWord8N1 mega)) oneMegabyteLBS+        , bench "Cereal" $+            whnf (runCereal (getWord8N1_cereal mega)) oneMegabyte+        ]+    , bgroup "getWord8 1MB"+        [ bench "chunk size 2 bytes" $+            whnf (runTest (getWord8N2 mega)) oneMegabyteLBS+        , bench "chunk size 4 bytes" $+            whnf (runTest (getWord8N4 mega)) oneMegabyteLBS+        , bench "chunk size 8 bytes" $+            whnf (runTest (getWord8N8 mega)) oneMegabyteLBS+        , bench "chunk size 16 bytes" $+            whnf (runTest (getWord8N16 mega)) oneMegabyteLBS+        ]+    , bgroup "getWord8 1MB Applicative"+        [ bench "chunk size 2 bytes" $+            whnf (runTest (getWord8N2A mega)) oneMegabyteLBS+        , bench "chunk size 4 bytes" $+            whnf (runTest (getWord8N4A mega)) oneMegabyteLBS+        , bench "chunk size 8 bytes" $+            whnf (runTest (getWord8N8A mega)) oneMegabyteLBS+        , bench "chunk size 16 bytes" $+            whnf (runTest (getWord8N16A mega)) oneMegabyteLBS+        ]+    , bgroup "roll"+        [ bench "foldr"  $ nf (roll_foldr  :: [Word8] -> Integer) manyBytes+        , bench "foldl'" $ nf (roll_foldl' :: [Word8] -> Integer) manyBytes+        ]+    , bgroup "Integer"+        [ bench "decode" $ nf (decode :: L.ByteString -> Integer) encodedBigInteger+        ]     ] +checkBracket :: Int -> Int checkBracket x | x == bracketCount = x                | otherwise = error "argh!" +runTest :: Get a -> L.ByteString -> a runTest decoder inp = runGet decoder inp++runCereal :: Cereal.Get a -> C8.ByteString -> a runCereal decoder inp = case Cereal.runGet decoder inp of                           Right a -> a                           Left err -> error err++runAtto :: AL.Parser a -> C8.ByteString -> a runAtto decoder inp = case A.parseOnly decoder inp of                         Right a -> a                         Left err -> error err++runAttoL :: Show a => AL.Parser a -> L.ByteString -> a runAttoL decoder inp = case AL.parse decoder inp of                         AL.Done _ r -> r                         a -> error (show a)@@ -108,15 +132,20 @@ oneMegabyteLBS :: L.ByteString oneMegabyteLBS = L.fromChunks [oneMegabyte] +mega :: Int mega = 1024 * 1024  -- 100k of brackets+bracketTest :: L.ByteString -> Int bracketTest inp = runTest bracketParser inp  bracketCount :: Int bracketCount = fromIntegral $ L.length brackets `div` 2 +brackets :: L.ByteString brackets = L.fromChunks [C8.concat (L.toChunks bracketsInChunks)]++bracketsInChunks :: L.ByteString bracketsInChunks = L.fromChunks (replicate chunksOfBrackets oneChunk)   where     oneChunk = "((()((()()))((()(()()()()()()()(((()()()()(()()(()(()())))))()((())())))()())(((())())(()))))()(()))"@@ -143,19 +172,23 @@ bracketParser_atto :: A.Parser Int bracketParser_atto = cont <|> return 0   where-  cont = do v <- some ( do A.word8 40+  cont = do v <- some ( do _ <- A.word8 40                            n <- bracketParser_atto-                           A.word8 41+                           _ <- A.word8 41                            return $! n + 1)             return $! sum v  -- Strict struct of 4 Word8s-data Struct4 = Struct4 {-# UNPACK #-} !Word8-                       {-# UNPACK #-} !Word8-                       {-# UNPACK #-} !Word8-                       {-# UNPACK #-} !Word8-               deriving Show+data S2 = S2 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+data S4 = S4 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+data S8 = S8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+             {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+data S16 = S16 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+               {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+               {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8+               {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 +getStruct4 :: Int -> Get [S4] getStruct4 = loop []   where loop acc 0 = return acc         loop acc n = do@@ -163,9 +196,10 @@           !w1 <- getWord8           !w2 <- getWord8           !w3 <- getWord8-          let !s = Struct4 w0 w1 w2 w3+          let !s = S4 w0 w1 w2 w3           loop (s : acc) (n - 4) +getStruct4_cereal :: Int -> Cereal.Get [S4] getStruct4_cereal = loop []   where loop acc 0 = return acc         loop acc n = do@@ -173,9 +207,10 @@           !w1 <- Cereal.getWord8           !w2 <- Cereal.getWord8           !w3 <- Cereal.getWord8-          let !s = Struct4 w0 w1 w2 w3+          let !s = S4 w0 w1 w2 w3           loop (s : acc) (n - 4) +getStruct4_atto :: Int -> A.Parser [S4] getStruct4_atto = loop []   where loop acc 0 = return acc         loop acc n = do@@ -183,48 +218,53 @@           !w1 <- A.anyWord8           !w2 <- A.anyWord8           !w3 <- A.anyWord8-          let !s = Struct4 w0 w1 w2 w3+          let !s = S4 w0 w1 w2 w3           loop (s : acc) (n - 4) --- No-allocation loops.--getWord8N1 = loop 0+getWord8N1 :: Int -> Get [Word8]+getWord8N1 = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do           s0 <- getWord8-          loop (s0+s) (n-1)+          loop (s0:s) (n-1) -getWord8N1_cereal = loop 0+getWord8N1_cereal :: Int -> Cereal.Get [Word8]+getWord8N1_cereal = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do           s0 <- Cereal.getWord8-          loop (s0+s) (n-1)+          loop (s0:s) (n-1) -getWord8N1_atto = loop 0+getWord8N1_atto :: Int -> A.Parser [Word8]+getWord8N1_atto = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do           s0 <- A.anyWord8-          loop (s0+s) (n-1)+          loop (s0:s) (n-1) -getWord8N2 = loop 0+getWord8N2 :: Int -> Get [S2]+getWord8N2 = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do           s0 <- getWord8           s1 <- getWord8-          loop (s0+s1+s) (n-2)+          let !v = S2 s0 s1+          loop (v:s) (n-2) -getWord8N2A = loop 0+getWord8N2A :: Int -> Get [S2]+getWord8N2A = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do-          v <- (+) <$> getWord8 <*> getWord8-          loop (s+v) (n-2)+          !v <- S2 <$> getWord8 <*> getWord8+          loop (v:s) (n-2) -getWord8N4 = loop 0+getWord8N4 :: Int -> Get [S4]+getWord8N4 = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do@@ -232,17 +272,19 @@           s1 <- getWord8           s2 <- getWord8           s3 <- getWord8-          loop (s+s0+s1+s2+s3) (n-4)+          let !v = S4 s0 s1 s2 s3+          loop (v:s) (n-4) -getWord8N4A = loop 0+getWord8N4A :: Int -> Get [S4]+getWord8N4A = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do-          let p !s0 !s1 !s2 !s3 = s0 + s1 + s2 + s3-          v <- p <$> getWord8 <*> getWord8 <*> getWord8 <*> getWord8-          loop (s+v) (n-4)+          !v <- S4 <$> getWord8 <*> getWord8 <*> getWord8 <*> getWord8+          loop (v:s) (n-4) -getWord8N8 = loop 0+getWord8N8 :: Int -> Get [S8]+getWord8N8 = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do@@ -254,15 +296,15 @@           s5 <- getWord8           s6 <- getWord8           s7 <- getWord8-          loop (s+s0+s1+s2+s3+s4+s5+s6+s7) (n-8)+          let !v = S8 s0 s1 s2 s3 s4 s5 s6 s7+          loop (v:s) (n-8) -getWord8N8A = loop 0+getWord8N8A :: Int -> Get [S8]+getWord8N8A = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do-          let p !s0 !s1 !s2 !s3 !s4 !s5 !s6 !s7 =-                s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7-          v <- p <$> getWord8+          !v <- S8 <$> getWord8                    <*> getWord8                    <*> getWord8                    <*> getWord8@@ -270,9 +312,10 @@                    <*> getWord8                    <*> getWord8                    <*> getWord8-          loop (s+v) (n-8)+          loop (v:s) (n-8) -getWord8N16 = loop 0+getWord8N16 :: Int -> Get [S16]+getWord8N16 = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do@@ -292,28 +335,47 @@           s13 <- getWord8           s14 <- getWord8           s15 <- getWord8-          loop (s+s0+s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11+s12+s13+s14+s15) (n-16)+          let !v = S16 s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15+          loop (v:s) (n-16) -getWord8N16A = loop 0+getWord8N16A :: Int -> Get [S16]+getWord8N16A = loop []   where loop s n | s `seq` n `seq` False = undefined         loop s 0 = return s         loop s n = do-          let p !s0 !s1 !s2 !s3 !s4 !s5 !s6 !s7 !s8 !s9 !s10 !s11 !s12 !s13 !s14 !s15 =-                s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15-          !v <- p <$> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-                   <*> getWord8-          loop (s+v) (n-16)+          !v <- S16 <$> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+                    <*> getWord8+          loop (v:s) (n-16)++manyBytes :: [Word8]+manyBytes = concat $ replicate 256 [0..255]++bigInteger :: Integer+bigInteger = roll_foldl' manyBytes++encodedBigInteger :: L.ByteString+encodedBigInteger = encode bigInteger++roll_foldr :: (Integral a, Num a, Bits a) => [Word8] -> a+roll_foldr   = foldr unstep 0+  where+    unstep b a = a `shiftL` 8 .|. fromIntegral b++roll_foldl' :: (Integral a, Num a, Bits a) => [Word8] -> a+roll_foldl'   = foldl' unstep 0 . reverse+  where+    unstep a b = a `shiftL` 8 .|. fromIntegral b
binary.cabal view
@@ -1,5 +1,5 @@ name:            binary-version:         0.7.6.1+version:         0.8.0.0 license:         BSD3 license-file:    LICENSE author:          Lennart Kolmodin <kolmodin@gmail.com>@@ -18,7 +18,7 @@ stability:       provisional build-type:      Simple cabal-version:   >= 1.8-tested-with:     GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1+tested-with:     GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2 extra-source-files:   README.md changelog.md docs/hcar/binary-Lb.tex tools/derive/*.hs @@ -120,7 +120,34 @@     mtl   -- build dependencies from using binary source rather than depending on the library   build-depends: array, containers-  ghc-options: -O2+  ghc-options: -O2 -Wall++benchmark generics-bench+  type: exitcode-stdio-1.0+  hs-source-dirs: src benchmarks+  main-is: GenericsBench.hs+  build-depends:+    base >= 3.0 && < 5,+    bytestring,+    Cabal == 1.22.*,+    directory,+    filepath,+    tar,+    unordered-containers,+    zlib,+    criterion+  other-modules:+    GenericsBenchCache+    GenericsBenchTypes+  -- build dependencies from using binary source rather than depending on the library+  build-depends: array, containers+  ghc-options: -O2 -Wall+  if impl(ghc >= 7.2.1)+    cpp-options: -DGENERICS+    other-modules: Data.Binary.Generic+    if impl(ghc <= 7.6)+      -- prior to ghc-7.4 generics lived in ghc-prim+      build-depends: ghc-prim  benchmark builder   type: exitcode-stdio-1.0
changelog.md view
@@ -1,6 +1,14 @@ binary ====== +binary-0.8.0.0+--------------++- Added binary instance for `Version` from `Data.Version`.+- Added binary instance for `Void` from GHC 7.10.1.+- Added binary instance for `(Data.Fixed a)` from GHC 7.8.1.+- Added semigroup instance for `Data.Binary.Builder` from GHC 8.0.+ binary-0.7.6.1 -------------- 
src/Data/Binary.hs view
@@ -30,8 +30,9 @@ -- If the specifics of the data format is not important to you, for example, -- you are more interested in serializing and deserializing values than -- in which format will be used, it is possible to derive 'Binary'--- instances using the generic support. See 'GBinary'.--- +-- instances using the generic support. See 'GBinaryGet' and+-- 'GBinaryPut'.+-- -- If you have specific requirements about the encoding format, you can use -- the encoding and decoding primitives directly, see the modules -- "Data.Binary.Get" and "Data.Binary.Put".@@ -48,7 +49,8 @@ #ifdef GENERICS     -- * Generic support     -- $generics-    , GBinary(..)+    , GBinaryGet(..)+    , GBinaryPut(..) #endif      -- * The Get and Put monads@@ -180,6 +182,8 @@ -- 'Right' on success. In both cases the unconsumed input and the number of -- consumed bytes is returned. In case of failure, a human-readable error -- message will be returned as well.+--+-- /Since: 0.7.0.0/ decodeOrFail :: Binary a => L.ByteString              -> Either (L.ByteString, ByteOffset, String)                        (L.ByteString, ByteOffset, a)@@ -204,6 +208,8 @@  -- | Decode a value from a file. In case of errors, 'error' will -- be called with the error message.+--+-- /Since: 0.7.0.0/ decodeFile :: Binary a => FilePath -> IO a decodeFile f = do   result <- decodeFileOrFail f
src/Data/Binary/Builder/Base.hs view
@@ -64,7 +64,11 @@  import qualified Data.ByteString      as S import qualified Data.ByteString.Lazy as L+#if MIN_VERSION_base(4,9,0)+import Data.Semigroup+#else import Data.Monoid+#endif import Data.Word import Foreign @@ -107,10 +111,20 @@                    -> IO L.ByteString     } +#if MIN_VERSION_base(4,9,0)+instance Semigroup Builder where+    (<>) = append+    {-# INLINE (<>) #-}+#endif+ instance Monoid Builder where     mempty  = empty     {-# INLINE mempty #-}+#if MIN_VERSION_base(4,9,0)+    mappend = (<>)+#else     mappend = append+#endif     {-# INLINE mappend #-}     mconcat = foldr mappend mempty     {-# INLINE mconcat #-}@@ -191,6 +205,7 @@       else let !b  = Buffer p (o+u) 0 l                !bs = S.PS p o u            in return $! L.Chunk bs (inlinePerformIO (k b))+{-# INLINE [0] flush #-}  ------------------------------------------------------------------------ 
src/Data/Binary/Class.hs view
@@ -8,12 +8,21 @@  #if MIN_VERSION_base(4,8,0) #define HAS_NATURAL+#define HAS_VOID #endif +#if MIN_VERSION_base(4,7,0)+#define HAS_FIXED_CONSTRUCTOR+#endif+ #if __GLASGOW_HASKELL__ >= 704 #define HAS_GHC_FINGERPRINT #endif +#ifndef HAS_FIXED_CONSTRUCTOR+{-# LANGUAGE ScopedTypeVariables #-}+#endif+ ----------------------------------------------------------------------------- -- | -- Module      : Data.Binary.Class@@ -35,7 +44,8 @@  #ifdef GENERICS     -- * Support for generics-    , GBinary(..)+    , GBinaryGet(..)+    , GBinaryPut(..) #endif      ) where@@ -43,17 +53,23 @@ import Data.Word import Data.Bits import Data.Int+#ifdef HAS_VOID+import Data.Void+#endif  import Data.Binary.Put import Data.Binary.Get +#if ! MIN_VERSION_base(4,8,0)+import Control.Applicative+#endif import Control.Monad  import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as L  import Data.Char    (ord)-import Data.List    (unfoldr)+import Data.List    (unfoldr, foldl')  -- And needed for the instances: import qualified Data.ByteString as B@@ -74,6 +90,9 @@ #ifdef HAS_NATURAL import Numeric.Natural #endif++import qualified Data.Fixed as Fixed+ -- -- This isn't available in older Hugs or older GHC --@@ -86,11 +105,19 @@ import GHC.Fingerprint #endif +import Data.Version (Version(..))+ ------------------------------------------------------------------------  #ifdef GENERICS-class GBinary f where+-- Factored into two classes because this makes GHC optimize the+-- instances faster.  This doesn't matter for builds of binary,+-- but it matters a lot for end-users who write 'instance Binary T'.+-- See also: https://ghc.haskell.org/trac/ghc/ticket/9630+class GBinaryPut f where     gput :: f t -> Put++class GBinaryGet f where     gget :: Get (f t) #endif @@ -118,16 +145,26 @@     get :: Get t  #ifdef GENERICS-    default put :: (Generic t, GBinary (Rep t)) => t -> Put+    default put :: (Generic t, GBinaryPut (Rep t)) => t -> Put     put = gput . from -    default get :: (Generic t, GBinary (Rep t)) => Get t+    default get :: (Generic t, GBinaryGet (Rep t)) => Get t     get = to `fmap` gget #endif  ------------------------------------------------------------------------ -- Simple instances +#ifdef HAS_VOID+-- Void never gets written nor reconstructed since it's impossible to have a+-- value of that type++-- | /Since: 0.8.0.0/+instance Binary Void where+    put     = absurd+    get     = mzero+#endif+ -- The () type need never be written to disk: values of singleton type -- can be reconstructed from the type alone instance Binary () where@@ -239,24 +276,37 @@                     let v = roll bytes                     return $! if sign == (1 :: Word8) then v else - v +-- | /Since: 0.8.0.0/+#ifdef HAS_FIXED_CONSTRUCTOR+instance Binary (Fixed.Fixed a) where+  put (Fixed.MkFixed a) = put a+  get = Fixed.MkFixed `liftM` get+#else+instance forall a. Fixed.HasResolution a => Binary (Fixed.Fixed a) where+  -- Using undefined :: Maybe a as a proxy, as Data.Proxy is introduced only in base-4.7+  put x = put (truncate (x * fromInteger (Fixed.resolution (undefined :: Maybe a))) :: Integer)+  get = (\x -> fromInteger x / fromInteger (Fixed.resolution (undefined :: Maybe a))) `liftM` get+#endif+ -- -- Fold and unfold an Integer to and from a list of its bytes ---unroll :: (Integral a, Num a, Bits a) => a -> [Word8]+unroll :: (Integral a, Bits a) => a -> [Word8] unroll = unfoldr step   where     step 0 = Nothing     step i = Just (fromIntegral i, i `shiftR` 8) -roll :: (Integral a, Num a, Bits a) => [Word8] -> a-roll   = foldr unstep 0+roll :: (Integral a, Bits a) => [Word8] -> a+roll   = foldl' unstep 0 . reverse   where-    unstep b a = a `shiftL` 8 .|. fromIntegral b+    unstep a b = a `shiftL` 8 .|. fromIntegral b  #ifdef HAS_NATURAL -- Fixed-size type for a subset of Natural type NaturalWord = Word64 +-- | /Since: 0.7.3.0/ instance Binary Natural where     {-# INLINE put #-}     put n | n <= hi = do@@ -597,6 +647,7 @@ -- Fingerprints  #ifdef HAS_GHC_FINGERPRINT+-- | /Since: 0.7.6.0/ instance Binary Fingerprint where     put (Fingerprint x1 x2) = do         put x1@@ -606,3 +657,11 @@         x2 <- get         return $! Fingerprint x1 x2 #endif++------------------------------------------------------------------------+-- Version++-- | /Since: 0.8.0.0/+instance Binary Version where+    get = Version <$> get <*> get+    put (Version br tags) = put br >> put tags
src/Data/Binary/Generic.hs view
@@ -32,28 +32,38 @@ import Prelude -- Silence AMP warning.  -- Type without constructors-instance GBinary V1 where+instance GBinaryPut V1 where     gput _ = return ()++instance GBinaryGet V1 where     gget   = return undefined  -- Constructor without arguments-instance GBinary U1 where+instance GBinaryPut U1 where     gput U1 = return ()++instance GBinaryGet U1 where     gget    = return U1  -- Product: constructor with parameters-instance (GBinary a, GBinary b) => GBinary (a :*: b) where+instance (GBinaryPut a, GBinaryPut b) => GBinaryPut (a :*: b) where     gput (x :*: y) = gput x >> gput y++instance (GBinaryGet a, GBinaryGet b) => GBinaryGet (a :*: b) where     gget = (:*:) <$> gget <*> gget  -- Metadata (constructor name, etc)-instance GBinary a => GBinary (M1 i c a) where+instance GBinaryPut a => GBinaryPut (M1 i c a) where     gput = gput . unM1++instance GBinaryGet a => GBinaryGet (M1 i c a) where     gget = M1 <$> gget  -- Constants, additional parameters, and rank-1 recursion-instance Binary a => GBinary (K1 i a) where+instance Binary a => GBinaryPut (K1 i a) where     gput = put . unK1++instance Binary a => GBinaryGet (K1 i a) where     gget = K1 <$> get  -- Borrowed from the cereal package.@@ -69,14 +79,15 @@ #define PUTSUM(WORD) GUARD(WORD) = putSum (0 :: WORD) (fromIntegral size) #define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size) -instance ( GSum     a, GSum     b-         , GBinary a, GBinary b-         , SumSize    a, SumSize    b) => GBinary (a :+: b) where+instance ( GSumPut  a, GSumPut  b+         , SumSize    a, SumSize    b) => GBinaryPut (a :+: b) where     gput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64)          | otherwise = sizeError "encode" size       where         size = unTagged (sumSize :: Tagged (a :+: b) Word64) +instance ( GSumGet  a, GSumGet  b+         , SumSize    a, SumSize    b) => GBinaryGet (a :+: b) where     gget | GETSUM(Word8) | GETSUM(Word16) | GETSUM(Word32) | GETSUM(Word64)          | otherwise = sizeError "decode" size       where@@ -88,23 +99,26 @@  ------------------------------------------------------------------------ -checkGetSum :: (Ord word, Num word, Bits word, GSum f)+checkGetSum :: (Ord word, Num word, Bits word, GSumGet f)             => word -> word -> Get (f a) checkGetSum size code | code < size = getSum code size                       | otherwise   = fail "Unknown encoding for constructor" {-# INLINE checkGetSum #-} -class GSum f where+class GSumGet f where     getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a)++class GSumPut f where     putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put -instance (GSum a, GSum b, GBinary a, GBinary b) => GSum (a :+: b) where+instance (GSumGet a, GSumGet b) => GSumGet (a :+: b) where     getSum !code !size | code < sizeL = L1 <$> getSum code           sizeL                        | otherwise    = R1 <$> getSum (code - sizeL) sizeR         where           sizeL = size `shiftR` 1           sizeR = size - sizeL +instance (GSumPut a, GSumPut b) => GSumPut (a :+: b) where     putSum !code !size s = case s of                              L1 x -> putSum code           sizeL x                              R1 x -> putSum (code + sizeL) sizeR x@@ -112,9 +126,10 @@           sizeL = size `shiftR` 1           sizeR = size - sizeL -instance GBinary a => GSum (C1 c a) where+instance GBinaryGet a => GSumGet (C1 c a) where     getSum _ _ = gget +instance GBinaryPut a => GSumPut (C1 c a) where     putSum !code _ x = put code *> gput x  ------------------------------------------------------------------------
src/Data/Binary/Get.hs view
@@ -63,9 +63,6 @@ --getTrade' = Trade '<$>' 'getWord32le' '<*>' 'getWord32le' '<*>' 'getWord16le' -- @ ----- The applicative style can sometimes result in faster code, as @binary@--- will try to optimize the code by grouping the reads together.--- -- There are two kinds of ways to execute this decoder, the lazy input -- method and the incremental input method. Here we will use the lazy -- input method.@@ -299,6 +296,8 @@ -- success. In both cases any unconsumed input and the number of bytes -- consumed is returned. In the case of failure, a human-readable -- error message is included as well.+--+-- /Since: 0.6.4.0/ runGetOrFail :: Get a -> L.ByteString              -> Either (L.ByteString, ByteOffset, String) (L.ByteString, ByteOffset, a) runGetOrFail g lbs0 = feedAll (runGetIncremental g) lbs0@@ -409,7 +408,7 @@ -- | Read a Word8 from the monad state getWord8 :: Get Word8 getWord8 = readN 1 B.unsafeHead-{-# INLINE getWord8 #-}+{-# INLINE[2] getWord8 #-}  -- force GHC to inline getWordXX {-# RULES@@ -429,7 +428,7 @@ word16be = \s ->         (fromIntegral (s `B.unsafeIndex` 0) `shiftl_w16` 8) .|.         (fromIntegral (s `B.unsafeIndex` 1))-{-# INLINE getWord16be #-}+{-# INLINE[2] getWord16be #-} {-# INLINE word16be #-}  -- | Read a Word16 in little endian format@@ -440,7 +439,7 @@ word16le = \s ->               (fromIntegral (s `B.unsafeIndex` 1) `shiftl_w16` 8) .|.               (fromIntegral (s `B.unsafeIndex` 0) )-{-# INLINE getWord16le #-}+{-# INLINE[2] getWord16le #-} {-# INLINE word16le #-}  -- | Read a Word32 in big endian format@@ -453,7 +452,7 @@               (fromIntegral (s `B.unsafeIndex` 1) `shiftl_w32` 16) .|.               (fromIntegral (s `B.unsafeIndex` 2) `shiftl_w32`  8) .|.               (fromIntegral (s `B.unsafeIndex` 3) )-{-# INLINE getWord32be #-}+{-# INLINE[2] getWord32be #-} {-# INLINE word32be #-}  -- | Read a Word32 in little endian format@@ -466,7 +465,7 @@               (fromIntegral (s `B.unsafeIndex` 2) `shiftl_w32` 16) .|.               (fromIntegral (s `B.unsafeIndex` 1) `shiftl_w32`  8) .|.               (fromIntegral (s `B.unsafeIndex` 0) )-{-# INLINE getWord32le #-}+{-# INLINE[2] getWord32le #-} {-# INLINE word32le #-}  -- | Read a Word64 in big endian format@@ -483,7 +482,7 @@               (fromIntegral (s `B.unsafeIndex` 5) `shiftl_w64` 16) .|.               (fromIntegral (s `B.unsafeIndex` 6) `shiftl_w64`  8) .|.               (fromIntegral (s `B.unsafeIndex` 7) )-{-# INLINE getWord64be #-}+{-# INLINE[2] getWord64be #-} {-# INLINE word64be #-}  -- | Read a Word64 in little endian format@@ -500,7 +499,7 @@               (fromIntegral (s `B.unsafeIndex` 2) `shiftl_w64` 16) .|.               (fromIntegral (s `B.unsafeIndex` 1) `shiftl_w64`  8) .|.               (fromIntegral (s `B.unsafeIndex` 0) )-{-# INLINE getWord64le #-}+{-# INLINE[2] getWord64le #-} {-# INLINE word64le #-}  ------------------------------------------------------------------------
src/Data/Binary/Get/Internal.hs view
@@ -23,7 +23,7 @@     , withInputChunks     , Consume     , failOnEOF-    +     , get     , put     , ensureN@@ -91,14 +91,10 @@ type Success a r = B.ByteString -> a -> Decoder r  instance Monad Get where-  return = returnG+  return = pure   (>>=) = bindG   fail = failG -returnG :: a -> Get a-returnG a = C $ \s ks -> ks s a-{-# INLINE [0] returnG #-}- bindG :: Get a -> (a -> Get b) -> Get b bindG (C c) f = C $ \i ks -> c i (\i' a -> (runCont (f a)) i' ks) {-# INLINE bindG #-}@@ -118,11 +114,12 @@ {-# INLINE fmapG #-}  instance Applicative Get where-  pure = returnG-  {-# INLINE pure #-}+  pure = \x -> C $ \s ks -> ks s x+  {-# INLINE [0] pure #-}   (<*>) = apG   {-# INLINE (<*>) #-} +-- | /Since: 0.7.1.0/ instance MonadPlus Get where   mzero = empty   mplus = (<|>)@@ -192,6 +189,8 @@ -- If the given decoder fails, 'isolate' will also fail. -- Offset from 'bytesRead' will be relative to the start of 'isolate', not the -- absolute of the input.+--+-- /Since: 0.7.2.0/ isolate :: Int   -- ^ The number of bytes that must be consumed         -> Get a -- ^ The decoder to isolate         -> Get a@@ -254,6 +253,7 @@ getBytes = getByteString {-# INLINE getBytes #-} +-- | /Since: 0.7.0.0/ instance Alternative Get where   empty = C $ \inp _ks -> Fail inp "Data.Binary.Get(Alternative).empty"   (<|>) f g = do@@ -272,7 +272,7 @@ #endif  -- | Run a decoder and keep track of all the input it consumes.--- Once it's finished, return the final decoder (always 'Done' or 'Fail'), +-- Once it's finished, return the final decoder (always 'Done' or 'Fail'), -- and unconsume all the the input the decoder required to run. -- Any additional chunks which was required to run the decoder -- will also be returned.@@ -298,6 +298,8 @@  -- | Run the given decoder, but without consuming its input. If the given -- decoder fails, then so will this function.+--+-- /Since: 0.7.0.0/ lookAhead :: Get a -> Get a lookAhead g = do   (decoder, bs) <- runAndKeepTrack g@@ -309,6 +311,8 @@ -- | Run the given decoder, and only consume its input if it returns 'Just'. -- If 'Nothing' is returned, the input will be unconsumed. -- If the given decoder fails, then so will this function.+--+-- /Since: 0.7.0.0/ lookAheadM :: Get (Maybe a) -> Get (Maybe a) lookAheadM g = do   let g' = maybe (Left ()) Right <$> g@@ -317,6 +321,8 @@ -- | Run the given decoder, and only consume its input if it returns 'Right'. -- If 'Left' is returned, the input will be unconsumed. -- If the given decoder fails, then so will this function.+--+-- /Since: 0.7.1.0/ lookAheadE :: Get (Either a b) -> Get (Either a b) lookAheadE g = do   (decoder, bs) <- runAndKeepTrack g@@ -326,8 +332,10 @@     Fail inp s -> C $ \_ _ -> Fail inp s     _ -> error "Binary: impossible" --- Label a decoder. If the decoder fails, the label will be appended on+-- | Label a decoder. If the decoder fails, the label will be appended on -- a new line to the error message string.+--+-- /Since: 0.7.2.0/ label :: String -> Get a -> Get a label msg decoder = C $ \inp ks ->   let r0 = runCont decoder inp (\inp' a -> Done inp' a)@@ -380,17 +388,10 @@  {-# RULES -"<$> to <*>" forall f g.-  (<$>) f g = returnG f <*> g- "readN/readN merge" forall n m f g.   apG (readN n f) (readN m g) = readN (n+m) (\bs -> f bs $ g (B.unsafeDrop n bs)) -"returnG/readN swap" [~1] forall f.-  returnG f = readN 0 (const f)--"readN 0/returnG swapback" [1] forall f.-  readN 0 f = returnG (f B.empty) #-}+ #-}  -- | Ensure that there are at least @n@ bytes available. If not, the -- computation will escape with 'Partial'.
src/Data/Binary/Put.hs view
@@ -84,27 +84,32 @@         {-# INLINE fmap #-}  instance Applicative PutM where-        pure    = return+        pure a  = Put $ PairS a mempty+        {-# INLINE pure #-}+         m <*> k = Put $             let PairS f w  = unPut m                 PairS x w' = unPut k             in PairS (f x) (w `mappend` w') +        m *> k  = Put $+            let PairS _ w  = unPut m+                PairS b w' = unPut k+            in PairS b (w `mappend` w')+        {-# INLINE (*>) #-}+ -- Standard Writer monad, with aggressive inlining instance Monad PutM where-    return a = Put $ PairS a mempty-    {-# INLINE return #-}-     m >>= k  = Put $         let PairS a w  = unPut m             PairS b w' = unPut (k a)         in PairS b (w `mappend` w')     {-# INLINE (>>=) #-} -    m >> k  = Put $-        let PairS _ w  = unPut m-            PairS b w' = unPut k-        in PairS b (w `mappend` w')+    return = pure+    {-# INLINE return #-}++    (>>) = (*>)     {-# INLINE (>>) #-}  tell :: Builder -> Put
tests/File.hs view
@@ -1,14 +1,18 @@+{-# LANGUAGE CPP #-} module Main where -import Control.Applicative-import Test.HUnit-import System.Directory ( getTemporaryDirectory )-import System.FilePath ( (</>) )+#if ! MIN_VERSION_base(4,8,0)+import           Control.Applicative+#endif -import Distribution.Simple.Utils ( withTempDirectory )-import Distribution.Verbosity ( silent )+import           System.Directory          (getTemporaryDirectory)+import           System.FilePath           ((</>))+import           Test.HUnit -import Data.Binary+import           Distribution.Simple.Utils (withTempDirectory)+import           Distribution.Verbosity    (silent)++import           Data.Binary  data Foo = Bar !Word32 !Word32 !Word32 deriving (Eq, Show) 
tests/QC.hs view
@@ -5,6 +5,10 @@ #define HAS_NATURAL #endif +#if MIN_VERSION_base(4,7,0)+#define HAS_FIXED_CONSTRUCTOR+#endif+ #if __GLASGOW_HASKELL__ >= 704 #define HAS_GHC_FINGERPRINT #endif@@ -28,6 +32,8 @@ import           GHC.Fingerprint #endif +import qualified Data.Fixed as Fixed+ import           Test.Framework import           Test.Framework.Providers.QuickCheck2 import           Test.QuickCheck@@ -398,6 +404,30 @@  ------------------------------------------------------------------------ +#ifdef HAS_FIXED_CONSTRUCTOR++fixedPut :: forall a. Fixed.HasResolution a => Fixed.Fixed a -> Put+fixedPut x = put (truncate (x * fromInteger (Fixed.resolution (undefined :: Maybe a))) :: Integer)++fixedGet :: forall a. Fixed.HasResolution a => Get (Fixed.Fixed a)+fixedGet = (\x -> fromInteger x / fromInteger (Fixed.resolution (undefined :: Maybe a))) `liftA` get++-- | Serialise using base >=4.7 and <4.7 methods agree+prop_fixed_ser :: Fixed.Fixed Fixed.E3 -> Bool+prop_fixed_ser x = runPut (put x) == runPut (fixedPut x)++-- | Serialised with base >=4.7, unserialised with base <4.7 method roundtrip+prop_fixed_constr_resolution :: Fixed.Fixed Fixed.E3 -> Bool+prop_fixed_constr_resolution x = runGet fixedGet (runPut (put x)) == x++-- | Serialised with base <4.7, unserialised with base >=4.7 method roundtrip+prop_fixed_resolution_constr :: Fixed.Fixed Fixed.E3 -> Bool+prop_fixed_resolution_constr x = runGet get (runPut (fixedPut x)) == x++#endif++------------------------------------------------------------------------+ type T a = a -> Property type B a = a -> Bool @@ -475,6 +505,7 @@             , ("Word",       p (test :: T Word                   ))             , ("Int",        p (test :: T Int                    ))             , ("Integer",    p (test :: T Integer                ))+            , ("Fixed",      p (test :: T (Fixed.Fixed Fixed.E3) )) #ifdef HAS_NATURAL             , ("Natural",         prop_test_Natural               ) #endif@@ -536,4 +567,11 @@             , ("L.ByteString invariant",   p (prop_invariant :: B L.ByteString                 ))             , ("[L.ByteString] invariant", p (prop_invariant :: B [L.ByteString]               ))             ]+#ifdef HAS_FIXED_CONSTRUCTOR+        , testGroup "Fixed"+            [ testProperty "Serialisation same"       $ p prop_fixed_ser+            , testProperty "MkFixed -> HasResolution" $ p prop_fixed_constr_resolution+            , testProperty "HasResolution -> MkFixed" $ p prop_fixed_resolution_constr+            ]+#endif         ]