packages feed

flat 0.2.2 → 0.3

raw patch · 17 files changed

+344/−168 lines, 17 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Flat.Run: flatStrict :: Flat a => a -> ByteString
- Data.Flat.Run: instance Data.Flat.Class.Flat a => Data.Flat.Run.FlatRaw a Data.ByteString.Internal.ByteString
- Data.Flat.Run: instance Data.Flat.Class.Flat a => Data.Flat.Run.FlatRaw a Data.ByteString.Lazy.Internal.ByteString
- Data.Flat.Run: unflatStrict :: Flat a => ByteString -> Decoded a
+ Data.ByteString.Convert: class AsByteString a
+ Data.ByteString.Convert: fromByteString :: AsByteString a => ByteString -> a
+ Data.ByteString.Convert: instance Data.ByteString.Convert.AsByteString Data.ByteString.Internal.ByteString
+ Data.ByteString.Convert: instance Data.ByteString.Convert.AsByteString Data.ByteString.Lazy.Internal.ByteString
+ Data.ByteString.Convert: instance Data.ByteString.Convert.AsByteString [GHC.Word.Word8]
+ Data.ByteString.Convert: toByteString :: AsByteString a => a -> ByteString
+ Data.Flat.Bits: asBits :: FiniteBits a => a -> Bits
+ Data.Flat.Bits: fromBools :: [Bool] -> Bits
+ Data.Flat.Decoder: dBE16 :: Get Word16
+ Data.Flat.Decoder: dBE32 :: Get Word32
+ Data.Flat.Decoder: dBE64 :: Get Word64
+ Data.Flat.Decoder: dBE8 :: Get Word8
+ Data.Flat.Decoder: dBEBits16 :: Int -> Get Word16
+ Data.Flat.Decoder: dBEBits32 :: Int -> Get Word32
+ Data.Flat.Decoder: dBEBits64 :: Int -> Get Word64
+ Data.Flat.Decoder: dBEBits8 :: Int -> Get Word8
+ Data.Flat.Decoder: dropBits :: Int -> Get ()
+ Data.Flat.Decoder.Prim: dBE16 :: Get Word16
+ Data.Flat.Decoder.Prim: dBE32 :: Get Word32
+ Data.Flat.Decoder.Prim: dBE64 :: Get Word64
+ Data.Flat.Decoder.Prim: dBE8 :: Get Word8
+ Data.Flat.Decoder.Prim: dBEBits16 :: Int -> Get Word16
+ Data.Flat.Decoder.Prim: dBEBits32 :: Int -> Get Word32
+ Data.Flat.Decoder.Prim: dBEBits64 :: Int -> Get Word64
+ Data.Flat.Decoder.Prim: dBEBits8 :: Int -> Get Word8
+ Data.Flat.Decoder.Prim: dropBits :: Int -> Get ()
+ Data.Flat.Run: flatRaw :: (Flat a, AsByteString b) => a -> b
+ Data.Flat.Run: unflatRawWith :: AsByteString b => Get a -> b -> Decoded a
- Data.Flat.Decoder.Types: badEncoding :: Ptr Word8 -> S -> IO a
+ Data.Flat.Decoder.Types: badEncoding :: Ptr Word8 -> S -> String -> IO a
- Data.Flat.Filler: postAlignedDecoder :: Get a -> Get (PostAligned a)
+ Data.Flat.Filler: postAlignedDecoder :: Get b -> Get b
- Data.Flat.Run: flat :: (FlatRaw (PostAligned a) c, Flat a) => a -> c
+ Data.Flat.Run: flat :: Flat a => a -> ByteString
- Data.Flat.Run: unflat :: (FlatRaw (PostAligned a) b, Flat a) => b -> Decoded a
+ Data.Flat.Run: unflat :: (Flat a, AsByteString b) => b -> Decoded a
- Data.Flat.Run: unflatRaw :: (FlatRaw a b, Flat a) => b -> Decoded a
+ Data.Flat.Run: unflatRaw :: (Flat a, AsByteString b) => b -> Decoded a
- Data.Flat.Run: unflatWith :: FlatRaw (PostAligned a) b => Get (PostAligned a) -> b -> Decoded a
+ Data.Flat.Run: unflatWith :: AsByteString b => Get a -> b -> Decoded a

Files

