binary 0.4.2 → 0.4.3
raw patch · 7 files changed
+147/−32 lines, 7 filesdep ~basedep ~bytestringPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, bytestring
API changes (from Hackage documentation)
- Data.Binary.Put: Put :: (a, Builder) -> PutM a
+ Data.Binary.Put: Put :: PairS a -> PutM a
- Data.Binary.Put: unPut :: PutM a -> (a, Builder)
+ Data.Binary.Put: unPut :: PutM a -> PairS a
Files
- binary.cabal +15/−7
- docs/hcar/binary-Lb.tex +48/−0
- index.html +13/−1
- src/Data/Binary.hs +14/−2
- src/Data/Binary/Builder.hs +12/−2
- src/Data/Binary/Get.hs +5/−0
- src/Data/Binary/Put.hs +40/−20
binary.cabal view
@@ -1,5 +1,5 @@ name: binary-version: 0.4.2+version: 0.4.3 license: BSD3 license-file: LICENSE author: Lennart Kolmodin <kolmodin@dtek.chalmers.se>@@ -30,7 +30,7 @@ cpp-options: -DBYTESTRING_IN_BASE else -- in base 1.0 and 3.0 bytestring is a separate package- build-depends: base < 2.0 || >= 3, bytestring >= 0.9+ build-depends: base < 2.0 || >= 3, bytestring >= 0.9.1.0 if flag(split-base) build-depends: base >= 3.0, containers, array@@ -42,13 +42,21 @@ cpp-options: -DAPPLICATIVE_IN_BASE else build-depends: base < 2.0+ hs-source-dirs: src exposed-modules: Data.Binary, Data.Binary.Put, Data.Binary.Get, Data.Binary.Builder- extensions: CPP, FlexibleContexts- hs-source-dirs: src- ghc-options: -O2 -Wall -fliberate-case-threshold=1000- if impl(ghc < 6.5)- cpp-options: -fallow-undecidable-instances+ extensions: CPP,+ FlexibleContexts++ ghc-options: -O2+ -Wall+ -fspec-constr+ -fliberate-case-threshold=1000+ -fdicts-cheap+ -fno-method-sharing++-- if impl(ghc < 6.5)+-- ghc-options: -fallow-undecidable-instances
+ docs/hcar/binary-Lb.tex view
@@ -0,0 +1,48 @@+\begin{hcarentry}{binary}+\label{binary}+\report{Lennart Kolmodin}+\status{active}+\participants{Duncan Coutts, Don Stewart, Binary Strike Team}+\makeheader++The Binary Strike Team is pleased to announce yet a release of a new,+pure, efficient binary serialisation library.++The `binary' package provides efficient serialisation of Haskell values+to and from lazy ByteStrings. ByteStrings constructed this way may then+be written to disk, written to the network, or further processed (e.g.+stored in memory directly, or compressed in memory with zlib or bzlib).++The binary library has been heavily tuned for performance, particularly for+writing speed. Throughput of up to 160M/s has been achieved in practice, and+in general speed is on par or better than NewBinary, with the advantage of a+pure interface. Efforts are underway to improve performance still further.+Plans are also taking shape for a parser combinator library on top of+binary, for bit parsing and foreign structure parsing (e.g. network+protocols).++Data.Derive~\cref{derive} has support for automatically generating Binary+instances, allowing to read and write your data structures with little fuzz.++Binary was developed by a team of 8 during the Haskell Hackathon in Oxford+2007, and since then has about 15 people contributed code and many more+given feedback and cheerleading on \verb|#haskell|.++The package is cabalized and available through Hackage~\cref{hackagedb}.+% to editors: ref. to cabal?++\FurtherReading+\begin{compactitem}+\item Homepage++ \url{http://code.haskell.org/binary/}+\item Hackage++ \url{http://hackage.haskell.org/cgi-bin/hackage-scripts/package/binary}+\item Development version++ \texttt{darcs get --partial}++ \url{http://code.haskell.org/binary}+\end{compactitem}+\end{hcarentry}
index.html view
@@ -25,6 +25,18 @@ writing of structures in binary format. </p> + <p>+ Chris Eidhof writes on his use of Data.Binary implementing a+ full-text search engine:+ </p>+ <pre>+ "The communication with Sphinx is done using a quite low-level binary+ protocol, but Data.Binary saved the day: it made it very easy for us+ to parse all the binary things. Especially the use of the Get and+ Put monads are a big improvement over the manual reading and keeping+ track of positions, as is done in the PHP/Python clients."+ </pre>+ <h3>Example</h3> For example, to serialise an interpreter's abstract syntax tree to binary format:@@ -142,7 +154,7 @@ <div id="footer">-Mon Apr 21 16:12:09 PDT 2008+Mon Jul 14 11:37:21 PDT 2008 </div> </body>
src/Data/Binary.hs view
@@ -251,7 +251,7 @@ encodeFile :: Binary a => FilePath -> a -> IO () encodeFile f v = L.writeFile f (encode v) --- | Lazily reconstruct a value previously written to a file+-- | Lazily reconstruct a value previously written to a file. -- -- This is just a convenience function, it's defined simply as: --@@ -261,8 +261,20 @@ -- -- > return . decode . decompress =<< B.readFile f --+-- After contructing the data from the input file, 'decodeFile' checks+-- if the file is empty, and in doing so will force the associated file+-- handle closed, if it is indeed empty. If the file is not empty, +-- it is up to the decoding instance to consume the rest of the data,+-- or otherwise finalise the resource.+-- decodeFile :: Binary a => FilePath -> IO a-decodeFile f = liftM decode (L.readFile f)+decodeFile f = do+ s <- L.readFile f+ return $ runGet (do v <- get+ m <- isEmpty+ m `seq` return v) s++-- needs bytestring 0.9.1.x to work ------------------------------------------------------------------------ -- Lazy put and get
src/Data/Binary/Builder.hs view
@@ -99,7 +99,9 @@ instance Monoid Builder where mempty = empty+ {-# INLINE mempty #-} mappend = append+ {-# INLINE mappend #-} ------------------------------------------------------------------------ @@ -109,6 +111,7 @@ -- empty :: Builder empty = Builder id+{-# INLINE empty #-} -- | /O(1)./ A Builder taking a single byte, satisfying --@@ -127,6 +130,7 @@ -- append :: Builder -> Builder -> Builder append (Builder f) (Builder g) = Builder (f . g)+{-# INLINE append #-} -- | /O(1)./ A Builder taking a 'S.ByteString', satisfying --@@ -136,6 +140,7 @@ fromByteString bs | S.null bs = empty | otherwise = flush `append` mapBuilder (bs :)+{-# INLINE fromByteString #-} -- | /O(1)./ A Builder taking a lazy 'L.ByteString', satisfying --@@ -143,6 +148,7 @@ -- fromLazyByteString :: L.ByteString -> Builder fromLazyByteString bss = flush `append` mapBuilder (L.toChunks bss ++)+{-# INLINE fromLazyByteString #-} ------------------------------------------------------------------------ @@ -212,7 +218,7 @@ -- bytes into the memory. writeN :: Int -> (Ptr Word8 -> IO ()) -> Builder writeN n f = ensureFree n `append` unsafeLiftIO (writeNBuffer n f)-{-# INLINE [1] writeN #-}+{-# INLINE writeN #-} writeNBuffer :: Int -> (Ptr Word8 -> IO ()) -> Buffer -> IO Buffer writeNBuffer n f (Buffer fp o u l) = do@@ -224,6 +230,7 @@ newBuffer size = do fp <- S.mallocByteString size return $! Buffer fp 0 0 size+{-# INLINE newBuffer #-} ------------------------------------------------------------------------ -- Aligned, host order writes of storable values@@ -232,7 +239,7 @@ -- storable values into the memory. writeNbytes :: Storable a => Int -> (Ptr a -> IO ()) -> Builder writeNbytes n f = ensureFree n `append` unsafeLiftIO (writeNBufferBytes n f)-{-# INLINE [1] writeNbytes #-}+{-# INLINE writeNbytes #-} writeNBufferBytes :: Storable a => Int -> (Ptr a -> IO ()) -> Buffer -> IO Buffer writeNBufferBytes n f (Buffer fp o u l) = do@@ -388,8 +395,11 @@ ------------------------------------------------------------------------ -- Unchecked shifts +{-# INLINE shiftr_w16 #-} shiftr_w16 :: Word16 -> Int -> Word16+{-# INLINE shiftr_w32 #-} shiftr_w32 :: Word32 -> Int -> Word32+{-# INLINE shiftr_w64 #-} shiftr_w64 :: Word64 -> Int -> Word64 #if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)
src/Data/Binary/Get.hs view
@@ -110,6 +110,7 @@ instance Functor Get where fmap f m = Get (\s -> let (a, s') = unGet m s in (f a, s'))+ {-# INLINE fmap #-} #ifdef APPLICATIVE_IN_BASE instance Applicative Get where@@ -119,8 +120,12 @@ instance Monad Get where return a = Get (\s -> (a, s))+ {-# INLINE return #-}+ m >>= k = Get (\s -> let (a, s') = unGet m s in unGet (k a) s')+ {-# INLINE (>>=) #-}+ fail = failDesc instance MonadFix Get where
src/Data/Binary/Put.hs view
@@ -45,6 +45,7 @@ ) where +import Data.Monoid import Data.Binary.Builder (Builder, toLazyByteString) import qualified Data.Binary.Builder as B @@ -59,49 +60,64 @@ ------------------------------------------------------------------------ +-- XXX Strict in buffer only. +data PairS a = PairS a {-# UNPACK #-}!Builder++sndS :: PairS a -> Builder+sndS (PairS _ b) = b+ -- | The PutM type. A Writer monad over the efficient Builder monoid.-newtype PutM a = Put { unPut :: (a, Builder) }+newtype PutM a = Put { unPut :: PairS a } --- | Put merely lifts Builder into a Write monad, applied to ().+-- | Put merely lifts Builder into a Writer monad, applied to (). type Put = PutM () instance Functor PutM where- fmap f m = Put (let (a, w) = unPut m- in (f a, w))+ fmap f m = Put $ let PairS a w = unPut m in PairS (f a) w+ {-# INLINE fmap #-} #ifdef APPLICATIVE_IN_BASE instance Applicative PutM where- pure = return- m <*> k = Put (let (f, w) = unPut m- (x, w') = unPut k- in (f x, w `B.append` w'))+ pure = return+ m <*> k = Put $+ let PairS f w = unPut m+ PairS x w' = unPut k+ in PairS (f x) (w `mappend` w') #endif +-- Standard Writer monad, with aggressive inlining instance Monad PutM where- return a = Put (a, B.empty)+ return a = Put $ PairS a mempty+ {-# INLINE return #-} - m >>= k = Put (let (a, w) = unPut m- (b, w') = unPut (k a)- in (b, w `B.append` w'))+ m >>= k = Put $+ let PairS a w = unPut m+ PairS b w' = unPut (k a)+ in PairS b (w `mappend` w')+ {-# INLINE (>>=) #-} - m1 >> m2 = Put (let (_, w) = unPut m1- (b, w') = unPut m2- in (b, w `B.append` w'))- {-# INlINE (>>) #-}+ m >> k = Put $+ let PairS _ w = unPut m+ PairS b w' = unPut k+ in PairS b (w `mappend` w')+ {-# INLINE (>>) #-} tell :: Builder -> Put-tell b = Put ((), b)-{-# INlINE tell #-}+tell b = Put $ PairS () b+{-# INLINE tell #-} -- | Run the 'Put' monad with a serialiser-runPut :: Put -> L.ByteString-runPut = toLazyByteString . snd . unPut+runPut :: Put -> L.ByteString+runPut = toLazyByteString . sndS . unPut {-# INLINE runPut #-} +------------------------------------------------------------------------+ -- | Pop the ByteString we have constructed so far, if any, yielding a -- new chunk in the result ByteString. flush :: Put flush = tell B.flush+{-# INLINE flush #-} -- | Efficiently write a byte into the output buffer putWord8 :: Word8 -> Put@@ -112,19 +128,23 @@ -- It flushes the current buffer, and writes the argument into a new chunk. putByteString :: S.ByteString -> Put putByteString = tell . B.fromByteString+{-# INLINE putByteString #-} -- | Write a lazy ByteString efficiently, simply appending the lazy -- ByteString chunks to the output buffer putLazyByteString :: L.ByteString -> Put putLazyByteString = tell . B.fromLazyByteString+{-# INLINE putLazyByteString #-} -- | Write a Word16 in big endian format putWord16be :: Word16 -> Put putWord16be = tell . B.putWord16be+{-# INLINE putWord16be #-} -- | Write a Word16 in little endian format putWord16le :: Word16 -> Put putWord16le = tell . B.putWord16le+{-# INLINE putWord16le #-} -- | Write a Word32 in big endian format putWord32be :: Word32 -> Put