+ CHANGELOG view
@@ -0,0 +1,7 @@+Significant and compatibility-breaking changes.++Version 0.3:+	- Removed 'flatStrict' and 'unflatStrict' (use 'flat' and 'unflat' instead that also encode/decode strictly)+	- `unflatWith` now takes a decoder for the unpadded value (previously it expected a padded decoder) and decodes the padded value+	- Added some decoding primitives+	- Added Data.ByteString.Convert
README.md view
@@ -31,10 +31,10 @@ data List a = Nil | Cons a (List a) deriving (Show,Generic,Flat) ``` -For encoding, use `flat`, for decoding, use `unflat` (or equivalently: `flatStrict` and `unflatStrict`):+For encoding, use `flat`, for decoding, use `unflat`:  ```haskell-unflatStrict . flat $ Cons North (Cons South Nil) :: Decoded (List Direction)+unflat . flat $ Cons North (Cons South Nil) :: Decoded (List Direction) -> Right (Cons North (Cons South Nil)) ``` @@ -119,9 +119,9 @@  * Encoding: `store` and `flat` are usually faster  * Decoding: `store`, `cereal` and `flat` are usually faster - One thing that is not shown by the benchmarks is that, if the serialized data is to be transferred over a network, the total total transfer time (encoding time + transmission time + decoding time) is usually dominated by the transmission time and that's where the smaller binaries produced by flat give it a significant advantage.+ One thing that is not shown by the benchmarks is that, if the serialized data is to be transferred over a network, the total transfer time (encoding time + transmission time + decoding time) is usually dominated by the transmission time and that's where the smaller binaries produced by flat give it a significant advantage. - Consider for example the Cars dataset. As you can see in the following comparison with `store`, the overall top performer for encoding/decoding speed, the total transfer time is actually significantly lower for `flat` for all except the highest transmission speeds.+ Consider for example the Cars dataset. As you can see in the following comparison with `store`, the overall top performer for encoding/decoding speed, the transfer time is actually significantly lower for `flat` for all except the highest transmission speeds.  ||Store|Flat| |---|---|---|
flat.cabal view
@@ -1,22 +1,23 @@ name: flat-version: 0.2.2+version: 0.3 synopsis: Principled and efficient bit-oriented binary serialization. description: See the <http://github.com/tittoassini/flat online tutorial>. homepage: http://github.com/tittoassini/flat-copyright: Copyright: (c) 2016 Pasqualino `Titto` Assini-author: Pasqualino `Titto` Assini-license: BSD3-license-file: LICENSE-maintainer: tittoassini@gmail.com+license:             BSD3+license-file:        LICENSE+author:              Pasqualino `Titto` Assini+maintainer:          tittoassini@gmail.com+copyright:           Copyright: (c) 2016 Pasqualino `Titto` Assini category: Data,Parsing,Serialization cabal-version: >=1.10 build-type: Simple-tested-with: GHC ==7.10.3 GHC ==8.0.2+Tested-With: GHC == 7.10.3 GHC == 8.0.1 GHC == 8.0.2 extra-source-files:     stack.yaml     stack801.yaml     stack802.yaml     README.md+    CHANGELOG  source-repository head     type: git@@ -24,6 +25,7 @@  library     exposed-modules:+        Data.ByteString.Convert         Data.Flat.Bits         Data.Flat.Class         Data.Flat.Decoder
+ src/Data/ByteString/Convert.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE FlexibleInstances #-}+-- |Convert to/from strict ByteStrings+module Data.ByteString.Convert (AsByteString(..)) where++import qualified Data.ByteString      as B+import qualified Data.ByteString.Lazy as L+import           Data.Word++class AsByteString a where+  toByteString :: a -> B.ByteString+  fromByteString :: B.ByteString -> a++instance AsByteString B.ByteString where+  toByteString = id+  fromByteString = id++instance AsByteString L.ByteString where+  toByteString = L.toStrict+  fromByteString = L.fromStrict++instance AsByteString [Word8] where+  toByteString = B.pack+  fromByteString = B.unpack+
src/Data/Flat/Bits.hs view
@@ -4,15 +4,22 @@ {-# LANGUAGE TypeSynonymInstances #-}  -- |Utilities to represent and display bit sequences-module Data.Flat.Bits (Bits, toBools, bits, paddedBits, asBytes) where+module Data.Flat.Bits (+    Bits,+    toBools,+    fromBools,+    bits,+    paddedBits,+    asBytes,+    asBits,+    ) where  import           Data.Bits                      hiding (Bits)-import qualified Data.ByteString           as L-import           Data.Flat.Decoder+import qualified Data.ByteString                as B import           Data.Flat.Class+import           Data.Flat.Decoder import           Data.Flat.Filler import           Data.Flat.Run--- import           Data.Int import qualified Data.Vector.Unboxed            as V import           Data.Word import           Text.PrettyPrint.HughesPJClass@@ -23,19 +30,27 @@ toBools :: Bits -> [Bool] toBools = V.toList +fromBools :: [Bool] -> Bits+fromBools = V.fromList+ -- |The sequence of bits corresponding to the serialization of the passed value (without any final byte padding) bits :: forall a. Flat a => a -> Bits bits v = let lbs = flat v              Right (PostAligned _ f) = unflatRaw lbs :: Decoded (PostAligned a)-         in takeBits (8 * L.length lbs - fillerLength f) lbs+         in takeBits (8 * B.length lbs - fillerLength f) lbs  -- |The sequence of bits corresponding to the byte-padded serialization of the passed value paddedBits :: forall a. Flat a => a -> Bits paddedBits v = let lbs = flat v-               in takeBits (8 * L.length lbs) lbs+               in takeBits (8 * B.length lbs) lbs -takeBits :: Int -> L.ByteString -> V.Vector Bool-takeBits numBits lbs  = V.generate (fromIntegral numBits) (\n -> let (bb,b) = n `divMod` 8 in testBit (L.index lbs (fromIntegral bb)) (7-b))+takeBits :: Int -> B.ByteString -> Bits+takeBits numBits lbs  = V.generate (fromIntegral numBits) (\n -> let (bb,b) = n `divMod` 8 in testBit (B.index lbs (fromIntegral bb)) (7-b))++-- | asBits (5::Word8)+-- | > [False,False,False,False,False,True,False,True]+asBits :: FiniteBits a => a -> Bits+asBits w = let s = finiteBitSize w in V.generate s (testBit w . (s-1-))  -- |Convert a sequence of bits to the corresponding list of bytes asBytes :: Bits -> [Word8]
src/Data/Flat/Decoder.hs view
@@ -29,6 +29,15 @@     dInt32,     dInt64,     dInt,+    dBE8,+    dBE16,+    dBE32,+    dBE64,+    dBEBits8,+    dBEBits16,+    dBEBits32,+    dBEBits64,+    dropBits,     ) where  import Data.Flat.Decoder.Prim
src/Data/Flat/Decoder/Prim.hs view
@@ -1,17 +1,25 @@ {-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE DeriveGeneric       #-} {-# LANGUAGE MagicHash           #-} {-# LANGUAGE ScopedTypeVariables #-} -- |Strict Decoder Primitives module Data.Flat.Decoder.Prim (     dBool,     dWord8,+    dBE8,+    dBE16,+    dBE32,+    dBE64,+    dBEBits8,+    dBEBits16,+    dBEBits32,+    dBEBits64,+    dropBits,     dFloat,     dDouble,     getChunksInfo,     dByteString_,     dLazyByteString_,-    dByteArray_+    dByteArray_,     ) where  import           Control.Monad@@ -24,9 +32,29 @@ import           Foreign import           System.Endian +{-# INLINE ensureBits #-}+-- |Ensure that the specified number of bits is available+ensureBits :: Ptr Word8 -> S -> Int -> IO ()+ensureBits endPtr s n = when ((endPtr `minusPtr` currPtr s) * 8 - usedBits s < n) $ notEnoughSpace endPtr s++{-# INLINE dropBits #-}+-- |Drop the specified number of bits+dropBits :: Int -> Get ()+dropBits n+  | n > 0 = Get $ \endPtr s -> do+      ensureBits endPtr s n+      return $ GetResult (dropBits_ s n) ()+  | n == 0 = return ()+  | otherwise = error $ unwords ["dropBits",show n]++dropBits_ :: S -> Int -> S+dropBits_ s n = let (bytes,bits) = (n+usedBits s) `divMod` 8+                in S {currPtr=currPtr s `plusPtr` bytes,usedBits=bits}+ {-# INLINE dBool #-}+-- |Decode a boolean dBool :: Get Bool-dBool = Get $ \endPtr s -> +dBool = Get $ \endPtr s ->   if currPtr s >= endPtr     then notEnoughSpace endPtr s     else do@@ -38,63 +66,185 @@                   else s { usedBits = usedBits s + 1 }       return $ GetResult s' b -{-# INLINE dWord8  #-}+{-# INLINE dBEBits8  #-}+-- |Return the n most significant bits (up to maximum of 8)+-- The bits are returned right shifted.+--+-- >>> unflatWith (dBEBits8 3) [128+64+32+1::Word8]+-- Right 7+dBEBits8 :: Int -> Get Word8+dBEBits8 n = Get $ \endPtr s -> do+      ensureBits endPtr s n+      take8 s n++{-# INLINE dBEBits16  #-}+-- |Return the n most significant bits (up to maximum of 16)+-- The bits are returned right shifted.+dBEBits16 :: Int -> Get Word16+dBEBits16 n = Get $ \endPtr s -> do+      ensureBits endPtr s n+      takeN n s++{-# INLINE dBEBits32  #-}+-- |Return the n most significant bits (up to maximum of 8)+-- The bits are returned right shifted.+dBEBits32 :: Int -> Get Word32+dBEBits32 n = Get $ \endPtr s -> do+      ensureBits endPtr s n+      takeN n s++{-# INLINE dBEBits64  #-}+-- |Return the n most significant bits (up to maximum of 8)+-- The bits are returned right shifted.+dBEBits64 :: Int -> Get Word64+dBEBits64 n = Get $ \endPtr s -> do+      ensureBits endPtr s n+      takeN n s++-- {-# INLINE take8 #-}+-- take8 :: Int -> S -> IO (GetResult Word8)+-- take8 n s+--   | n == 0 = return $ GetResult s 0++--   -- all bits in the same byte+--   | n <= 8 - usedBits s = do+--       w <- peek (currPtr s)+--       let (bytes,bits) = (n+usedBits s) `divMod` 8+--       return $ GetResult (S {currPtr=currPtr s `plusPtr` bytes,usedBits=bits}) ((w `unsafeShiftL` usedBits s) `unsafeShiftR` (8 - n))++--   -- two different bytes+--   | n <= 8 = do+--       w::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)+--       return $ GetResult (S {currPtr=currPtr s `plusPtr` 1,usedBits=(usedBits s + n) `mod` 8}) (fromIntegral $ (w `unsafeShiftL` usedBits s) `unsafeShiftR` (16 - n))++--   | otherwise = error $ unwords ["take8: cannot take",show n,"bits"]++{-# INLINE take8 #-}+take8 :: S -> Int -> IO (GetResult Word8)+take8 s n = GetResult (dropBits_ s n) <$> read8 s n++{-# INLINE read8 #-}+read8 :: S -> Int -> IO Word8+read8 s n | n >=0 && n <=8 =+            if n <= 8 - usedBits s+            then do  -- all bits in the same byte+              w <- peek (currPtr s)+              return $ (w `unsafeShiftL` usedBits s) `unsafeShiftR` (8 - n)+            else do -- two different bytes+              w::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)+              return $ fromIntegral $ (w `unsafeShiftL` usedBits s) `unsafeShiftR` (16 - n)+          | otherwise = error $ unwords ["read8: cannot read",show n,"bits"]++{-# INLINE takeN #-}+takeN :: (Num a, Bits a) => Int -> S -> IO (GetResult a)+takeN n s = read s 0 (n - (n `min` 8)) n+   where+     read s r sh n | n <=0 = return $ GetResult s r+                   | otherwise = do+                     let m = n `min` 8+                     GetResult s' b <- take8 s m+                     read s' (r .|. (fromIntegral b `unsafeShiftL` sh)) ((sh-8) `max` 0) (n-8)++-- takeN n = Get $ \endPtr s -> do+--   ensureBits endPtr s n+--   let (bytes,bits) = (n+usedBits s) `divMod` 8+--   r <- case bytes of+--     0 -> do+--       w <- peek (currPtr s)+--       return . fromIntegral $ ((w `unsafeShiftL` usedBits s) `unsafeShiftR` (8 - n))+--     1 -> do+--       w::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)+--       return $ fromIntegral $ (w `unsafeShiftL` usedBits s) `unsafeShiftR` (16 - n)+--     2 -> do+--       let r = 0+--       w1 <- fromIntegral <$> r8 s+--       w2 <- fromIntegral <$> r16 s+--       w1 +--   return $ GetResult (S {currPtr=currPtr s `plusPtr` bytes,usedBits=bits}) r++-- r8 s = peek (currPtr s)+-- r16 s = toBE16 <$> peek (castPtr $ currPtr s)++-- |Return the 8 most significant bits (same as dBE8) dWord8 :: Get Word8-dWord8 = Get $ \endPtr s -> do+dWord8 = dBE8++{-# INLINE dBE8  #-}+-- |Return the 8 most significant bits+dBE8 :: Get Word8+dBE8 = Get $ \endPtr s -> do       ensureBits endPtr s 8+      !w1 <- peek (currPtr s)       !w <- if usedBits s == 0-            then peek (currPtr s)+            then return w1             else do-                   !w1 <- peek (currPtr s)                    !w2 <- peek (currPtr s `plusPtr` 1)                    return $ (w1 `unsafeShiftL` usedBits s) .|. (w2 `unsafeShiftR` (8-usedBits s))       return $ GetResult (s {currPtr=currPtr s `plusPtr` 1}) w -{-# INLINE ensureBits #-}-ensureBits :: Ptr Word8 -> S -> Int -> IO ()-ensureBits endPtr s n = when ((endPtr `minusPtr` currPtr s) * 8 - usedBits s < n) $ notEnoughSpace endPtr s---- {-# INLINE incBits #-}--- incBits :: Int -> S -> S--- incBits 1 s = if usedBits s == 7---            then s {currPtr=currPtr s `plusPtr` 1,usedBits=0}---            else s {usedBits=usedBits s+1}---- incBits 8 s = s {currPtr=currPtr s `plusPtr` 1}+{-# INLINE dBE16 #-}+-- |Return the 16 most significant bits+dBE16 :: Get Word16+dBE16 = Get $ \endPtr s -> do+  ensureBits endPtr s 16+  !w1 <- toBE16 <$> peek (castPtr $ currPtr s)+  !w <- if usedBits s == 0+        then return w1+        else do+           !(w2::Word8) <- peek (currPtr s `plusPtr` 2)+           return $ w1 `unsafeShiftL` usedBits s  .|. fromIntegral (w2 `unsafeShiftR` (8-usedBits s))+  return $ GetResult (s {currPtr=currPtr s `plusPtr` 2}) w -{-# INLINE dFloat #-}-dFloat :: Get Float-dFloat = Get $ \endPtr s -> do+{-# INLINE dBE32 #-}+-- |Return the 32 most significant bits+dBE32 :: Get Word32+dBE32 = Get $ \endPtr s -> do   ensureBits endPtr s 32+  !w1 <- toBE32 <$> peek (castPtr $ currPtr s)   !w <- if usedBits s == 0-        then toBE32 <$> peek (castPtr $ currPtr s)+        then return w1         else do-           !w1 <- toBE32 <$> peek (castPtr $ currPtr s)            !(w2::Word8) <- peek (currPtr s `plusPtr` 4)            return $ w1 `unsafeShiftL` usedBits s  .|. fromIntegral (w2 `unsafeShiftR` (8-usedBits s))-  return $ GetResult (s {currPtr=currPtr s `plusPtr` 4}) (wordToFloat w)+  return $ GetResult (s {currPtr=currPtr s `plusPtr` 4}) w -{-# INLINE dDouble #-}-dDouble :: Get Double-dDouble = Get $ \endPtr s -> do+{-# INLINE dBE64 #-}+-- |Return the 64 most significant bits+dBE64 :: Get Word64+dBE64 = Get $ \endPtr s -> do   ensureBits endPtr s 64+  !w1 <- toBE64 <$> peek (castPtr $ currPtr s)   !w <- if usedBits s == 0-        then toBE64 <$> peek (castPtr $ currPtr s)+        then return w1         else do-           !w1 <- toBE64 <$> peek (castPtr $ currPtr s)            !(w2::Word8) <- peek (currPtr s `plusPtr` 8)            return $ w1 `unsafeShiftL` usedBits s  .|. fromIntegral (w2 `unsafeShiftR` (8-usedBits s))-  return $ GetResult (s {currPtr=currPtr s `plusPtr` 8}) (wordToDouble w)+  return $ GetResult (s {currPtr=currPtr s `plusPtr` 8}) w +{-# INLINE dFloat #-}+-- |Decode a Float+dFloat :: Get Float+dFloat = wordToFloat <$> dBE32++{-# INLINE dDouble #-}+-- |Decode a Double+dDouble :: Get Double+dDouble = wordToDouble <$> dBE64++-- |Decode a Lazy ByteString dLazyByteString_ :: Get L.ByteString dLazyByteString_ = L.fromStrict <$> dByteString_ +-- |Decode a ByteString dByteString_ :: Get B.ByteString dByteString_ = chunksToByteString <$> getChunksInfo +-- |Decode a ByteArray and its length dByteArray_ :: Get (ByteArray,Int) dByteArray_ = chunksToByteArray <$> getChunksInfo +-- |Decode an Array (a list of chunks up to 255 bytes long)+-- returning the pointer to the first data byte and a list of chunk sizes getChunksInfo :: Get (Ptr Word8, [Int]) getChunksInfo = Get $ \endPtr s -> do @@ -107,6 +257,6 @@               ensureBits endPtr s ((n+1)*8)               getChunks (srcPtr `plusPtr` (n+1)) (l . (n:)) -   when (usedBits s /=0) $ badEncoding endPtr s+   when (usedBits s /=0) $ badEncoding endPtr s "usedBits /= 0"    (currPtr',ns) <- getChunks (currPtr s) id    return $ GetResult (s {currPtr=currPtr'}) (currPtr s `plusPtr` 1,ns)
src/Data/Flat/Decoder/Types.hs view
@@ -93,8 +93,8 @@         runGet (f x') end s'     {-# INLINE (>>=) #-} -    -- fail = getException-    -- {-# INLINE fail #-}+    fail msg = Get $ \end s -> badEncoding end s msg+    {-# INLINE fail #-}  -- |Decoder state data S =@@ -111,7 +111,7 @@ -- |An exception during decoding data DecodeException = NotEnoughSpace Env                      | TooMuchSpace Env-                     | BadEncoding Env+                     | BadEncoding Env String   deriving (Show,Eq,Ord)  type Env = (Ptr Word8,S)@@ -122,8 +122,8 @@ tooMuchSpace :: Ptr Word8 -> S -> IO a tooMuchSpace endPtr s = throwIO $ TooMuchSpace (endPtr,s) -badEncoding :: Ptr Word8 -> S -> IO a-badEncoding endPtr s = throwIO $ BadEncoding (endPtr,s)+badEncoding :: Ptr Word8 -> S -> String -> IO a+badEncoding endPtr s msg = throwIO $ BadEncoding (endPtr,s) msg  instance Exception DecodeException 
src/Data/Flat/Encoder.hs view
@@ -55,8 +55,9 @@     sShortBytes,     sUTF16,     sFillerMax,-    sBool-    ,sUTF8Max,eUTF8+    sBool,+    sUTF8Max,+    eUTF8,     ) where  import           Data.Flat.Encoder.Prim
src/Data/Flat/Filler.hs view
@@ -51,8 +51,10 @@ preAligned :: a -> PreAligned a preAligned = PreAligned FillerEnd -postAlignedDecoder :: Get a -> Get (PostAligned a)+-- postAlignedDecoder :: Get a -> Get (PostAligned a)+postAlignedDecoder :: Get b -> Get b postAlignedDecoder dec = do   v <- dec   _::Filler <- decode-  return (postAligned v)+  -- return (postAligned v)+  return v
src/Data/Flat/Instances.hs view
@@ -181,7 +181,7 @@ -- |Calculate size of an instance of IsMap {-# INLINE sizeMap #-} sizeMap :: (Flat (ContainerKey r), Flat (MapValue r), IsMap r) => Size r-sizeMap m acc = F.foldl' (\acc (k,v) -> size k (size v (acc + 1))) (acc+1) . mapToList $ m+sizeMap m acc = F.foldl' (\acc' (k,v) -> size k (size v (acc' + 1))) (acc+1) . mapToList $ m  {-# INLINE encodeMap #-} -- |Encode an instance of IsMap, as a list
src/Data/Flat/Run.hs view
@@ -1,59 +1,43 @@-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances         #-} -- |Encoding and decoding functions module Data.Flat.Run (     flat,-    flatStrict,+    flatRaw,     unflat,-    unflatStrict,     unflatWith,     unflatRaw,-    --unflatRawWith,+    unflatRawWith,     ) where -import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString         as B+import           Data.ByteString.Convert import           Data.Flat.Class import           Data.Flat.Decoder-import qualified Data.Flat.Encoder    as E+import qualified Data.Flat.Encoder       as E import           Data.Flat.Filler --- |Strictly encode padded value.-flatStrict :: Flat a => a -> B.ByteString-flatStrict = flat- -- |Encode padded value.-flat :: (FlatRaw (PostAligned a) c, Flat a) => a -> c+flat :: Flat a => a -> B.ByteString flat = flatRaw . postAligned -unflatStrict :: Flat a => B.ByteString -> Decoded a-unflatStrict = unflat- -- |Decode padded value.-unflat :: (FlatRaw (PostAligned a) b, Flat a) => b -> Decoded a+unflat :: (Flat a,AsByteString b) => b -> Decoded a unflat = unflatWith decode --- |Decode padded value, using the provided decoder.-unflatWith :: FlatRaw (PostAligned a) b => Get (PostAligned a) -> b -> Decoded a-unflatWith dec bs = postValue <$> unflatRawWith dec bs+-- |Decode padded value, using the provided unpadded decoder.+unflatWith :: AsByteString b => Get a -> b -> Decoded a+unflatWith dec = unflatRawWith (postAlignedDecoder dec) --- |Decode (unpadded) value.-unflatRaw :: (FlatRaw a b, Flat a) => b -> Decoded a+-- |Decode unpadded value.+unflatRaw :: (Flat a,AsByteString b) => b -> Decoded a unflatRaw = unflatRawWith decode -class FlatRaw a b where-  -- |Encode (unpadded) value-  flatRaw :: Flat a => a -> b--  -- |Unflat (unpadded) value, using provided decoder-  unflatRawWith :: Get a -> b -> Decoded a--instance Flat a => FlatRaw a B.ByteString where-  flatRaw a = E.strictEncoder (getSize a) (encode a)--  unflatRawWith = strictDecoder+-- |Unflat unpadded value, using provided decoder+unflatRawWith :: AsByteString b => Get a -> b -> Decoded a+unflatRawWith dec = strictDecoder dec . toByteString -instance Flat a => FlatRaw a L.ByteString where-  flatRaw = L.fromStrict . flatRaw-  unflatRawWith dec = unflatRawWith dec . L.toStrict+-- |Encode unpadded value+flatRaw :: (Flat a, AsByteString b) => a -> b+flatRaw a = fromByteString $ E.strictEncoder (getSize a) (encode a)
stack.yaml view
@@ -1,26 +1,4 @@-# pvp-bounds: lower--flags:-  binary-serialise-cbor:-    newtime15: true-extra-package-dbs: []-packages:-- '.'--- location:-    git: https://github.com/well-typed/binary-serialise-cbor-    commit: 5e2f20c0a2d8fd750f431af9a17ba116a6f31cf0-  extra-dep: true+resolver: lts-6.31 -# ghc-7.10.3-resolver: lts-6.30 extra-deps: - mono-traversable-1.0.2-- store-0.4.1-- store-core-0.4-- binary-0.8.5.1-- cereal-0.5.4.0-- th-utilities-0.2.0.1-- criterion-1.1.4.0-- optparse-applicative-0.13.0.0-
stack801.yaml view
@@ -1,22 +1,1 @@-flags:-  binary-serialise-cbor:-    newtime15: true--extra-package-dbs: []--packages:-- '.'--- location:-    git: https://github.com/well-typed/binary-serialise-cbor-    commit: 5e2f20c0a2d8fd750f431af9a17ba116a6f31cf0-  extra-dep: true- -# 8.0.1-resolver: lts-7.20-extra-deps:-- store-0.4.1-- store-core-0.4-- binary-0.8.5.1-- criterion-1.1.4.0-- optparse-applicative-0.13.2.0+resolver: lts-7.21
stack802.yaml view
@@ -1,23 +1,1 @@-flags:-  binary-serialise-cbor:-    newtime15: true--extra-package-dbs: []--packages:-- '.'--- location:-    git: https://github.com/well-typed/binary-serialise-cbor-    commit: 5e2f20c0a2d8fd750f431af9a17ba116a6f31cf0-  extra-dep: true- -# 8.0.2 - doesn't compile heavily mutually recursive data types.-# low performance on certain tests as encoder RULES are not applied-resolver: lts-8.5-extra-deps:-- store-0.4.1-- store-core-0.4-- binary-0.8.5.1-- derive-2.6.2- +resolver: lts-8.13
test/Spec.hs view
@@ -10,6 +10,7 @@ -- | Tests for the flat module module Main where +import           Data.Bits import qualified Data.ByteString       as B import qualified Data.ByteString.Lazy  as L import qualified Data.ByteString.Short as SBS@@ -18,6 +19,7 @@ import           Data.Either import           Data.Flat import           Data.Flat.Bits+import           Data.Flat.Decoder import           Data.Int import           Data.List import qualified Data.Map              as M@@ -204,6 +206,29 @@   ,s (-0.15625::Float)  [0b10111110,0b00100000,0,0]   ,s (-0.15625::Double) [0b10111111,0b11000100,0,0,0,0,0,0]   ,s (-123.2325E-23::Double) [0b10111011,0b10010111,0b01000111,0b00101000,0b01110101,0b01111011,0b01000111,0b10111010]+  ,dec ((,,,) <$> dropBits 13 <*> dBool <*> dBool <*> dBool) [0b10111110,0b10011010] ((),False,True,False)+  ,dec ((,,,) <$> dropBits 1 <*> dBE16 <*> dBool <*> dropBits 6) [0b11000000+                                                                 ,0b00000001+                                                                 ,0b01000000] ((),2^15+2,True,())+  ,dec ((,,,) <$> dropBits 1 <*> dBE32 <*> dBool <*> dropBits 6) [0b11000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000001+                                                                 ,0b01000000] ((),2^31+2,True,())+  ,dec ((,,,) <$> dropBits 1 <*> dBE64 <*> dBool <*> dropBits 6) [0b11000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000000+                                                                 ,0b00000001+                                                                 ,0b01000000] ((),2^63+2,True,())++  ,decBitsN dBEBits8+  ,decBitsN dBEBits16+  ,decBitsN dBEBits32+  ,decBitsN dBEBits64   ,map trip [maxBound::Word16]   ,map trip [maxBound::Word32]   ,map trip [maxBound::Word64]@@ -248,7 +273,7 @@    -- Long LazyStrings can have internal sections shorter than 255    --,s (L.pack $ csb 600) (bsl s600)   ,[trip [1..100::Int16]]-  ,[trip unicodeText,trip unicodeTextUTF8T,trip unicodeTextUTF16T]+  ,[trip asciiStrT,trip "维护和平正",trip (T.pack "abc"),trip unicodeText,trip unicodeTextUTF8T,trip unicodeTextUTF16T]   ,[trip longBS,trip longLBS,trip longSBS]   ,[trip longSeq]   ,[trip mapV]@@ -301,6 +326,26 @@       s v e = [testCase (unwords ["flat raw",sshow v]) $ serRaw v @?= e]               --,testCase (unwords ["unflat raw",sshow v]) $ desRaw e @?= Right v] +      dec decOp v e = [testCase (unwords ["decode",sshow v]) $ unflatRawWith decOp (B.pack v) @?= Right e]++      decBitsN :: forall a. (Num a,FiniteBits a,Show a,Flat a) => (Int -> Get a) -> [TestTree]+      decBitsN dec = let s = finiteBitSize (undefined::a)+                     in [decBits_ dec v n pre | n <- [0 .. s], v <- [0::a ,1+2^(s - 2)+2^(s - 5) ,fromIntegral $ (2^s::Integer) - 1],pre <- [0,1,7]]++      -- why Flat a?+      decBits_ :: forall a. (FiniteBits a,Show a,Flat a) => (Int -> Get a) -> a -> Int -> Int -> TestTree+      decBits_ deco v n pre =+        let vs = B.pack . asBytes . fromBools $ replicate pre False ++ toBools (asBits v)+            len = B.length vs+            s = finiteBitSize (undefined::a)+            dec = do+              dropBits pre+              r <- deco n+              dropBits (len*8-n-pre)+              return r+            e = v `shiftR` (s - n)+        in testCase (unwords ["take",show n,"bits from",show v,"of size",show s,"with prefix",show pre]) $ unflatRawWith dec vs @?= Right e+       -- Aligned values unflat to the original value, modulo the added filler.       a v e = [testCase (unwords ["flat",sshow v]) $ ser v @?= e               ,testCase (unwords ["unflat",sshow v]) $ let Right v' = des e in v @?= v']@@ -320,10 +365,10 @@ uc = map ord "\x4444\x5555\x10001\xD800"  ser :: Flat a => a -> [Word8]-ser = L.unpack . flat+ser = B.unpack . flat  des :: Flat a => [Word8] -> Decoded a-des = unflat . L.pack+des = unflat  serRaw :: Flat a => a -> [Word8] -- serRaw = B.unpack . flatRaw
test/Test/Data/Values.hs view
@@ -179,11 +179,13 @@  unicodeStrT = ("unicodeStr",unicodeStr) -unicodeStr = longS uniSS+unicodeStr = notLongS uniSS  uniSS = "\x1F600\&\x1F600\&\x1F600\&I promessi sposi è un celebre romanzo storico di Alessandro Manzoni, ritenuto il più famoso e il più letto tra quelli scritti in lingua italiana[1].维护和平正义 开创美好未来——习近平主席在纪念中国人民抗日战争暨世界反法西斯战争胜利70周年大会上重要讲话在国际社会引起热烈反响"  longS =  take 1000000 . concat . repeat++notLongS =  take 1000 . concat . repeat  arr0 = ("[Bool]",map (odd . ord) $ unicodeStr :: [Bool])