packages feed

flat 0.4.4 → 0.5

raw patch · 47 files changed

+1333/−752 lines, 47 filesdep +list-tdep +timeitdep −quickcheck-instancesdep ~QuickCheckdep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: list-t, timeit

Dependencies removed: quickcheck-instances

Dependency ranges changed: QuickCheck, base, bytestring, hashable, semigroups

API changes (from Hackage documentation)

- Data.ZigZag: instance Data.ZigZag.ZigZag GHC.Integer.Type.Integer GHC.Natural.Natural
- Flat.Class: instance (Flat.Class.GDecode a, Flat.Class.GDecode b) => Flat.Class.GDecode (GHC.Generics.C1 m1 a GHC.Generics.:+: GHC.Generics.C1 m2 b)
- Flat.Class: instance (Flat.Class.GDecode a, Flat.Class.GDecode b) => Flat.Class.GDecode (a GHC.Generics.:*: b)
- Flat.Class: instance (Flat.Class.GDecodeSum a, Flat.Class.GDecodeSum b) => Flat.Class.GDecodeSum (a GHC.Generics.:+: b)
- Flat.Class: instance (Flat.Class.GDecodeSum n1, Flat.Class.GDecodeSum n2, Flat.Class.GDecodeSum n3, Flat.Class.GDecodeSum n4) => Flat.Class.GDecodeSum ((n1 GHC.Generics.:+: n2) GHC.Generics.:+: (n3 GHC.Generics.:+: n4))
- Flat.Class: instance (Flat.Class.GDecodeSum n1, Flat.Class.GDecodeSum n2, Flat.Class.GDecodeSum n3, Flat.Class.GDecodeSum n4, Flat.Class.GDecodeSum n5, Flat.Class.GDecodeSum n6, Flat.Class.GDecodeSum n7, Flat.Class.GDecodeSum n8) => Flat.Class.GDecodeSum (((n1 GHC.Generics.:+: n2) GHC.Generics.:+: (n3 GHC.Generics.:+: n4)) GHC.Generics.:+: ((n5 GHC.Generics.:+: n6) GHC.Generics.:+: (n7 GHC.Generics.:+: n8)))
- Flat.Class: instance (Flat.Class.GEncode a, Flat.Class.GEncode b) => Flat.Class.GEncode (a GHC.Generics.:*: b)
- Flat.Class: instance (Flat.Class.GEncodeSum a, Flat.Class.GEncodeSum b) => Flat.Class.GEncodeSum (a GHC.Generics.:+: b)
- Flat.Class: instance (Flat.Class.GSize a, Flat.Class.GSize b) => Flat.Class.GSize (a GHC.Generics.:*: b)
- Flat.Class: instance (Flat.Class.GSizeSum a, Flat.Class.GSizeSum b) => Flat.Class.GSizeSum (a GHC.Generics.:+: b)
- Flat.Class: instance (Flat.Class.NumConstructors (a GHC.Generics.:+: b) GHC.TypeNats.<= 512, Flat.Class.GDecodeSum (a GHC.Generics.:+: b)) => Flat.Class.GDecode (a GHC.Generics.:+: b)
- Flat.Class: instance (Flat.Class.NumConstructors (a GHC.Generics.:+: b) GHC.TypeNats.<= 512, Flat.Class.GEncodeSum (a GHC.Generics.:+: b)) => Flat.Class.GEncode (a GHC.Generics.:+: b)
- Flat.Class: instance Flat.Class.Flat a => Flat.Class.GDecode (GHC.Generics.K1 i a)
- Flat.Class: instance Flat.Class.Flat a => Flat.Class.GEncode (GHC.Generics.K1 i a)
- Flat.Class: instance Flat.Class.Flat a => Flat.Class.GSize (GHC.Generics.K1 i a)
- Flat.Class: instance Flat.Class.GDecode GHC.Generics.U1
- Flat.Class: instance Flat.Class.GDecode GHC.Generics.V1
- Flat.Class: instance Flat.Class.GDecode a => Flat.Class.GDecode (GHC.Generics.M1 i c a)
- Flat.Class: instance Flat.Class.GDecode a => Flat.Class.GDecodeSum (GHC.Generics.C1 c a)
- Flat.Class: instance Flat.Class.GEncode GHC.Generics.U1
- Flat.Class: instance Flat.Class.GEncode GHC.Generics.V1
- Flat.Class: instance Flat.Class.GEncode a => Flat.Class.GEncode (GHC.Generics.D1 i (GHC.Generics.C1 c a))
- Flat.Class: instance Flat.Class.GEncode a => Flat.Class.GEncodeSum (GHC.Generics.C1 c a)
- Flat.Class: instance Flat.Class.GEncode f => Flat.Class.GEncode (GHC.Generics.M1 i c f)
- Flat.Class: instance Flat.Class.GSize GHC.Generics.U1
- Flat.Class: instance Flat.Class.GSize GHC.Generics.V1
- Flat.Class: instance Flat.Class.GSize a => Flat.Class.GSizeSum (GHC.Generics.C1 c a)
- Flat.Class: instance Flat.Class.GSize f => Flat.Class.GSize (GHC.Generics.M1 i c f)
- Flat.Class: instance Flat.Class.GSizeSum (a GHC.Generics.:+: b) => Flat.Class.GSize (a GHC.Generics.:+: b)
- Flat.Decoder.Types: strictDecoder :: Get a -> ByteString -> Either DecodeException a
- Flat.Instances.Array: instance (Flat.Class.Flat i, Flat.Class.Flat e, GHC.Arr.Ix i) => Flat.Class.Flat (GHC.Arr.Array i e)
- Flat.Instances.Array: instance (Flat.Class.Flat i, Flat.Class.Flat e, GHC.Arr.Ix i, Data.Array.Base.IArray Data.Array.Base.UArray e) => Flat.Class.Flat (Data.Array.Base.UArray i e)
- Flat.Instances.Base: instance Flat.Class.Flat GHC.Integer.Type.Integer
- Flat.Instances.Base: instance Flat.Class.Flat GHC.Natural.Natural
- Flat.Instances.Base: instance Flat.Class.Flat [GHC.Types.Char]
- Flat.Instances.Base: instance Flat.Class.Flat a => Flat.Class.Flat (Data.Semigroup.Option a)
- Flat.Instances.DList: instance Flat.Class.Flat a => Flat.Class.Flat (Data.DList.DList a)
- Flat.Instances.Unordered: instance (Data.Hashable.Class.Hashable a, GHC.Classes.Eq a, Flat.Class.Flat a) => Flat.Class.Flat (Data.HashSet.Base.HashSet a)
- Flat.Instances.Unordered: instance (Data.Hashable.Class.Hashable k, GHC.Classes.Eq k, Flat.Class.Flat k, Flat.Class.Flat v) => Flat.Class.Flat (Data.HashMap.Base.HashMap k v)
+ Data.ZigZag: instance Data.ZigZag.ZigZag GHC.Num.Integer.Integer GHC.Num.Natural.Natural
+ Flat: BadOp :: String -> DecodeException
+ Flat.Bits: takeAllBits :: ByteString -> Bits
+ Flat.Bits: takeBits :: Int -> ByteString -> Bits
+ Flat.Class: SizeOf :: NumBits -> SizeOf a
+ Flat.Class: class GFlatDecode f
+ Flat.Class: class GFlatEncode f
+ Flat.Class: class GFlatSize f
+ Flat.Class: instance (Flat.Class.GFlatDecode a, Flat.Class.GFlatDecode b) => Flat.Class.GFlatDecode (GHC.Generics.C1 m1 a GHC.Generics.:+: GHC.Generics.C1 m2 b)
+ Flat.Class: instance (Flat.Class.GFlatDecode a, Flat.Class.GFlatDecode b) => Flat.Class.GFlatDecode (a GHC.Generics.:*: b)
+ Flat.Class: instance (Flat.Class.GFlatDecodeSum a, Flat.Class.GFlatDecodeSum b) => Flat.Class.GFlatDecodeSum (a GHC.Generics.:+: b)
+ Flat.Class: instance (Flat.Class.GFlatDecodeSum n1, Flat.Class.GFlatDecodeSum n2, Flat.Class.GFlatDecodeSum n3, Flat.Class.GFlatDecodeSum n4) => Flat.Class.GFlatDecodeSum ((n1 GHC.Generics.:+: n2) GHC.Generics.:+: (n3 GHC.Generics.:+: n4))
+ Flat.Class: instance (Flat.Class.GFlatDecodeSum n1, Flat.Class.GFlatDecodeSum n2, Flat.Class.GFlatDecodeSum n3, Flat.Class.GFlatDecodeSum n4, Flat.Class.GFlatDecodeSum n5, Flat.Class.GFlatDecodeSum n6, Flat.Class.GFlatDecodeSum n7, Flat.Class.GFlatDecodeSum n8) => Flat.Class.GFlatDecodeSum (((n1 GHC.Generics.:+: n2) GHC.Generics.:+: (n3 GHC.Generics.:+: n4)) GHC.Generics.:+: ((n5 GHC.Generics.:+: n6) GHC.Generics.:+: (n7 GHC.Generics.:+: n8)))
+ Flat.Class: instance (Flat.Class.GFlatEncode a, Flat.Class.GFlatEncode b) => Flat.Class.GFlatEncode (a GHC.Generics.:*: b)
+ Flat.Class: instance (Flat.Class.GFlatEncodeSum a, Flat.Class.GFlatEncodeSum b) => Flat.Class.GFlatEncodeSum (a GHC.Generics.:+: b)
+ Flat.Class: instance (Flat.Class.GFlatSize (GHC.Generics.Rep a), Flat.Class.GFlatDecode (GHC.Generics.Rep a)) => Flat.Class.Flat (Flat.Class.SizeOf a)
+ Flat.Class: instance (Flat.Class.GFlatSize a, Flat.Class.GFlatSize b) => Flat.Class.GFlatSize (a GHC.Generics.:*: b)
+ Flat.Class: instance (Flat.Class.GFlatSizeSum a, Flat.Class.GFlatSizeSum b) => Flat.Class.GFlatSizeSum (a GHC.Generics.:+: b)
+ Flat.Class: instance (Flat.Class.NumConstructors (a GHC.Generics.:+: b) Data.Type.Ord.<= 512, Flat.Class.GFlatDecodeSum (a GHC.Generics.:+: b)) => Flat.Class.GFlatDecode (a GHC.Generics.:+: b)
+ Flat.Class: instance (Flat.Class.NumConstructors (a GHC.Generics.:+: b) Data.Type.Ord.<= 512, Flat.Class.GFlatEncodeSum (a GHC.Generics.:+: b)) => Flat.Class.GFlatEncode (a GHC.Generics.:+: b)
+ Flat.Class: instance Flat.Class.Flat a => Flat.Class.GFlatDecode (GHC.Generics.K1 i a)
+ Flat.Class: instance Flat.Class.Flat a => Flat.Class.GFlatEncode (GHC.Generics.K1 i a)
+ Flat.Class: instance Flat.Class.Flat a => Flat.Class.GFlatSize (GHC.Generics.K1 i a)
+ Flat.Class: instance Flat.Class.GFlatDecode GHC.Generics.U1
+ Flat.Class: instance Flat.Class.GFlatDecode GHC.Generics.V1
+ Flat.Class: instance Flat.Class.GFlatDecode a => Flat.Class.GFlatDecode (GHC.Generics.M1 i c a)
+ Flat.Class: instance Flat.Class.GFlatDecode a => Flat.Class.GFlatDecodeSum (GHC.Generics.C1 c a)
+ Flat.Class: instance Flat.Class.GFlatEncode GHC.Generics.U1
+ Flat.Class: instance Flat.Class.GFlatEncode GHC.Generics.V1
+ Flat.Class: instance Flat.Class.GFlatEncode a => Flat.Class.GFlatEncode (GHC.Generics.D1 i (GHC.Generics.C1 c a))
+ Flat.Class: instance Flat.Class.GFlatEncode a => Flat.Class.GFlatEncodeSum (GHC.Generics.C1 c a)
+ Flat.Class: instance Flat.Class.GFlatEncode f => Flat.Class.GFlatEncode (GHC.Generics.M1 i c f)
+ Flat.Class: instance Flat.Class.GFlatSize GHC.Generics.U1
+ Flat.Class: instance Flat.Class.GFlatSize GHC.Generics.V1
+ Flat.Class: instance Flat.Class.GFlatSize a => Flat.Class.GFlatSizeSum (GHC.Generics.C1 c a)
+ Flat.Class: instance Flat.Class.GFlatSize f => Flat.Class.GFlatSize (GHC.Generics.M1 i c f)
+ Flat.Class: instance Flat.Class.GFlatSizeSum (a GHC.Generics.:+: b) => Flat.Class.GFlatSize (a GHC.Generics.:+: b)
+ Flat.Class: instance GHC.Show.Show (Flat.Class.SizeOf a)
+ Flat.Class: newtype SizeOf a
+ Flat.Decoder: BadOp :: String -> DecodeException
+ Flat.Decoder: listTDecoder :: Get a -> ByteString -> IO (ListT IO a)
+ Flat.Decoder.Run: listTDecoder :: Get a -> ByteString -> IO (ListT IO a)
+ Flat.Decoder.Run: strictDecoder :: Get a -> ByteString -> Either DecodeException a
+ Flat.Decoder.Types: BadOp :: String -> DecodeException
+ Flat.Decoder.Types: badOp :: String -> IO a
+ Flat.Encoder.Prim: updateWord8 :: Word8 -> S -> Prim
+ Flat.Encoder.Strict: encodingAppend :: Encoding -> Encoding -> Encoding
+ Flat.Encoder.Strict: numEncodedBits :: Int -> Encoding -> NumBits
+ Flat.Encoder.Strict: sizeListWith :: (Foldable t1, Num t2) => (t3 -> t2 -> t2) -> t1 t3 -> t2 -> t2
+ Flat.Encoder.Strict: strictEncoderPartial :: Int -> Encoding -> (ByteString, NumBits)
+ Flat.Filler: preAlignedDecoder :: Get b -> Get b
+ Flat.Instances.Array: instance (Flat.Class.Flat i, Flat.Class.Flat e, GHC.Ix.Ix i) => Flat.Class.Flat (GHC.Arr.Array i e)
+ Flat.Instances.Array: instance (Flat.Class.Flat i, Flat.Class.Flat e, GHC.Ix.Ix i, Data.Array.Base.IArray Data.Array.Base.UArray e) => Flat.Class.Flat (Data.Array.Base.UArray i e)
+ Flat.Instances.Base: instance Flat.Class.Flat GHC.Num.Integer.Integer
+ Flat.Instances.Base: instance Flat.Class.Flat GHC.Num.Natural.Natural
+ Flat.Instances.DList: instance Flat.Class.Flat a => Flat.Class.Flat (Data.DList.Internal.DList a)
+ Flat.Instances.Extra: instance Flat.Class.Flat [GHC.Types.Char]
+ Flat.Instances.Test: encBits :: NumBits -> Encoding -> Bits
+ Flat.Instances.Unordered: instance (Data.Hashable.Class.Hashable a, GHC.Classes.Eq a, Flat.Class.Flat a) => Flat.Class.Flat (Data.HashSet.Internal.HashSet a)
+ Flat.Instances.Unordered: instance (Data.Hashable.Class.Hashable k, GHC.Classes.Eq k, Flat.Class.Flat k, Flat.Class.Flat v) => Flat.Class.Flat (Data.HashMap.Internal.HashMap k v)
+ Flat.Repr: Repr :: ByteString -> Repr a
+ Flat.Repr: [repr] :: Repr a -> ByteString
+ Flat.Repr: instance Flat.Class.Flat a => Flat.Class.Flat (Flat.Repr.Repr a)
+ Flat.Repr: instance GHC.Show.Show (Flat.Repr.Repr a)
+ Flat.Repr: newtype Repr a
+ Flat.Repr: unrepr :: Flat a => Repr a -> a
- Data.FloatCast: runST :: () => (forall s. () => ST s a) -> a
+ Data.FloatCast: runST :: (forall s. () => ST s a) -> a
- Flat.Class: decode :: (Flat a, Generic a, GDecode (Rep a)) => Get a
+ Flat.Class: decode :: (Flat a, Generic a, GFlatDecode (Rep a)) => Get a
- Flat.Class: encode :: (Flat a, Generic a, GEncode (Rep a)) => a -> Encoding
+ Flat.Class: encode :: (Flat a, Generic a, GFlatEncode (Rep a)) => a -> Encoding
- Flat.Class: size :: (Flat a, Generic a, GSize (Rep a)) => a -> NumBits -> NumBits
+ Flat.Class: size :: (Flat a, Generic a, GFlatSize (Rep a)) => a -> NumBits -> NumBits
- Flat.Filler: FillerBit :: Filler -> Filler
+ Flat.Filler: FillerBit :: !Filler -> Filler
- Flat.Memory: minusPtr :: () => Ptr a -> Ptr b -> Int
+ Flat.Memory: minusPtr :: Ptr a -> Ptr b -> Int

Files

CHANGELOG view
@@ -1,5 +1,17 @@ Significant and compatibility-breaking changes. +Version 0.5:+    - Compatibility with ghc 9.0.2 & 9.2.4 & 9.4.2+    - Compatibility with text-2.0+    - Fixed https://github.com/Quid2/flat/issues/23 that could cause an encoding failure for non byte aligned Arrays +    - Fixed https://github.com/Quid2/flat/pull/26 that could cause the decoder to read beyond the end of the decoding buffer (causing a SEGFAULT on ghcjs)+    - Merged https://github.com/Quid2/flat/pull/22 - fails correctly on invalid UTF-8 text +    - Added a few ways to partially or incrementally decode values, see Flat.Repr and Flat.Decoder.Run.listTDecoder+    - Moved strictDecoder from Flat.Decoder.Types to Flat.Decoder+    - Removed Flat instance for Semigroup.Option from Flat.Instances.Base+    - Moved overlapping/specialised Flat instance for [Char] to Flat.Instances.Extra+    - Added a few extra functions+ Version 0.4.4: 	- Added instances for Identity, Monoid.Dual/All/Any/Sum/Product/Alt, Semigroup.Min/Max/First/Last/Option  
README.md view
@@ -1,21 +1,66 @@ -[![Build Status](https://travis-ci.org/Quid2/flat.svg?branch=master)](https://travis-ci.org/Quid2/flat)+![Build Status](https://github.com/Quid2/flat/actions/workflows/haskell-ci.yml/badge.svg)+ [![Hackage version](https://img.shields.io/hackage/v/flat.svg)](http://hackage.haskell.org/package/flat)-[![Stackage Nightly](http://stackage.org/package/flat/badge/nightly)](http://stackage.org/nightly/package/model)-[![Stackage LTS](http://stackage.org/package/flat/badge/lts)](http://stackage.org/lts/package/model) +[![Stackage LTS 16](http://stackage.org/package/flat/badge/lts-16)](http://stackage.org/lts/package/flat)+[![Stackage LTS 18](http://stackage.org/package/flat/badge/lts-18)](http://stackage.org/lts/package/flat)+[![Stackage LTS 19](http://stackage.org/package/flat/badge/lts-19)](http://stackage.org/lts/package/flat)+[![Stackage Nightly](http://stackage.org/package/flat/badge/nightly)](http://stackage.org/nightly/package/flat) -Haskell implementation of [Flat](http://quid2.org/docs/Flat.pdf), a principled, language-independent and efficient binary data format.+Haskell implementation of [Flat](http://quid2.org/docs/Flat.pdf), a principled, portable and compact binary data format ([specs](http://quid2.org)). ++### How To Use It For Fun and Profit++```haskell+{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}+```++```haskell+import Flat+```++++```haskell+data Direction = North | South | Center | East | West deriving (Show,Generic,Flat)+```++Use **flat** to encode: ++```haskell+flat $ [North,South]+-> "\149"+```+++and **unflat** to decode:++```haskell+unflat (flat $ [North,South]) :: Decoded [Direction]+-> Right [ North , South ]+```+++And thanks to Flat's bit-encoding, this little list fits in a single byte (rather than the five that would be required by a traditional byte encoding):++```haskell+flatBits $ [North,South]+-> "10010101"+```+++ ### Performance  For some hard data, see this [comparison of the major haskell serialisation libraries](https://github.com/haskell-perf/serialization).  Briefly:- * Transfer time (serialisation time + transport time on the network + deserialisation at the receiving end): `flat` is usually faster for all but the highest network speeds  * Size: `flat` produces significantly smaller binaries than all other libraries (3/4 times usually)- * Serialization: `store`, `persist` and `flat` are faster- * Deserialization: `store`, `flat`, `persist` and `cereal` are faster+ * Serialization time: `store`, `persist` and `flat` are faster+ * Deserialization time: `store`, `flat`, `persist` and `cereal` are faster+ * Transfer time (serialisation time + transport time on the network + deserialisation at the receiving end): `flat` is usually faster for all but the highest network speeds  ### Documentation @@ -25,22 +70,57 @@  * [Flat Format Specification](http://quid2.org/docs/Flat.pdf) + ### Installation  Get the latest stable version from [hackage](https://hackage.haskell.org/package/flat). -### Other Stuff You Might Like+### Compatibility -#### [ZM - Language independent, reproducible, absolute types](https://github.com/Quid2/zm)+Tested with: -To decode `flat` encoded data you need to know the type of the serialised data.+* [GHC](https://www.haskell.org/ghc/) 7.10.3 to 9.4.2 (x64) -This is ok for applications that do not require long-term storage and that do not operate in open distributed systems. -For those who do, you might want to supplement `flat` with something like [ZM](https://github.com/Quid2/zm).+* [GHCJS](https://github.com/ghcjs/ghcjs) -#### Ports for other languages+  * Note: versions of `flat` prior to 0.33 encode `Double` values incorrectly when they are not aligned with a byte boundary. -[TypeScript-JavaScript](https://github.com/Quid2/ts) and [Purescript](https://www.purescript.org/) ports are under development. ++### Known Bugs and Infelicities++* Data types with more than 512 constructors are currently unsupported++* Longish compilation times++  * `flat` relies more than other serialisation libraries on extensive inlining for its good performance, this unfortunately leads to longer compilation times. ++    If you have many data types or very large ones this might become an issue.++    A couple of good practices that will eliminate or mitigate this problem are:++      * During development, turn optimisations off (`stack --fast` or `-O0` in the cabal file).++      * Keep your serialisation code in a separate module or modules.++* See also the [full list of open issues](https://github.com/Quid2/flat/issues).++### Ports for other languages++[Rust](https://www.rust-lang.org/) and [TypeScript-JavaScript](https://github.com/Quid2/ts) ports are under development.++ Get in touch if you would like to help porting `flat` to other languages.++### Acknowledgements++`flat` reuses ideas and readapts code from various packages, mainly: `store`, `binary-bits` and `binary` and includes bug fixes from a number of contributors.++### Other Stuff You Might Like++To decode `flat` encoded data you need to know the type of the serialised data.++This is ok for applications that do not require long-term storage and that do not operate in open distributed systems.++For those who do, you might want to supplement `flat` with [ZM - Language independent, reproducible, absolute types](https://github.com/Quid2/zm).
flat.cabal view
@@ -1,25 +1,19 @@ cabal-version:      >=1.10 name:               flat-version:            0.4.4+version:            0.5+homepage:           http://quid2.org+synopsis:           Principled and efficient bit-oriented binary serialization.+description:        Reference implementation of `flat`, a principled and efficient binary serialization format.+category:           Data,Parsing,Serialization license:            BSD3 license-file:       LICENSE-copyright:          Copyright: (c) 2016-2020 Pasqualino `Titto` Assini+copyright:          Copyright: (c) 2016-2022 Pasqualino `Titto` Assini maintainer:         tittoassini@gmail.com author:             Pasqualino `Titto` Assini-tested-with:-  GHC ==7.10.3 || ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.3--homepage:           http://quid2.org-synopsis:           Principled and efficient bit-oriented binary serialization.-description:-  Reference implementation of `flat`, a principled and efficient binary serialization format.--category:           Data,Parsing,Serialization+tested-with:        GHC ==7.10.3 || ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.2 build-type:         Simple extra-source-files:   stack.yaml-  stack-6.35.yaml-  stack-9.21.yaml   README.md   CHANGELOG @@ -37,6 +31,7 @@     Flat.Class     Flat.Decoder     Flat.Decoder.Prim+    Flat.Decoder.Run     Flat.Decoder.Strict     Flat.Decoder.Types     Flat.Encoder@@ -52,6 +47,7 @@     Flat.Instances.ByteString     Flat.Instances.Containers     Flat.Instances.DList+    Flat.Instances.Extra     Flat.Instances.Mono     Flat.Instances.Test     Flat.Instances.Text@@ -60,6 +56,7 @@     Flat.Instances.Vector     Flat.Memory     Flat.Run+    Flat.Repr     Flat.Tutorial     Flat.Types @@ -87,8 +84,10 @@   ghc-options:     -Wall -O2 -funbox-strict-fields -fno-warn-orphans     -fno-warn-name-shadowing+    -- -Werror -  --  -Werror+    -- Stan options+    -- -fwrite-ide-info -hiedir=.hie    if impl(eta -any)     build-depends:@@ -121,30 +120,60 @@       , deepseq               >=1.4       , dlist                 >=0.6       , ghc-prim-      , hashable       , mono-traversable       , pretty                >=1.1.2       , primitive-      , semigroups       , text       , unordered-containers       , vector+      , list-t > 1+  +  if impl(ghc <8)+    build-depends: +      semigroups < 0.19+      , hashable              >=1.2.4.0  && <=1.2.7.0+  else +    build-depends: hashable >= 1.4.0.2 --- , base                  >=4.8.2.0 && <5--- if impl(ghc <8.2)---   build-depends: semigroups >=0.8.4 && <0.17 +-- test-suite ref+--   type:             exitcode-stdio-1.0+--   main-is:          Reference.hs+--   hs-source-dirs:   test+--   other-modules:+--     Test.Data+--     Test.Data.Arbitrary+--     Test.Data.Flat+--     Test.Data.Values+--     Test.Data2+--     Test.Data2.Flat+--     Test.E+--     Test.E.Arbitrary+--     Test.E.Flat++--   default-language: Haskell2010+--   build-depends:+--       base+--     , flat+--     , zm+--     , ghc-prim+--     , quickcheck-text+--     , tasty-hunit+--     , tasty-quickcheck+--     , text++ test-suite spec   type:             exitcode-stdio-1.0   main-is:          Spec.hs   cpp-options:      -DLIST_BIT -DTEST_DECBITS -  if impl(ghc <8.6)-    cpp-options: -DENUM_LARGE+  -- if impl(ghc <8.6)+  cpp-options: -DENUM_LARGE     -- -DETA_VERSION -Dghcjs_HOST_OS -  -- ghc-options: -O1 +  ghc-options: -O0   if impl(ghc >8)     ghc-options:       -Wno-unused-top-binds -Wno-type-defaults -Wno-missing-signatures@@ -172,7 +201,7 @@     , text    if impl(ghc <8)-    build-depends: semigroups+    build-depends: semigroups < 0.19    if impl(eta -any)     build-depends:@@ -195,12 +224,13 @@       , deepseq       , filepath       , mono-traversable-      , QuickCheck       , tasty       , text+      , QuickCheck >= 2.14.2  --- dynamic doctests and generation of static doctests--- Usable only with recent versions of ghc (no ghcjs or eta)+-- -- dynamic doctests and generation of static doctests+-- -- Usable only with recent versions of ghc (no ghcjs or eta)+ -- test-suite doc --   type:             exitcode-stdio-1.0 --   main-is:          DocSpec.hs@@ -212,8 +242,10 @@ --     , doctest    ==0.16.3.1 --     , filemanip  >=0.3.6.3 --     , text+--     , QuickCheck >= 2.14.2   -- static doctests (faster, useful for test coverage and to test ghcjs and eta)+ test-suite doc-static   type:             exitcode-stdio-1.0   main-is:          DocTests.hs@@ -225,6 +257,7 @@     DocTest.Flat.Bits     DocTest.Flat.Decoder.Prim     DocTest.Flat.Endian+    DocTest.Flat.Repr     DocTest.Flat.Instances.Array     DocTest.Flat.Instances.Base     DocTest.Flat.Instances.ByteString@@ -235,6 +268,8 @@     DocTest.Flat.Instances.Unordered     DocTest.Flat.Instances.Vector     DocTest.Flat.Tutorial+    DocTest.Flat.Encoder.Prim+    DocTest.Flat.Instances.Extra    default-language: Haskell2010   build-depends:@@ -245,126 +280,42 @@     , dlist     , flat     , pretty-    , quickcheck-instances     , tasty     , tasty-hunit     , tasty-quickcheck     , text     , unordered-containers     , vector+    , QuickCheck >= 2.14.2  -  -- >=0.3.22-  --, QuickCheck >= 2.13.2 && < 3-  --, hashable >= 1.2.6.1 && < 1.4   if impl(ghc <8)-    build-depends: semigroups+    build-depends: semigroups <0.19 ---ghc-options: -Wno-unused-top-binds -Wno-type-defaults+-- Test for Flat.Repr+test-suite repr+  type:             exitcode-stdio-1.0+  main-is:          FlatRepr.hs+  hs-source-dirs:   test+  default-language: Haskell2010+  build-depends:+      base+    , bytestring+    , flat+    , timeit+    , list-t --- Additional development time tests and benchmarks--- test-suite core---   type:             exitcode-stdio-1.0---   main-is:          Core.hs---   hs-source-dirs:   test---   default-language: Haskell2010---   ghc-options:      -O2---   other-modules:---   other-modules:---     Test.Data---     Test.Data.Values---     Test.Data2---     Test.Data2.Flat---     Test.E---     Test.E.Flat---     Test.Data.Flat---   build-depends:---       base---     , benchpress---     , bytestring---     , containers---     , deepseq---     , flat---     , text---     ,inspection-testing+  ghc-options: -rtsopts --- executable listTest---   main-is:          ListTest.hs+-- test-suite ghcjs-cons+--   type:             exitcode-stdio-1.0+--   main-is:          Cons.hs --   hs-source-dirs:   test --   default-language: Haskell2010 --   build-depends: --       base --     , flat---     , text---     , time---- benchmark microBench---   type:             exitcode-stdio-1.0---   main-is:          Micro.hs---   hs-source-dirs:   benchmarks test---   other-modules:---     Common---     Test.Data---     Test.Data.Values---     Test.Data2---     Test.Data2.Flat---     Test.E---     Test.E.Flat---     Test.Data.Flat----   default-language: Haskell2010---   build-depends:---       base---     , benchpress --     , bytestring---     , containers---     , deepseq---     , flat---     , text---- benchmark miniBench---   type:             exitcode-stdio-1.0---   main-is:          Mini.hs---   hs-source-dirs:   benchmarks test---   other-modules:---     Report---     Test.Data---     Test.Data.Values---     Test.Data2---     Test.Data2.Flat---     Test.E---     Test.E.Flat---     Test.Data.Flat----   default-language: Haskell2010---   ghc-options:      -O2---   build-depends:---       base---     , flat---     , text+--     , jsaddle ---   if impl(eta -any)---     build-depends:---         bytestring         ==0.10.8.2---       , containers         ==0.5.9.1---       , criterion          ==1.5.1.0---       , deepseq            ==1.4.3.0---       , directory          ==1.3.1.0---       , filepath           ==1.4.1.1---       , mono-traversable   ==1.0.1---       , process            ==1.6.2.0---       , statistics         ==0.14.0.2---       , text               ==1.2.3.0---       , vector-algorithms  ==0.7.0.1+--   ghc-options: -rtsopts ---   else---     build-depends:---         bytestring---       , containers---       , criterion---       , deepseq---       , directory---       , filepath---       , mono-traversable---       , process---       , statistics---       , text
src/Data/FloatCast.hs view
@@ -36,9 +36,11 @@   --- | Reinterpret-casts a `Word32` to a `Float`.-{-|++{- | Reinterpret-casts a `Word32` to a `Float`.+ prop> \f -> wordToFloat (floatToWord f ) == f++++ OK, passed 100 tests.  >>> floatToWord (-0.15625) 3189768192@@ -62,9 +64,11 @@ -- >>> import Numeric (showHex) -- >>> import Data.Word --- | Reinterpret-casts a `Double` to a `Word64`. {-|+Reinterpret-casts a `Double` to a `Word64`.+ prop> \f -> wordToDouble (doubleToWord f ) == f++++ OK, passed 100 tests.  >>> showHex (doubleToWord 1.0000000000000004) "" "3ff0000000000002"@@ -89,10 +93,9 @@ wordToDouble x = runST (cast x) -- wordToDouble x = runST (cast $ fix64 x) -{- | ->>> runST (cast (0xF0F1F2F3F4F5F6F7::Word64)) == (0xF0F1F2F3F4F5F6F7::Word64)-True--}+-- | +-- >>> runST (cast (0xF0F1F2F3F4F5F6F7::Word64)) == (0xF0F1F2F3F4F5F6F7::Word64)+-- True cast   :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) => a -> ST s b cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
src/Data/ZigZag.hs view
@@ -1,35 +1,36 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DefaultSignatures      #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE ScopedTypeVariables    #-}+ -- |<https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba ZigZag encoding> of signed integrals.-module Data.ZigZag-  ( ZigZag(..)-  )-where+module Data.ZigZag (ZigZag(..)) where -import           Data.Word-import           Data.Int-import           Data.Bits-import           Numeric.Natural+import           Data.Bits       (Bits (shiftL, shiftR, xor, (.&.)),+                                  FiniteBits (finiteBitSize))+import           Data.Int        (Int16, Int32, Int64, Int8)+import           Data.Word       (Word16, Word32, Word64, Word8)+import           Numeric.Natural (Natural)  -- $setup -- >>> :set -XNegativeLiterals -XScopedTypeVariables -XFlexibleContexts -- >>> import Data.Word -- >>> import Data.Int -- >>> import Numeric.Natural--- >>> import Test.QuickCheck.Instances.Natural+-- >>> import Test.QuickCheck.Arbitrary+-- >>> instance Arbitrary Natural where arbitrary = arbitrarySizedNatural; shrink    = shrinkIntegral  {-| Convert between a signed integral and the corresponding ZigZag encoded unsigned integral (e.g. between Int8 and Word8 or Integral and Natural). -Invalid conversions produce a type error:+Allow conversion only between compatible types, invalid conversions produce a type error: -zigZag (-1::Int64) :: Word32 +@+zigZag (-1::Int64) :: Word32 ... ... Couldn't match type ... ...-+@ >>> zigZag (0::Int8) 0 @@ -64,41 +65,63 @@ [0,-1,1,-2,2,-3,3]  prop> \(f::Integer) -> zagZig (zigZag f) == f++++ OK, passed 100 tests.  prop> \(f::Natural) -> zigZag (zagZig f) == f++++ OK, passed 100 tests.  prop> \(f::Int8) -> zagZig (zigZag f) == f++++ OK, passed 100 tests.+ prop> \(f::Word8) -> zigZag (zagZig f) == f++++ OK, passed 100 tests.+ prop> \(s::Int8) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer))++++ OK, passed 100 tests.+ prop> \(u::Word8) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural))++++ OK, passed 100 tests.  prop> \(f::Int64) -> zagZig (zigZag f) == f++++ OK, passed 100 tests.+ prop> \(f::Word64) -> zigZag (zagZig f) == f++++ OK, passed 100 tests.+ prop> \(s::Int64) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer))++++ OK, passed 100 tests.+ prop> \(u::Word64) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural))++++ OK, passed 100 tests. -}---- Allow conversion only between compatible types-class (Integral signed,Integral unsigned) => ZigZag signed unsigned | unsigned -> signed,signed -> unsigned where+class (Integral signed, Integral unsigned)+  => ZigZag signed unsigned | unsigned -> signed, signed -> unsigned where   zigZag :: signed -> unsigned   default zigZag :: FiniteBits signed => signed -> unsigned-  zigZag s = fromIntegral ((s `shiftL` 1) `xor` (s `shiftR` (finiteBitSize s - 1)))-  {-# INLINE zigZag #-}+  zigZag s = fromIntegral+    ((s `shiftL` 1) `xor` (s `shiftR` (finiteBitSize s - 1))) +  {-# INLINE zigZag #-}   zagZig :: unsigned -> signed   default zagZig :: (Bits unsigned) => unsigned -> signed-  zagZig u = fromIntegral ((u `shiftR` 1) `xor` (negate (u .&. 1)))+  zagZig u = fromIntegral ((u `shiftR` 1) `xor` negate (u .&. 1))    -- default zagZig :: (Bits signed) => unsigned -> signed   -- zagZig u = let (s::signed) = fromIntegral u in ((s `shiftR` 1) `xor` (negate (s .&. 1)))   {-# INLINE zagZig #-}  instance ZigZag Int8 Word8+ instance ZigZag Int16 Word16+ instance ZigZag Int32 Word32+ instance ZigZag Int64 Word64+ instance ZigZag Integer Natural where-  zigZag x | x >= 0    = fromIntegral $ x `shiftL` 1-           | otherwise = fromIntegral $ negate (x `shiftL` 1) - 1-  zagZig u =-    let s = fromIntegral u in ((s `shiftR` 1) `xor` (negate (s .&. 1)))+  zigZag x+    | x >= 0 = fromIntegral $ x `shiftL` 1+    | otherwise = fromIntegral $ negate (x `shiftL` 1) - 1++  zagZig u = let s = fromIntegral u+             in ((s `shiftR` 1) `xor` negate (s .&. 1))
src/Flat/Bits.hs view
@@ -1,29 +1,34 @@ {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE RankNTypes           #-} {-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TypeSynonymInstances #-} + -- |Utilities to represent and display bit sequences-module Flat.Bits-  ( Bits-  , toBools-  , fromBools-  , bits-  , paddedBits-  , asBytes-  , asBits-  )-where+module Flat.Bits (+    Bits,+    toBools,+    fromBools,+    bits,+    paddedBits,+    asBytes,+    asBits,+    takeBits,+    takeAllBits,+) where+-- TODO: AsBits Class? -import           Data.Bits               hiding ( Bits )-import qualified Data.ByteString               as B-import           Flat.Class-import           Flat.Decoder-import           Flat.Filler-import           Flat.Run-import qualified Data.Vector.Unboxed           as V-import           Data.Word-import           Text.PrettyPrint.HughesPJClass+import           Data.Bits                      (FiniteBits (finiteBitSize),+                                                 testBit)+import qualified Data.ByteString                as B+import qualified Data.Vector.Unboxed            as V+import           Data.Word                      (Word8)+import           Flat.Class                     (Flat)+import           Flat.Decoder                   (Decoded)+import           Flat.Filler                    (PostAligned (PostAligned),+                                                 fillerLength)+import           Flat.Run                       (flat, unflatRaw)+import           Text.PrettyPrint.HughesPJClass (Doc, Pretty (pPrint), hsep,+                                                 text)  -- |A sequence of bits type Bits = V.Vector Bool@@ -34,37 +39,43 @@ fromBools :: [Bool] -> Bits fromBools = V.fromList --- $setup--- >>> import Data.Word--- >>> import Flat.Instances.Base--- >>> import Flat.Instances.Test+{- $setup+>>> import Data.Word+>>> import Flat.Instances.Base+>>> import Flat.Instances.Test(tst,prettyShow)+-}  {- |The sequence of bits corresponding to the serialization of the passed value (without any final byte padding)  >>> bits True [True] -}-bits :: forall a . Flat a => a -> Bits+bits :: forall a. Flat a => a -> Bits bits v =-  let lbs                     = flat v-      Right (PostAligned _ f) = unflatRaw lbs :: Decoded (PostAligned a)-  in  takeBits (8 * B.length lbs - fillerLength f) lbs+    let lbs = flat v+    in case unflatRaw lbs :: Decoded (PostAligned a) of +            Right (PostAligned _ f) -> takeBits (8 * B.length lbs - fillerLength f) lbs+            Left _ -> error "incorrect coding or decoding, please inform the maintainer of this package"  {- |The sequence of bits corresponding to the byte-padded serialization of the passed value  >>> paddedBits True [True,False,False,False,False,False,False,True] -}-paddedBits :: forall a . Flat a => a -> Bits-paddedBits v = let lbs = flat v in takeBits (8 * B.length lbs) lbs+paddedBits :: forall a. Flat a => a -> Bits+paddedBits v = let lbs = flat v in takeAllBits lbs +takeAllBits :: B.ByteString -> Bits+takeAllBits lbs= takeBits (8 * B.length lbs) lbs+ 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)-  )+takeBits numBits lbs =+    V.generate+        (fromIntegral numBits)+        ( \n ->+            let (bb, b) = n `divMod` 8+             in testBit (B.index lbs (fromIntegral bb)) (7 - b)+        )  {- |Convert an integral value to its equivalent bit representation @@ -75,7 +86,7 @@ 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 $ asBits (256+3::Word16) [1,3] -}@@ -84,8 +95,7 @@  -- |Convert to the corresponding value (most significant bit first) byteVal :: [Bool] -> Word8-byteVal = sum . map (\(e, b) -> if b then e else 0) . zip-  [ 2 ^ n | n <- [7 :: Int, 6 .. 0] ]+byteVal = sum . zipWith (\ e b -> (if b then e else 0)) ([2 ^ n | n <- [7 :: Int, 6 .. 0]])  -- |Split a list in groups of 8 elements or less bytes :: [t] -> [[t]]@@ -97,9 +107,8 @@ "00000001 00000011" -} instance Pretty Bits where-  pPrint = hsep . map prettyBits . bytes . V.toList+    pPrint = hsep . map prettyBits . bytes . V.toList  prettyBits :: Foldable t => t Bool -> Doc prettyBits l =-  text . take (length l) . concatMap (\b -> if b then "1" else "0") $ l-+    text . take (length l) . concatMap (\b -> if b then "1" else "0") $ l
src/Flat/Class.hs view
@@ -5,14 +5,12 @@ {-# LANGUAGE DefaultSignatures         #-} {-# LANGUAGE FlexibleContexts          #-} {-# LANGUAGE FlexibleInstances         #-}-{-# LANGUAGE KindSignatures            #-} {-# LANGUAGE MultiParamTypeClasses     #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE ScopedTypeVariables       #-} {-# LANGUAGE Trustworthy               #-} {-# LANGUAGE TypeFamilies              #-} {-# LANGUAGE TypeOperators             #-}-{-# LANGUAGE TypeSynonymInstances      #-} {-# LANGUAGE UndecidableInstances      #-}  -- |Generics-based generation of Flat instances@@ -22,17 +20,31 @@     Flat(..)   , getSize   , module GHC.Generics+  , GFlatEncode,GFlatDecode,GFlatSize+  , SizeOf(..)   ) where -import           Data.Bits-import           Flat.Decoder-import           Flat.Encoder-import           Data.Word+import           Data.Bits          (Bits (unsafeShiftL, (.|.)))+import           Data.Word          (Word16)+import           Flat.Decoder.Prim  (ConsState (..), consBits, consBool,+                                     consClose, consOpen, dBool)+import           Flat.Decoder.Types (Get)+import           Flat.Encoder       (Encoding, NumBits, eBits16, mempty)+import           GHC.Base           (Any) import           GHC.Generics-import           GHC.TypeLits-import           Prelude           hiding (mempty)--- import Data.Proxy+import           GHC.TypeLits       (Nat, type (+), type (<=))+import           Prelude            hiding (mempty)++#if MIN_VERSION_base(4,9,0)+import           Data.Kind+#endif++#if ! MIN_VERSION_base(4,11,0)+import           Data.Semigroup     ((<>))+#endif++ -- External and Internal inlining #define INL 2 -- Internal inlining@@ -41,7 +53,7 @@ -- #define INL 0  #if INL == 1-import           GHC.Exts          (inline)+import           GHC.Exts           (inline) #endif  -- import           Data.Proxy@@ -50,23 +62,32 @@ getSize :: Flat a => a -> NumBits getSize a = size a 0 --- |Class of types that can be encoded/decoded+{-| Class of types that can be encoded/decoded++Encoding a value involves three steps:++* calculate the maximum size of the serialised value, using `size`++* preallocate a buffer of the required size++* encode the value in the buffer, using `encode`+-} class Flat a where     -- |Return the encoding corrresponding to the value     encode :: a -> Encoding-    default encode :: (Generic a, GEncode (Rep a)) => a -> Encoding+    default encode :: (Generic a, GFlatEncode (Rep a)) => a -> Encoding     encode = gencode . from      -- |Decode a value     decode :: Get a-    default decode :: (Generic a, GDecode (Rep a)) => Get a+    default decode :: (Generic a, GFlatDecode (Rep a)) => Get a     decode = to `fmap` gget      -- |Add maximum size in bits of the value to the total count-    -- -    --  Used to calculated maximum buffer size before encoding +    --+    --  Used to calculated maximum buffer size before encoding     size :: a -> NumBits -> NumBits-    default size :: (Generic a, GSize (Rep a)) => a -> NumBits -> NumBits+    default size :: (Generic a, GFlatSize (Rep a)) => a -> NumBits -> NumBits     size !x !n = gsize n $ from x  #if INL>=2@@ -82,29 +103,44 @@     {-# NOINLINE encode #-} #endif +-- | Skip a value, return its size in bits+skip :: forall a. (GFlatSize (Rep a),GFlatDecode (Rep a)) => Get (SizeOf a)+skip = SizeOf . (gsize 0 :: Rep a Any -> NumBits) <$> (gget :: Get (Rep a Any))+{-# INLINE skip #-}++-- | Decode to the size in bits of a value rather than to the value itself (see "Flat.Repr")+newtype SizeOf a = SizeOf NumBits deriving Show++instance (GFlatSize (Rep a),GFlatDecode (Rep a)) => Flat (SizeOf a) where+    size = error "unused"+    encode = error "unused"++    decode = skip++ -- |Generic Encoder-class GEncode f where gencode :: f a -> Encoding+class GFlatEncode f where gencode :: f a -> Encoding -instance {-# OVERLAPPABLE #-} GEncode f => GEncode (M1 i c f) where+instance {-# OVERLAPPABLE #-} GFlatEncode f => GFlatEncode (M1 i c f) where       gencode = gencode . unM1       {-# INLINE gencode #-}    -- Special case, single constructor datatype-instance {-# OVERLAPPING #-} GEncode a => GEncode (D1 i (C1 c a)) where+instance {-# OVERLAPPING #-} GFlatEncode a => GFlatEncode (D1 i (C1 c a)) where       gencode = gencode . unM1 . unM1       {-# INLINE gencode #-}    -- Type without constructors-instance GEncode V1 where+instance GFlatEncode V1 where       gencode = unused       {-# INLINE gencode #-}    -- Constructor without arguments-instance GEncode U1 where+instance GFlatEncode U1 where       gencode U1 = mempty       {-# INLINE gencode #-} -instance Flat a => GEncode (K1 i a) where+instance Flat a => GFlatEncode (K1 i a) where       {-# INLINE gencode #-} #if INL == 1       gencode x = inline encode (unK1 x)@@ -112,56 +148,56 @@       gencode = encode . unK1 #endif -instance (GEncode a, GEncode b) => GEncode (a :*: b) where+instance (GFlatEncode a, GFlatEncode b) => GFlatEncode (a :*: b) where       --gencode (!x :*: (!y)) = gencode x <++> gencode y       gencode (x :*: y) = gencode x <> gencode y       {-# INLINE gencode #-} -instance (NumConstructors (a :+: b) <= 512,GEncodeSum (a :+: b)) => GEncode (a :+: b) where--- instance (GEncodeSum (a :+: b)) => GEncode (a :+: b) where+instance (NumConstructors (a :+: b) <= 512,GFlatEncodeSum (a :+: b)) => GFlatEncode (a :+: b) where+-- instance (GFlatEncodeSum (a :+: b)) => GFlatEncode (a :+: b) where       gencode = gencodeSum 0 0       {-# INLINE gencode #-}  -- Constructor Encoding-class GEncodeSum f where+class GFlatEncodeSum f where   gencodeSum :: Word16 -> NumBits -> f a -> Encoding -instance (GEncodeSum a, GEncodeSum b) => GEncodeSum (a :+: b) where+instance (GFlatEncodeSum a, GFlatEncodeSum b) => GFlatEncodeSum (a :+: b) where   gencodeSum !code !numBits s = case s of-                           L1 !x -> gencodeSum ((code `unsafeShiftL` 1)) (numBits+1) x+                           L1 !x -> gencodeSum (code `unsafeShiftL` 1) (numBits+1) x                            R1 !x -> gencodeSum ((code `unsafeShiftL` 1) .|. 1) (numBits+1) x   {-# INLINE  gencodeSum #-} -instance GEncode a => GEncodeSum (C1 c a) where+instance GFlatEncode a => GFlatEncodeSum (C1 c a) where   gencodeSum !code !numBits x = eBits16 numBits code <> gencode x   {-# INLINE  gencodeSum #-}  -- |Generic Decoding-class GDecode f where+class GFlatDecode f where   gget :: Get (f t)  -- |Metadata (constructor name, etc)-instance GDecode a => GDecode (M1 i c a) where+instance GFlatDecode a => GFlatDecode (M1 i c a) where     gget = M1 <$> gget     {-# INLINE  gget #-}  -- |Type without constructors-instance GDecode V1 where+instance GFlatDecode V1 where     gget = unused     {-# INLINE  gget #-}  -- |Constructor without arguments-instance GDecode U1 where+instance GFlatDecode U1 where     gget = pure U1     {-# INLINE  gget #-}  -- |Product: constructor with parameters-instance (GDecode a, GDecode b) => GDecode (a :*: b) where+instance (GFlatDecode a, GFlatDecode b) => GFlatDecode (a :*: b) where   gget = (:*:) <$> gget <*> gget   {-# INLINE gget #-}  -- |Constants, additional parameters, and rank-1 recursion-instance Flat a => GDecode (K1 i a) where+instance Flat a => GFlatDecode (K1 i a) where #if INL == 1   gget = K1 <$> inline decode #else@@ -198,12 +234,12 @@ #define DEC_BOOL  #ifdef DEC_BOOLG-instance (GDecode a, GDecode b) => GDecode (a :+: b)+instance (GFlatDecode a, GFlatDecode b) => GFlatDecode (a :+: b) #endif  #ifdef DEC_BOOLC -- Special case for data types with two constructors-instance {-# OVERLAPPING #-} (GDecode a,GDecode b) => GDecode (C1 m1 a :+: C1 m2 b)+instance {-# OVERLAPPING #-} (GFlatDecode a,GFlatDecode b) => GFlatDecode (C1 m1 a :+: C1 m2 b) #endif  #ifdef DEC_BOOL@@ -219,22 +255,22 @@ #ifdef DEC_CONS -- | Data types with up to 512 constructors -- Uses a custom constructor decoding state--- instance {-# OVERLAPPABLE #-} (GDecodeSum (a :+: b),GDecode a, GDecode b) => GDecode (a :+: b) where-instance {-# OVERLAPPABLE #-} (NumConstructors (a :+: b) <= 512, GDecodeSum (a :+: b)) => GDecode (a :+: b) where+-- instance {-# OVERLAPPABLE #-} (GFlatDecodeSum (a :+: b),GFlatDecode a, GFlatDecode b) => GFlatDecode (a :+: b) where+instance {-# OVERLAPPABLE #-} (NumConstructors (a :+: b) <= 512, GFlatDecodeSum (a :+: b)) => GFlatDecode (a :+: b) where   gget = do     cs <- consOpen     getSum cs   {-# INLINE gget #-}  -- |Constructor Decoder-class GDecodeSum f where+class GFlatDecodeSum f where     getSum :: ConsState -> Get (f a)  #ifdef DEC_CONS48  -- Decode constructors in groups of 2 or 3 bits -- Significantly reduce instance compilation time and slightly improve execution times-instance {-# OVERLAPPING #-} (GDecodeSum n1,GDecodeSum n2,GDecodeSum n3,GDecodeSum n4) => GDecodeSum ((n1 :+: n2) :+: (n3 :+: n4)) -- where -- getSum = undefined+instance {-# OVERLAPPING #-} (GFlatDecodeSum n1,GFlatDecodeSum n2,GFlatDecodeSum n3,GFlatDecodeSum n4) => GFlatDecodeSum ((n1 :+: n2) :+: (n3 :+: n4)) -- where -- getSum = undefined       where           getSum cs = do             -- error "DECODE4"@@ -246,7 +282,7 @@               _ -> R1 . R1 <$> getSum cs'           {-# INLINE getSum #-} -instance {-# OVERLAPPING #-} (GDecodeSum n1,GDecodeSum n2,GDecodeSum n3,GDecodeSum n4,GDecodeSum n5,GDecodeSum n6,GDecodeSum n7,GDecodeSum n8) => GDecodeSum (((n1 :+: n2) :+: (n3 :+: n4)) :+: ((n5 :+: n6) :+: (n7 :+: n8))) -- where -- getSum cs = undefined+instance {-# OVERLAPPING #-} (GFlatDecodeSum n1,GFlatDecodeSum n2,GFlatDecodeSum n3,GFlatDecodeSum n4,GFlatDecodeSum n5,GFlatDecodeSum n6,GFlatDecodeSum n7,GFlatDecodeSum n8) => GFlatDecodeSum (((n1 :+: n2) :+: (n3 :+: n4)) :+: ((n5 :+: n6) :+: (n7 :+: n8))) -- where -- getSum cs = undefined      where       getSum cs = do         --error "DECODE8"@@ -262,9 +298,9 @@           _ -> R1 . R1 . R1 <$> getSum cs'       {-# INLINE getSum #-} -instance {-# OVERLAPPABLE #-} (GDecodeSum a, GDecodeSum b) => GDecodeSum (a :+: b) where+instance {-# OVERLAPPABLE #-} (GFlatDecodeSum a, GFlatDecodeSum b) => GFlatDecodeSum (a :+: b) where #else-instance (GDecodeSum a, GDecodeSum b) => GDecodeSum (a :+: b) where+instance (GFlatDecodeSum a, GFlatDecodeSum b) => GFlatDecodeSum (a :+: b) where #endif    getSum cs = do@@ -273,13 +309,13 @@   {-# INLINE getSum #-}  -instance GDecode a => GDecodeSum (C1 c a) where+instance GFlatDecode a => GFlatDecodeSum (C1 c a) where     getSum (ConsState _ usedBits) = consClose usedBits >> gget     {-# INLINE getSum #-} #endif  #ifdef DEC_BOOL48-instance {-# OVERLAPPING #-} (GDecode n1,GDecode n2,GDecode n3,GDecode n4) => GDecode ((n1 :+: n2) :+: (n3 :+: n4)) -- where -- gget = undefined+instance {-# OVERLAPPING #-} (GFlatDecode n1,GFlatDecode n2,GFlatDecode n3,GFlatDecode n4) => GFlatDecode ((n1 :+: n2) :+: (n3 :+: n4)) -- where -- gget = undefined   where       gget = do         -- error "DECODE4"@@ -291,7 +327,7 @@           _ -> R1 <$> R1 <$> gget       {-# INLINE gget #-} -instance {-# OVERLAPPING #-} (GDecode n1,GDecode n2,GDecode n3,GDecode n4,GDecode n5,GDecode n6,GDecode n7,GDecode n8) => GDecode (((n1 :+: n2) :+: (n3 :+: n4)) :+: ((n5 :+: n6) :+: (n7 :+: n8))) -- where -- gget = undefined+instance {-# OVERLAPPING #-} (GFlatDecode n1,GFlatDecode n2,GFlatDecode n3,GFlatDecode n4,GFlatDecode n5,GFlatDecode n6,GFlatDecode n7,GFlatDecode n8) => GFlatDecode (((n1 :+: n2) :+: (n3 :+: n4)) :+: ((n5 :+: n6) :+: (n7 :+: n8))) -- where -- gget = undefined  where   gget = do     --error "DECODE8"@@ -310,25 +346,25 @@  -- |Calculate the number of bits required for the serialisation of a value -- Implemented as a function that adds the maximum size to a running total-class GSize f where gsize :: NumBits -> f a -> NumBits+class GFlatSize f where gsize :: NumBits -> f a -> NumBits  -- |Skip metadata-instance GSize f => GSize (M1 i c f) where+instance GFlatSize f => GFlatSize (M1 i c f) where     gsize !n = gsize n . unM1     {-# INLINE gsize #-}  -- |Type without constructors-instance GSize V1 where+instance GFlatSize V1 where     gsize !n _ = n     {-# INLINE gsize #-}  -- |Constructor without arguments-instance GSize U1 where+instance GFlatSize U1 where     gsize !n _ = n     {-# INLINE gsize #-}  -- |Skip metadata-instance Flat a => GSize (K1 i a) where+instance Flat a => GFlatSize (K1 i a) where #if INL == 1   gsize !n x = inline size (unK1 x) n #else@@ -336,8 +372,8 @@ #endif   {-# INLINE gsize #-} -instance (GSize a, GSize b) => GSize (a :*: b) where-    gsize !n (x :*: y) = +instance (GFlatSize a, GFlatSize b) => GFlatSize (a :*: b) where+    gsize !n (x :*: y) =       let !n' = gsize n x       in gsize n' y       -- gsize (gsize n x) y@@ -352,56 +388,56 @@ -- #define SIZ_MAX_PROX  #ifdef SIZ_ADD-instance (GSizeSum (a :+: b)) => GSize (a :+: b) where+instance (GFlatSizeSum (a :+: b)) => GFlatSize (a :+: b) where   gsize !n = gsizeSum n #endif  #ifdef SIZ_NUM-instance (GSizeSum (a :+: b)) => GSize (a :+: b) where+instance (GFlatSizeSum (a :+: b)) => GFlatSize (a :+: b) where   gsize !n x = n + gsizeSum 0 x #endif  #ifdef SIZ_MAX-instance (GSizeNxt (a :+: b),GSizeMax (a:+:b)) => GSize (a :+: b) where+instance (GFlatSizeNxt (a :+: b),GFlatSizeMax (a:+:b)) => GFlatSize (a :+: b) where   gsize !n x = gsizeNxt (gsizeMax x + n) x   {-# INLINE gsize #-}  -- |Calculate the maximum size of a class constructor (that might be one bit more than the size of some of its constructors) #ifdef SIZ_MAX_VAL-class GSizeMax (f :: * -> *) where gsizeMax :: f a ->  NumBits+class GFlatSizeMax (f :: * -> *) where gsizeMax :: f a ->  NumBits -instance (GSizeMax f, GSizeMax g) => GSizeMax (f :+: g) where+instance (GFlatSizeMax f, GFlatSizeMax g) => GFlatSizeMax (f :+: g) where     gsizeMax _ = 1 + max (gsizeMax (undefined::f a )) (gsizeMax (undefined::g a))     {-# INLINE gsizeMax #-} -instance (GSize a) => GSizeMax (C1 c a) where+instance (GFlatSize a) => GFlatSizeMax (C1 c a) where     {-# INLINE gsizeMax #-}     gsizeMax _ = 0 #endif  #ifdef SIZ_MAX_PROX--- instance (GSizeNxt (a :+: b),GSizeMax (a:+:b)) => GSize (a :+: b) where+-- instance (GFlatSizeNxt (a :+: b),GFlatSizeMax (a:+:b)) => GFlatSize (a :+: b) where --   gsize !n x = gsizeNxt (gsizeMax x + n) x --   {-# INLINE gsize #-}   -- -- |Calculate size in bits of constructor--- class KnownNat n => GSizeMax (n :: Nat) (f :: * -> *) where gsizeMax :: f a -> Proxy n -> NumBits+-- class KnownNat n => GFlatSizeMax (n :: Nat) (f :: * -> *) where gsizeMax :: f a -> Proxy n -> NumBits --- instance (GSizeMax (n + 1) a, GSizeMax (n + 1) b, KnownNat n) => GSizeMax n (a :+: b) where+-- instance (GFlatSizeMax (n + 1) a, GFlatSizeMax (n + 1) b, KnownNat n) => GFlatSizeMax n (a :+: b) where --     gsizeMax !n x _ = case x of --                         L1 !l -> gsizeMax n l (Proxy :: Proxy (n+1)) --                         R1 !r -> gsizeMax n r (Proxy :: Proxy (n+1)) --     {-# INLINE gsizeMax #-} --- instance (GSize a, KnownNat n) => GSizeMax n (C1 c a) where+-- instance (GFlatSize a, KnownNat n) => GFlatSizeMax n (C1 c a) where --     {-# INLINE gsizeMax #-} --     gsizeMax !n !x _ = gsize (constructorSize + n) x --       where --         constructorSize :: NumBits --         constructorSize = fromInteger (natVal (Proxy :: Proxy n)) --- class KnownNat (ConsSize f) => GSizeMax (f :: * -> *) where+-- class KnownNat (ConsSize f) => GFlatSizeMax (f :: * -> *) where --   gsizeMax :: f a ->  NumBits --   gsizeMax _ = fromInteger (natVal (Proxy :: Proxy (ConsSize f))) @@ -418,37 +454,46 @@ #endif  -- |Calculate the size of a value, not taking in account its constructor-class GSizeNxt (f :: * -> *) where gsizeNxt :: NumBits -> f a ->  NumBits+class GFlatSizeNxt (f :: * -> *) where gsizeNxt :: NumBits -> f a ->  NumBits -instance (GSizeNxt a, GSizeNxt b) => GSizeNxt (a :+: b) where+instance (GFlatSizeNxt a, GFlatSizeNxt b) => GFlatSizeNxt (a :+: b) where     gsizeNxt n x = case x of                         L1 !l-> gsizeNxt n l                         R1 !r-> gsizeNxt n r     {-# INLINE gsizeNxt #-} -instance (GSize a) => GSizeNxt (C1 c a) where+instance (GFlatSize a) => GFlatSizeNxt (C1 c a) where     {-# INLINE gsizeNxt #-}     gsizeNxt !n !x = gsize n x #endif  -- |Calculate size in bits of constructor -- vs proxy implementation: similar compilation time but much better run times (at least for Tree N, -70%)-class GSizeSum (f :: * -> *) where gsizeSum :: NumBits -> f a ->  NumBits+#if MIN_VERSION_base(4,9,0)+class GFlatSizeSum (f :: Type -> Type) where+#else+class GFlatSizeSum (f :: * -> *) where+#endif+    gsizeSum :: NumBits -> f a ->  NumBits -instance (GSizeSum a, GSizeSum b)-         => GSizeSum (a :+: b) where+instance (GFlatSizeSum a, GFlatSizeSum b)+         => GFlatSizeSum (a :+: b) where     gsizeSum !n x = case x of                         L1 !l-> gsizeSum (n+1) l                         R1 !r-> gsizeSum (n+1) r     {-# INLINE gsizeSum #-} -instance (GSize a) => GSizeSum (C1 c a) where+instance (GFlatSize a) => GFlatSizeSum (C1 c a) where     {-# INLINE gsizeSum #-}     gsizeSum !n !x = gsize n x   -- |Calculate number of constructors+#if MIN_VERSION_base(4,9,0)+type family NumConstructors (a :: Type -> Type) :: Nat where+#else type family NumConstructors (a :: * -> *) :: Nat where+#endif   NumConstructors (C1 c a) = 1   NumConstructors (x :+: y) = NumConstructors x + NumConstructors y 
src/Flat/Decoder.hs view
@@ -1,8 +1,8 @@-{-# LANGUAGE CPP          #-}+{-# LANGUAGE CPP #-} -- |Strict Decoder module Flat.Decoder (     strictDecoder,-    -- strictDecoderPart,+    listTDecoder,     Decoded,     DecodeException(..),     Get,@@ -46,5 +46,6 @@     ) where  import           Flat.Decoder.Prim+import           Flat.Decoder.Run import           Flat.Decoder.Strict import           Flat.Decoder.Types
src/Flat/Decoder/Prim.hs view
@@ -25,21 +25,33 @@     ConsState(..),consOpen,consClose,consBool,consBits     ) where -import           Control.Monad-import qualified Data.ByteString         as B-import qualified Data.ByteString.Lazy    as L-import           Flat.Decoder.Types-import           Flat.Endian-import           Flat.Memory-import           Data.FloatCast-import           Data.Word-import           Foreign+import           Control.Monad        (when)+import qualified Data.ByteString      as B+import qualified Data.ByteString.Lazy as L+import           Data.FloatCast       (wordToDouble, wordToFloat)+import           Data.Word            (Word16, Word32, Word64, Word8)+import           Flat.Decoder.Types   (Get (Get), GetResult (..), S (..),+                                       badEncoding, badOp, notEnoughSpace)+import           Flat.Endian          (toBE16, toBE32, toBE64)+import           Flat.Memory          (ByteArray, chunksToByteArray,+                                       chunksToByteString, minusPtr)+import           Foreign              (Bits (unsafeShiftL, unsafeShiftR, (.&.), (.|.)),+                                       FiniteBits (finiteBitSize), Ptr,+                                       Storable (peek), castPtr, plusPtr,+                                       ptrToIntPtr) +#ifdef ghcjs_HOST_OS+import           Foreign              (shift)+#else+#endif+ -- $setup -- >>> :set -XBinaryLiterals -- >>> import Data.Word -- >>> import Data.Int -- >>> import Flat.Run+-- >>> import Flat.Bits+-- >>> import Text.PrettyPrint.HughesPJClass (Pretty (pPrint))  {- |A special state, optimised for constructor decoding. @@ -59,14 +71,14 @@ consOpen :: Get ConsState consOpen = Get $ \endPtr s -> do   let u = usedBits s-  w <- case compare (currPtr s) endPtr of-    LT -> do -- two different bytes-      w16::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)-      return $ fromIntegral w16 `unsafeShiftL` (u+(wordSize-16))-    EQ -> do-        w8 :: Word8 <- peek (currPtr s)-        return $ fromIntegral w8 `unsafeShiftL` (u+(wordSize-8))-    GT -> notEnoughSpace endPtr s+  let d = ptrToIntPtr endPtr - ptrToIntPtr (currPtr s)+  w <-  if d > 1 then do -- two different bytes+          w16::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)+          return $ fromIntegral w16 `unsafeShiftL` (u+(wordSize-16))+        else  if d == 1 then do -- single last byte left+                w8 :: Word8 <- peek (currPtr s)+                return $ fromIntegral w8 `unsafeShiftL` (u+(wordSize-8))+              else notEnoughSpace endPtr s   return $ GetResult s (ConsState w 0)  -- |Switch back to normal decoding@@ -98,7 +110,7 @@ -- consBool (ConsState w usedBits) = (ConsState (w `unsafeShiftL` 1) (1+usedBits),0 /= 32768 .&. w)  -- |Decode from 1 to 3 bits--- +-- -- It could read more bits that are available, but it doesn't matter, errors will be checked in consClose. consBits :: ConsState -> Int -> (ConsState, Word) consBits cs 3 = consBits_ cs 3 7@@ -162,9 +174,9 @@   --   bits = n' .|. 7   in S {currPtr=currPtr s `plusPtr` bytes,usedBits=bits} -{-# INLINE dBool #-} --- Inlining dBool Massively increases compilation time and decreases run time by a third--- TODO: test dBool inlining for 8.8.3+{-# INLINE dBool #-}+-- Inlining dBool massively increases compilation time but decreases run time by a third+-- TODO: test dBool inlining for ghc >= 8.8.4 -- |Decode a boolean dBool :: Get Bool dBool = Get $ \endPtr s ->@@ -186,6 +198,9 @@  >>> unflatWith (dBEBits8 3) [0b11100001::Word8] == Right 0b00000111 True++>>> unflatWith (dBEBits8 9) [0b11100001::Word8,0b11111111]+Left (BadOp "read8: cannot read 9 bits") -} dBEBits8 :: Int -> Get Word8 dBEBits8 n = Get $ \endPtr s -> do@@ -193,15 +208,25 @@       take8 s n  {-# INLINE dBEBits16  #-}--- |Return the n most significant bits (up to maximum of 16)--- The bits are returned right shifted.+{- | Return the n most significant bits (up to maximum of 16)++The bits are returned right shifted:++>>> pPrint . asBits <$> unflatWith (dBEBits16 11) [0b10110111::Word8,0b11100001]+Right 00000101 10111111++If more than 16 bits are requested, only the last 16 are returned:++>>> pPrint . asBits <$> unflatWith (dBEBits16 19) [0b00000000::Word8,0b11111111,0b11100001]+Right 00000111 11111111+-} 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)+-- |Return the n most significant bits (up to maximum of 32) -- The bits are returned right shifted. dBEBits32 :: Int -> Get Word32 dBEBits32 n = Get $ \endPtr s -> do@@ -209,7 +234,7 @@       takeN n s  {-# INLINE dBEBits64  #-}--- |Return the n most significant bits (up to maximum of 8)+-- |Return the n most significant bits (up to maximum of 64) -- The bits are returned right shifted. dBEBits64 :: Int -> Get Word64 dBEBits64 n = Get $ \endPtr s -> do@@ -241,15 +266,15 @@   where     --{-# 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) `shR` (8 - n)-            else do -- two different bytes-              w::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)-              return $ fromIntegral $ (w `unsafeShiftL` usedBits s) `shR` (16 - n)-          | otherwise = error $ unwords ["read8: cannot read",show n,"bits"]+    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) `shR` (8 - n)+                    else do -- two different bytes+                      w::Word16 <- toBE16 <$> peek (castPtr $ currPtr s)+                      return $ fromIntegral $ (w `unsafeShiftL` usedBits s) `shR` (16 - n)+                | otherwise = badOp $ unwords ["read8: cannot read",show n,"bits"]     -- {-# INLINE dropBits8 #-}     -- -- Assume n <= 8     dropBits8 :: S -> Int -> S@@ -399,9 +424,9 @@ -- >>> shR (0b1111111111111111::Word16) 3 == 0b0001111111111111 -- True --- >>> shR (-1::Int16) 3 +-- >>> shR (-1::Int16) 3 -- -1--- -}  +-- -} {-# INLINE shR #-} shR :: Bits a => a -> Int -> a #ifdef ghcjs_HOST_OS
+ src/Flat/Decoder/Run.hs view
@@ -0,0 +1,68 @@+module Flat.Decoder.Run(strictDecoder,listTDecoder) where++import           Control.Exception        (Exception, try)+import qualified Data.ByteString          as B+import qualified Data.ByteString.Internal as BS+import           Flat.Decoder.Prim        (dBool)+import           Flat.Decoder.Types       (DecodeException, Get (runGet),+                                           GetResult (..), S (S), tooMuchSpace)+import           Foreign                  (Ptr, plusPtr, withForeignPtr)+import           ListT                    (ListT (..))+import           System.IO.Unsafe         (unsafePerformIO)++-- | Given a decoder and an input buffer returns either the decoded value or an error  (if the input buffer is not fully consumed)+strictDecoder :: Get a -> B.ByteString -> Either DecodeException a+strictDecoder get bs =+  strictDecoder_ get bs $ \(GetResult s'@(S ptr' o') a) endPtr ->+    if ptr' /= endPtr || o' /= 0+      then tooMuchSpace endPtr s'+      else return a++strictDecoder_ ::+     Exception e+  => Get a1+  -> BS.ByteString+  -> (GetResult a1 -> Ptr b -> IO a)+  -> Either e a+strictDecoder_ get (BS.PS base off len) check =+  unsafePerformIO . try $+  withForeignPtr base $ \base0 ->+    let ptr = base0 `plusPtr` off+        endPtr = ptr `plusPtr` len+     in do res <- runGet get endPtr (S ptr 0)+           check res endPtr+{-# NOINLINE strictDecoder_ #-}+++-- strictRawDecoder :: Exception e => Get t -> B.ByteString -> Either e (t,B.ByteString, NumBits)+-- strictRawDecoder get (BS.PS base off len) = unsafePerformIO . try $+--   withForeignPtr base $ \base0 ->+--     let ptr = base0 `plusPtr` off+--         endPtr = ptr `plusPtr` len+--     in do+--       GetResult (S ptr' o') a <- runGet get endPtr (S ptr 0)+--       return (a, BS.PS base (ptr' `minusPtr` base0) (endPtr `minusPtr` ptr'), o')++{-| +Decode a list of values, one value at a time.++Useful in case that the decoded values takes a lot more memory than the encoded ones.++See test/FlatRepr.hs for a test and an example of use.++@since 0.5+-}+listTDecoder :: Get a -> BS.ByteString -> IO (ListT IO a)+listTDecoder get (BS.PS base off len) =+    withForeignPtr base $ \base0 -> do+        let ptr = base0 `plusPtr` off+            endPtr = ptr `plusPtr` len+            s = S ptr 0+            go s = do+                GetResult s' b <- runGet dBool endPtr s+                if b+                    then do+                        GetResult s'' a <- runGet get endPtr s'+                        return $ Just (a, ListT $ go s'')+                    else return Nothing+        return $ ListT (go s)
src/Flat/Decoder/Strict.hs view
@@ -32,16 +32,19 @@ import qualified Data.ByteString                as B import qualified Data.ByteString.Lazy           as L import qualified Data.ByteString.Short          as SBS+#if !MIN_VERSION_bytestring(0,11,0) import qualified Data.ByteString.Short.Internal as SBS+#endif+import           Control.Monad                  (unless) import qualified Data.DList                     as DL-import           Flat.Decoder.Prim-import           Flat.Decoder.Types import           Data.Int import           Data.Primitive.ByteArray import qualified Data.Text                      as T import qualified Data.Text.Encoding             as T+import           Flat.Decoder.Prim+import           Flat.Decoder.Types -#if! defined(ghcjs_HOST_OS) && ! defined (ETA_VERSION)+#if! defined(ghcjs_HOST_OS) && ! defined (ETA_VERSION) && ! MIN_VERSION_text(2,0,0) import qualified Data.Text.Array                as TA import qualified Data.Text.Internal             as T #endif@@ -49,8 +52,7 @@ import           Data.Word import           Data.ZigZag import           GHC.Base                       (unsafeChr)-import           Numeric.Natural-+import           Numeric.Natural                (Natural) #include "MachDeps.h"  {-# INLINE decodeListWith #-}@@ -93,6 +95,7 @@ {-# INLINE dInt #-} dWord :: Get Word dInt :: Get Int+ #if WORD_SIZE_IN_BITS == 64 dWord = (fromIntegral :: Word64 -> Word) <$> dWord64 @@ -105,6 +108,13 @@ #error expected WORD_SIZE_IN_BITS to be 32 or 64 #endif +++++++ {-# INLINE dInt8 #-} dInt8 :: Get Int8 dInt8 = zagZig <$> dWord8@@ -162,7 +172,7 @@ charStep !shl !cont !n = do   !tw <- fromIntegral <$> dWord8   let !w = tw .&. 127-  let !v = n .|. (w `shift` shl)+  let !v = n .|. w `shift` shl   if tw == w     then return $ unsafeChr v     else cont v@@ -172,21 +182,21 @@ lastCharStep !shl !n = do   !tw <- fromIntegral <$> dWord8   let !w = tw .&. 127-  let !v = n .|. (w `shift` shl)+  let !v = n .|. w `shift` shl   if tw == w     then if v > 0x10FFFF            then charErr v            else return $ unsafeChr v     else charErr v- where -  charErr v = fail $ concat ["Unexpected extra byte or non unicode char", show v]+ where+  charErr v = fail $ "Unexpected extra byte or non unicode char" ++ show v  {-# INLINE wordStep #-} wordStep :: (Bits a, Num a) => Int -> (a -> Get a) -> a -> Get a wordStep shl k n = do   tw <- fromIntegral <$> dWord8   let w = tw .&. 127-  let v = n .|. (w `shift` shl)+  let v = n .|. w `shift` shl   if tw == w     then return v     --else oneShot k v@@ -197,14 +207,14 @@ lastStep shl n = do   tw <- fromIntegral <$> dWord8   let w = tw .&. 127-  let v = n .|. (w `shift` shl)+  let v = n .|. w `shift` shl   if tw == w     then if countLeadingZeros w < shl            then wordErr v            else return v     else wordErr v- where -   wordErr v = fail $ concat ["Unexpected extra byte in unsigned integer", show v]+ where+   wordErr v = fail $ "Unexpected extra byte in unsigned integer" ++ show v  -- {-# INLINE dUnsigned #-} dUnsigned :: (Num b, Bits b) => Get b@@ -223,7 +233,7 @@ dUnsigned_ shl n = do   tw <- dWord8   let w = tw .&. 127-  let v = n .|. (fromIntegral w `shift` shl)+  let v = n .|. fromIntegral w `shift` shl   if tw == w     then return (v, shl)     else dUnsigned_ (shl + 7) v@@ -234,23 +244,28 @@ dUTF16 :: Get T.Text dUTF16 = do   _ <- dFiller+#if MIN_VERSION_text(2,0,0)   -- Checked decoding-  -- T.decodeUtf16LE <$> dByteString_+  T.decodeUtf16LE <$> dByteString_+#else   -- Unchecked decoding   (ByteArray array, lengthInBytes) <- dByteArray_   return (T.Text (TA.Array array) 0 (lengthInBytes `div` 2)) #endif+#endif+ dUTF8 :: Get T.Text dUTF8 = do   _ <- dFiller-  T.decodeUtf8 <$> dByteString_+  bs <- dByteString_+  case T.decodeUtf8' bs of+    Right t -> pure t+    Left e  -> fail $ "Input contains invalid UTF-8 data" ++ show e  dFiller :: Get () dFiller = do   tag <- dBool-  case tag of-    False -> dFiller-    True  -> return ()+  unless tag dFiller  dLazyByteString :: Get L.ByteString dLazyByteString = dFiller >> dLazyByteString_@@ -265,3 +280,7 @@  dByteString :: Get B.ByteString dByteString = dFiller >> dByteString_++++
src/Flat/Decoder/Types.hs view
@@ -4,9 +4,8 @@  -- |Strict Decoder Types module Flat.Decoder.Types-  ( strictDecoder-  -- , strictDecoderPart-  , Get(..)+  (+    Get(..)   , S(..)   , GetResult(..)   , Decoded@@ -14,61 +13,40 @@   , notEnoughSpace   , tooMuchSpace   , badEncoding+  , badOp   ) where -import           Control.DeepSeq-import           Control.Exception-import qualified Data.ByteString          as B-import qualified Data.ByteString.Internal as BS-import           Data.Word-import           Foreign-import           System.IO.Unsafe+import           Control.DeepSeq    (NFData (..))+import           Control.Exception  (Exception, throwIO)+import           Data.Word          (Word8)+import           Foreign            (Ptr)+ #if MIN_VERSION_base(4,9,0)-import qualified Control.Monad.Fail       as Fail+import qualified Control.Monad.Fail as Fail #endif +{- |+A decoder. -strictDecoder :: Get a -> B.ByteString -> Either DecodeException a-strictDecoder get bs =-  strictDecoder_ get bs $ \(GetResult s'@(S ptr' o') a) endPtr ->-    if ptr' /= endPtr || o' /= 0-      then tooMuchSpace endPtr s'-      else return a+Given: --- strictDecoderPart :: Get a -> B.ByteString -> Either DecodeException a--- strictDecoderPart get bs =---   strictDecoder_ get bs $ \(GetResult _ a) _ -> return a+* end of input buffer -strictDecoder_ ::-     Exception e-  => Get a1-  -> BS.ByteString-  -> (GetResult a1 -> Ptr b -> IO a)-  -> Either e a-strictDecoder_ get (BS.PS base off len) check =-  unsafePerformIO . try $-  withForeignPtr base $ \base0 ->-    let ptr = base0 `plusPtr` off-        endPtr = ptr `plusPtr` len-     in do res <- runGet get endPtr (S ptr 0)-           check res endPtr+* current position in input buffer --- strictRawDecoder :: Exception e => Get t -> B.ByteString -> Either e (t,B.ByteString, NumBits)--- strictRawDecoder get (BS.PS base off len) = unsafePerformIO . try $---   withForeignPtr base $ \base0 ->---     let ptr = base0 `plusPtr` off---         endPtr = ptr `plusPtr` len---     in do---       GetResult (S ptr' o') a <- runGet get endPtr (S ptr 0)---       return (a, BS.PS base (ptr' `minusPtr` base0) (endPtr `minusPtr` ptr'), o')+Returns: +* decoded value --- |Decoder monad+* new position in input buffer+-} newtype Get a =   Get-    { runGet :: -      Ptr Word8 -> S -> IO (GetResult a)-    } -- deriving (Functor)+    { runGet ::+      Ptr Word8+      -> S+      -> IO (GetResult a)+    }  -- Seems to give better performance than the derived version instance Functor Get where@@ -112,7 +90,6 @@   {-# INLINE (>>=) #-} #if !(MIN_VERSION_base(4,13,0))   fail = failGet-                 -- base < 4.13 #endif  #if MIN_VERSION_base(4,9,0)@@ -143,6 +120,7 @@   = NotEnoughSpace Env   | TooMuchSpace Env   | BadEncoding Env String+  | BadOp String   deriving (Show, Eq, Ord)  type Env = (Ptr Word8, S)@@ -155,5 +133,8 @@  badEncoding :: Ptr Word8 -> S -> String -> IO a badEncoding endPtr s msg = throwIO $ BadEncoding (endPtr, s) msg++badOp :: String -> IO a+badOp msg = throwIO $ BadOp msg  instance Exception DecodeException
src/Flat/Encoder.hs view
@@ -70,10 +70,10 @@ #endif     ) where -import           Flat.Encoder.Prim+import Flat.Encoder.Prim ( eTrueF, eFalseF ) import           Flat.Encoder.Size(arrayBits) import           Flat.Encoder.Strict-import           Flat.Encoder.Types+import Flat.Encoder.Types ( NumBits, Size )  #if ! MIN_VERSION_base(4,11,0) import           Data.Semigroup((<>))
src/Flat/Encoder/Prim.hs view
@@ -3,12 +3,12 @@ {-# LANGUAGE MagicHash           #-} {-# LANGUAGE MultiWayIf          #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections       #-}-{-# LANGUAGE UnboxedTuples       #-}  -- |Encoding Primitives module Flat.Encoder.Prim-  ( eBits16F+  (+    -- Primitives whose name starts with 'e' encode a value in place+    eBits16F   , eBitsF   , eFloatF   , eDoubleF@@ -36,8 +36,12 @@   , eBoolF   , eTrueF   , eFalseF+   , varWordF++  , updateWord8   , w7l+     -- * Exported for testing only   , eWord32BEF   , eWord64BEF@@ -51,16 +55,20 @@ import qualified Data.ByteString.Lazy.Internal  as L import qualified Data.ByteString.Short.Internal as SBS import           Data.Char+import           Data.FloatCast+import           Data.Primitive.ByteArray+import qualified Data.Text                      as T import           Flat.Encoder.Types import           Flat.Endian import           Flat.Memory import           Flat.Types-import           Data.FloatCast-import           Data.Primitive.ByteArray-import qualified Data.Text                      as T-#if! defined(ghcjs_HOST_OS) && ! defined (ETA_VERSION)++#if! defined(ghcjs_HOST_OS) && ! defined (ETA_VERSION) && ! MIN_VERSION_text(2,0,0) import qualified Data.Text.Array                as TA import qualified Data.Text.Internal             as TI+-- import           Data.FloatCast+-- import           Data.Primitive.ByteArray+-- import qualified Data.Text                      as T #endif import qualified Data.Text.Encoding             as TE import           Data.ZigZag@@ -69,6 +77,14 @@ #include "MachDeps.h" -- traceShowId :: a -> a -- traceShowId = id++-- $setup+-- >>> import Flat.Instances.Test+-- >>> import Flat.Bits+-- >>> import Flat.Encoder.Strict+-- >>> import Control.Monad+-- >>> let enc e = prettyShow $ encBits 256 (Encoding e)+ {-# INLINE eFloatF #-} eFloatF :: Float -> Prim eFloatF = eWord32BEF . floatToWord@@ -93,6 +109,7 @@ eWordF :: Word -> Prim {-# INLINE eIntF #-} eIntF :: Int -> Prim+ #if WORD_SIZE_IN_BITS == 64 eWordF = eWord64F . (fromIntegral :: Word -> Word64) @@ -104,6 +121,7 @@ #else #error expected WORD_SIZE_IN_BITS to be 32 or 64 #endif+ {-# INLINE eInt8F #-} eInt8F :: Int8 -> Prim eInt8F = eWord8F . zigZag@@ -154,11 +172,16 @@   | o == 0 = foldM pokeWord' op vs >>= \op' -> return (S op' 0 0)   | otherwise = foldM (flip eWord8F) s vs +{-+>>> enc $ \s0 -> eTrueF s0 >>= \s1 -> eWord8F 0 s1 >>= \s2 -> eTrueF s2+"10000000 01"+-}+ {-# INLINE eWord8F #-} eWord8F :: Word8 -> Prim eWord8F t s@(S op _ o)   | o == 0 = pokeWord op t-  | otherwise = pokeByteUnaligned t s+  | otherwise = eByteUnaligned t s  {-# INLINE eWord32E #-} eWord32E :: (Word32 -> Word32) -> Word32 -> Prim@@ -191,8 +214,8 @@ {-# INLINE varWordF #-} varWordF :: (Bits t, Integral t) => t -> Prim varWordF t s@(S _ _ o)-  | o == 0 = varWord pokeByteAligned t s-  | otherwise = varWord pokeByteUnaligned t s+  | o == 0 = varWord eByteAligned t s+  | otherwise = varWord eByteUnaligned t s  {-# INLINE varWord #-} varWord :: (Bits t, Integral t) => (Word8 -> Prim) -> t -> Prim@@ -229,20 +252,26 @@ low7 t = fromIntegral t .&. 0x7F  -- | Encode text as UTF8 and encode the result as an array of bytes+--  -- PROB: encodeUtf8 calls a C primitive, not compatible with GHCJS (fixed in latest versions of GHCJS?) eUTF8F :: T.Text -> Prim eUTF8F = eBytesF . TE.encodeUtf8 --- PROB: Not compatible with GHCJS or ETA (that is big endian and writes contents in reverse order) -- | Encode text as UTF16 and encode the result as an array of bytes--- Efficient, as Text is already internally encoded as UTF16.+-- +-- PROB: Not compatible with GHCJS or ETA (that is big endian and writes contents in reverse order) #if ! defined(ghcjs_HOST_OS) && ! defined (ETA_VERSION)+ eUTF16F :: T.Text -> Prim+#if MIN_VERSION_text(2,0,0)+eUTF16F = eBytesF . TE.encodeUtf16LE+#else eUTF16F t = eFillerF >=> eUTF16F_ t   where-    eUTF16F_ !(TI.Text (TA.Array array) w16Off w16Len) s =+    eUTF16F_ (TI.Text (TA.Array array) w16Off w16Len) s =       writeArray array (2 * w16Off) (2 * w16Len) (nextPtr s) #endif+#endif  -- |Encode a Lazy ByteString eLazyBytesF :: L.ByteString -> Prim@@ -257,10 +286,10 @@ {-# INLINE eShortBytesF #-} eShortBytesF :: SBS.ShortByteString -> Prim eShortBytesF bs = eFillerF >=> eShortBytesF_ bs--eShortBytesF_ :: SBS.ShortByteString -> Prim-eShortBytesF_ bs@(SBS.SBS arr) =-  \(S op _ 0) -> writeArray arr 0 (SBS.length bs) op+  where+    eShortBytesF_ :: SBS.ShortByteString -> Prim+    eShortBytesF_ bs@(SBS.SBS arr) (S op _ 0) = writeArray arr 0 (SBS.length bs) op+    eShortBytesF_ _ _ = error "impossible"  -- data Array a = Array0 | Array1 a ... | Array255 ... writeArray :: ByteArray# -> Int -> Int -> Ptr Word8 -> IO S@@ -329,8 +358,7 @@ -} -- {-# NOINLINE eBitsF_ #-} eBitsF_ :: NumBits -> Word8 -> Prim-eBitsF_ n t =-  \(S op w o) ->+eBitsF_ n t (S op w o) =     let o' = o + n -- used bits         f = 8 - o' -- remaining free bits      in if | f > 0 -> return $ S op (w .|. (t `unsafeShiftL` f)) o'@@ -345,18 +373,30 @@ eBoolF False = eFalseF eBoolF True  = eTrueF +-- | >>> enc eTrueF+-- "1" {-# INLINE eTrueF #-} eTrueF :: Prim eTrueF (S op w o)   | o == 7 = pokeWord op (w .|. 1)   | otherwise = return (S op (w .|. 128 `unsafeShiftR` o) (o + 1)) +-- | >>> enc eFalseF+-- "0" {-# INLINE eFalseF #-} eFalseF :: Prim eFalseF (S op w o)   | o == 7 = pokeWord op w   | otherwise = return (S op w (o + 1)) +{- |++>>> enc $ eTrueF >=> eFillerF+"10000001"++>>> enc eFillerF+"00000001"+-} {-# INLINE eFillerF #-} eFillerF :: Prim eFillerF (S op w _) = pokeWord op (w .|. 1)@@ -365,15 +405,87 @@ -- TODO TEST -- poke16 :: Word16 -> Prim -- poke16 t (S op w o) | o == 0 = poke op w >> skipBytes op 2-{-# INLINE pokeByteUnaligned #-}-pokeByteUnaligned :: Word8 -> Prim-pokeByteUnaligned t (S op w o) =+{-+To be used only when usedBits /= 0++>>> enc (eFalseF >=> eFalseF >=> eByteUnaligned 255)+"00111111 11"+-}+{-# INLINE eByteUnaligned #-}+eByteUnaligned :: Word8 -> Prim+eByteUnaligned t (S op w o) =   poke op (w .|. (t `unsafeShiftR` o)) >>   return (S (plusPtr op 1) (t `unsafeShiftL` (8 - o)) o) -{-# INLINE pokeByteAligned #-}-pokeByteAligned :: Word8 -> Prim-pokeByteAligned t (S op _ _) = pokeWord op t+{- To be used only when usedBits = 0++>>> enc (eFalseF >=> eFalseF >=> eFalseF >=> eByteAligned 255)+"11111111"+-}+{-# INLINE eByteAligned #-}+eByteAligned :: Word8 -> Prim+eByteAligned t (S op _ _) = pokeWord op t++{-|+>>> enc $ \s-> eWord8F 0 s >>= updateWord8 255 s+"11111111"++>>> enc $ \s0 -> eTrueF s0 >>= \s1 -> eWord8F 255 s1 >>= eWord8F 255 >>= updateWord8 0 s1+"10000000 01111111 1"++>>> enc $ \s0 -> eFalseF s0 >>= \s1 -> eWord8F 0 s1 >>= updateWord8 255 s1+"01111111 1"++>>> enc $ \s0 -> eFalseF s0 >>= \s1 -> eWord8F 0 s1 >>= updateWord8 255 s1 >>= eFalseF+"01111111 10"++>>> enc $ \s0 -> eTrueF s0 >>= \s1 -> eWord8F 255 s1 >>= eTrueF >>= updateWord8 0 s1 >>= eTrueF+"10000000 011"++@since 0.5+-}+updateWord8 :: Word8 -> S -> Prim+updateWord8 t mem s = do+  uncache s+  pokeWord8 t mem+  cache s++uncache :: S -> IO ()+uncache s = poke (nextPtr s) (currByte s)++cache :: Prim+cache s = do+  w <- (mask s .&.) <$> peek (nextPtr s)+  return $ s {currByte = w}++mask :: S -> Word8+mask s = 255 `unsafeShiftL` (8 - usedBits s)++{-# INLINE pokeWord8 #-}+pokeWord8 :: Word8 -> S -> IO ()+pokeWord8 t  (S op _ 0) = poke op t+pokeWord8 t  (S op w o) = do+        poke op (w .|. (t `unsafeShiftR` o))+        let op' :: Ptr Word8 = plusPtr op 1+        v :: Word8 <- peek op'+        poke op' (t `unsafeShiftL` (8 - o) .|. ((v `unsafeShiftL` o) `unsafeShiftR` o))++-- | o == 0 = pokeByteAligned t s+-- | otherwise = pokeByteUnaligned t s+--   where+-- {-# INLINE pokeByteUnaligned #-}+-- pokeByteUnaligned :: Word8 -> S -> IO ()+-- pokeByteUnaligned t (S op w o) = do+--   let op' = plusPtr op 1+--   poke op (w .|. (t `unsafeShiftR` o))+--   v :: Word8 <- peek op'+--   poke op' (t `unsafeShiftL` (8 - o) .|. ((v `unsafeShiftL` o) `unsafeShiftR` o))++-- {-# INLINE pokeByteAligned #-}+-- pokeByteAligned :: Word8 -> S -> IO ()+-- pokeByteAligned t (S op _ _) = poke op t++-- FIX: not really pokes  {-# INLINE pokeWord #-} pokeWord :: Storable a => Ptr a -> a -> IO S
src/Flat/Encoder/Size.hs view
@@ -1,18 +1,18 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP          #-}+{-# LANGUAGE CPP #-} --- |Primitives to calculate the encoding size of a value+-- |Primitives to calculate the maximum size in bits of the encoding of a value module Flat.Encoder.Size where -import           Data.Bits+import           Data.Bits                      (Bits) import qualified Data.ByteString                as B import qualified Data.ByteString.Lazy           as L import qualified Data.ByteString.Short.Internal as SBS-import           Data.Char-import           Flat.Encoder.Prim         (w7l)-import           Flat.Encoder.Types-import           Flat.Types+import           Data.Char                      (ord) import qualified Data.Text                      as T+import           Flat.Encoder.Prim              (w7l)+import           Flat.Types                     (Int16, Int32, Int64, Natural,+                                                 NumBits, Text, Word16, Word32,+                                                 Word64) #ifndef ghcjs_HOST_OS import qualified Data.Text.Internal             as TI #endif@@ -119,7 +119,7 @@  --sUTF8 :: T.Text -> NumBits --sUTF8 t = fold--- Wildly pessimistic but fast+-- TOFIX: Wildly pessimistic and also slow as T.length is O(n) {-# INLINE sUTF8Max #-} sUTF8Max :: Text -> NumBits sUTF8Max = blobBits . (4 *) . T.length@@ -149,7 +149,7 @@ -- 4 {-# INLINE textBytes #-} textBytes :: T.Text -> Int-textBytes !(TI.Text _ _ w16Len) = w16Len * 2+textBytes (TI.Text _ _ w16Len) = w16Len * 2 #endif  {-# INLINE bitsToBytes #-}
src/Flat/Encoder/Strict.hs view
@@ -1,30 +1,32 @@ {-# LANGUAGE BangPatterns              #-} {-# LANGUAGE CPP                       #-} {-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE RecordWildCards           #-} {-# LANGUAGE ScopedTypeVariables       #-}  -- |Strict encoder module Flat.Encoder.Strict where -import qualified Data.ByteString         as B-import qualified Data.ByteString.Lazy    as L+import           Control.Monad        (when)+import qualified Data.ByteString      as B+import qualified Data.ByteString.Lazy as L+import           Data.Foldable import           Flat.Encoder.Prim-import qualified Flat.Encoder.Size  as S+import qualified Flat.Encoder.Size    as S import           Flat.Encoder.Types import           Flat.Memory import           Flat.Types-import           Data.Foldable  -- import           Data.Semigroup -- import           Data.Semigroup          (Semigroup (..))  #if !MIN_VERSION_base(4,11,0)-import           Data.Semigroup          (Semigroup (..))+import           Data.Semigroup       (Semigroup (..)) #endif  #ifdef ETA_VERSION -- import Data.Function(trampoline)-import           GHC.IO                  (trampolineIO)+import           GHC.IO               (trampolineIO) trampolineEncoding :: Encoding -> Encoding trampolineEncoding (Encoding op) = Encoding (\s -> trampolineIO (op s)) #else@@ -34,13 +36,28 @@  -- |Strict encoder strictEncoder :: NumBits -> Encoding -> B.ByteString-strictEncoder numBits (Encoding op) =-  let bufSize = S.bitsToBytes numBits-   in fst $-      unsafeCreateUptoN' bufSize $ \ptr -> do-        (S ptr' 0 0) <- op (S ptr 0 0)-        return (ptr' `minusPtr` ptr, ())+strictEncoder numBits enc =+  let (bs,numBitsUsed) = strictEncoderPartial numBits enc+      bitsInLastByte = numBitsUsed `mod` 8+  in if bitsInLastByte /=0+      then error $ unwords ["encoder: did not end on byte boundary, bits used in last byte=",show  bitsInLastByte]+      else bs +numEncodedBits :: Int -> Encoding -> NumBits+numEncodedBits numBits enc =snd $ strictEncoderPartial numBits enc++strictEncoderPartial ::+  Int                        -- ^ the maximum size in bits of the encoding+  -> Encoding                -- ^ the encoder+  -> (B.ByteString, NumBits) -- ^ the encoded bytestring + the actual number of encoded bits+strictEncoderPartial numBits (Encoding op)+  = let bufSize = S.bitsToBytes numBits+    in unsafeCreateUptoN' bufSize $ \ptr -> do+        S{..} <- op (S ptr 0 0)+        let numBitsUsed = nextPtr `minusPtr` ptr * 8 + usedBits+        when (numBitsUsed > numBits) $ error $ unwords ["encoder: size mismatch, expected <=",show numBits,"actual=",show numBitsUsed,"bits"]+        return (nextPtr `minusPtr` ptr,numBitsUsed)+ newtype Encoding =   Encoding     { run :: Prim@@ -51,20 +68,27 @@  instance Semigroup Encoding where   {-# INLINE (<>) #-}-  (<>) = mappend+  (<>) = encodingAppend  instance Monoid Encoding where   {-# INLINE mempty #-}   mempty = Encoding return++#if !(MIN_VERSION_base(4,11,0))   {-# INLINE mappend #-}-  -- mappend (Encoding f) (Encoding g) = Encoding (f >=> g)-  mappend (Encoding f) (Encoding g) = Encoding m+  mappend = encodingAppend+#endif++  {-# INLINE mconcat #-}+  mconcat = foldl' mappend mempty++{-# INLINE encodingAppend #-}+encodingAppend :: Encoding -> Encoding -> Encoding+encodingAppend (Encoding f) (Encoding g) = Encoding m     where       m s@(S !_ !_ !_) = do         !s1 <- f s         g s1-  {-# INLINE mconcat #-}-  mconcat = foldl' mappend mempty  -- PROB: GHC 8.02 won't always apply the rules leading to poor execution times (e.g. with lists) -- TODO: check with newest GHC versions@@ -76,9 +100,13 @@  {-# NOINLINE encodersS #-} encodersS :: [Encoding] -> Encoding--- without the explicit parameter the rules won't fire+-- Without the explicit parameter the rules won't fire! encodersS ws = foldl' mappend mempty ws +sizeListWith :: (Foldable t1, Num t2) => (t3 -> t2 -> t2) -> t1 t3 -> t2 -> t2+sizeListWith size l sz = foldl' (\s e -> size e (s + 1)) (sz + 1) l+{-# INLINE sizeListWith #-}+ -- encodersS ws = error $ unwords ["encodersS CALLED",show ws] {-# INLINE encodeListWith #-} -- |Encode as a List@@ -87,7 +115,7 @@   where     go []     = eFalse     go (x:xs) = eTrue <> enc x <> go xs- + -- {-# INLINE encodeList #-} -- encodeList :: (Foldable t, Flat a) => t a -> Encoding -- encodeList l = F.foldl' (\acc a -> acc <> eTrue <> encode a) mempty l <> eFalse@@ -101,12 +129,15 @@ encodeArrayWith f ws = Encoding $ go ws   where     go l s = do+      -- write a placeholder for the number of elements in current block       s' <- eWord8F 0 s-      (n, s'', l) <- gol l 0 s'-      _ <- eWord8F n s+      (n, sn, l) <- gol l 0 s'+      -- update actual number of elements+      s'' <- updateWord8 n s sn       if null l         then eWord8F 0 s''         else go l s''+    -- encode up to 255 elements and returns (numberOfWrittenElements,elementsLeftToWrite,currentState)     gol [] !n !s = return (n, s, [])     gol l@(x:xs) !n !s       | n == 255 = return (255, s, l)
src/Flat/Encoder/Types.hs view
@@ -9,7 +9,7 @@ import           Flat.Types import           GHC.Ptr         (Ptr (..)) --- |Calculate the size (in bits) of the encoding of a value+-- |Add the maximum size in bits of the encoding of value a to a NumBits type Size a = a -> NumBits -> NumBits  -- |Strict encoder state
src/Flat/Endian.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} -- | Endian utilities+--  -- Exported for testing purposes, but not meant to be used outside this package. module Flat.Endian     (@@ -12,7 +13,8 @@  #include "MachDeps.h" -import Data.Word+import           Data.Word (Word16, Word32, Word64, byteSwap16, byteSwap32,+                            byteSwap64)  -- #ifdef ghcjs_HOST_OS -- import Data.Bits
src/Flat/Filler.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE DeriveAnyClass      #-} {-# LANGUAGE DeriveGeneric       #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE CPP       #-}+{-# LANGUAGE CPP #-}  -- |Pre-value and post-value byte alignments module Flat.Filler (@@ -11,18 +11,20 @@     preAligned,     PostAligned(..),     postAligned,+    preAlignedDecoder,     postAlignedDecoder     ) where -import           Flat.Class-import           Flat.Encoder-import           Flat.Decoder-import           Control.DeepSeq-import           Data.Typeable+import Flat.Class ( Generic, Flat(..) )+import Flat.Encoder.Strict ( eFiller, sFillerMax )+import Flat.Decoder.Types ( Get )+import Control.DeepSeq ( NFData )+import Data.Typeable ( Typeable )  -- |A meaningless sequence of 0 bits terminated with a 1 bit (easier to implement than the reverse)--- Useful to align an encoded value at byte/word boundaries.-data Filler = FillerBit Filler+-- +-- Used to align encoded values at byte/word boundaries.+data Filler = FillerBit !Filler             | FillerEnd   deriving (Show, Eq, Ord, Typeable, Generic, NFData) @@ -33,6 +35,7 @@   -- use generated decode  -- |A Post aligned value, a value followed by a filler+--  -- Useful to complete the encoding of a top-level value data PostAligned a = PostAligned { postValue :: a, postFiller :: Filler } #ifdef ETA_VERSION    @@ -48,6 +51,7 @@   -- |A Pre aligned value, a value preceded by a filler+--  -- Useful to prealign ByteArrays, Texts and any structure that can be encoded more efficiently when byte aligned.   data PreAligned a = PreAligned { preFiller :: Filler, preValue :: a }   deriving (Show, Eq, Ord, Typeable, Generic, NFData, Flat)@@ -65,11 +69,17 @@ preAligned :: a -> PreAligned a preAligned = PreAligned FillerEnd --- postAlignedDecoder :: Get a -> Get (PostAligned a) -- |Decode a value assuming that is PostAligned postAlignedDecoder :: Get b -> Get b postAlignedDecoder dec = do   v <- dec   _::Filler <- decode-  -- return (postAligned v)   return v++-- |Decode a value assuming that is PreAligned+-- +-- @since 0.5+preAlignedDecoder :: Get b -> Get b+preAlignedDecoder dec = do+  _::Filler <- decode+  dec
src/Flat/Instances/Base.hs view
@@ -1,44 +1,48 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances ,StandaloneDeriving #-}+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE StandaloneDeriving #-}+ -- | Flat instances for the base library-module Flat.Instances.Base() where+module Flat.Instances.Base () where -import Data.Bool-import Data.Char-import Data.Fixed-import Flat.Instances.Util-import Data.Complex(Complex(..))-import Data.Ratio-import Prelude hiding ( mempty )-import           Control.Monad                  ( liftM2 )+import           Control.Monad         (liftM2)+import           Data.Bool+import           Data.Char+import           Data.Complex          (Complex (..))+import           Data.Fixed -- #if MIN_VERSION_base(4,9,0)-import qualified Data.List.NonEmpty as B+import qualified Data.List.NonEmpty    as B -- #endif  #if ! MIN_VERSION_base(4,8,0)-import Control.Applicative-import Data.Monoid (mempty)+import           Control.Applicative+import           Data.Monoid           (mempty) #endif  #if MIN_VERSION_base(4,9,0)-import qualified Data.Semigroup     as Semigroup+import qualified Data.Semigroup        as Semigroup #endif -import qualified Data.Monoid as Monoid+import qualified Data.Monoid           as Monoid+import           Data.Ratio+import           Flat.Instances.Util+import           Prelude               hiding (mempty) -#if !MIN_VERSION_base(4,11,0)-import Data.Monoid ((<>))-#endif+-- #if !MIN_VERSION_base(4,9,0)+-- import           Data.Monoid           ((<>))+-- #endif -#if MIN_VERSION_base(4,8,0)-import Data.Functor.Identity (Identity (..))+#if MIN_VERSION_base(4,9,0)+import           Data.Functor.Identity (Identity (..)) #endif -#if !MIN_VERSION_base(4,9,0)-deriving instance Generic (Complex a)-#endif+-- #if !MIN_VERSION_base(4,9,0)+-- deriving instance Generic (Complex a)+-- #endif +{- ORMOLU_DISABLE -} -- $setup -- >>> :set -XNegativeLiterals -- >>> import Flat.Instances.Test@@ -52,8 +56,35 @@ -- >>> import Data.Monoid -- >>> import qualified Data.List.NonEmpty as B -- >>> let test = tstBits+-- >>> let y = 33+{- ORMOLU_ENABLE -} +-- >>> y++-- | @since 0.4.4 #if MIN_VERSION_base(4,8,0)+instance Flat Monoid.All where+    encode (Monoid.All a) = encode a+    size (Monoid.All a) = size a+    decode = Monoid.All <$> decode++{- |++>>> let w = Just (11::Word8); a = Alt w <> Alt (Just 24) in tst a == tst w+True++>>> let w = Just (11::Word8); a = Alt Nothing <> Alt w in tst a == tst w+True++@since 0.4.4+-}+instance Flat (f a) => Flat (Monoid.Alt f a) where+    encode (Monoid.Alt a) = encode a+    size (Monoid.Alt a) = size a+    decode = Monoid.Alt <$> decode+#endif++#if MIN_VERSION_base(4,9,0) -- | @since 0.4.4 instance Flat a => Flat (Identity a) where     encode (Identity a) = encode a@@ -68,12 +99,6 @@     decode = Monoid.Dual <$> decode  -- | @since 0.4.4-instance Flat Monoid.All where-    encode (Monoid.All a) = encode a-    size (Monoid.All a) = size a-    decode = Monoid.All <$> decode---- | @since 0.4.4 instance Flat Monoid.Any where     encode (Monoid.Any a) = encode a     size (Monoid.Any a) = size a@@ -92,20 +117,6 @@     decode = Monoid.Product <$> decode  #if MIN_VERSION_base(4,9,0)-{- |->>> let w = Just (11::Word8); a = Alt w <> Alt (Just 24) in tst a == tst w -True-->>> let w = Just (11::Word8); a = Alt Nothing <> Alt w in tst a == tst w -True--@since 0.4.4--}-instance Flat (f a) => Flat (Monoid.Alt f a) where-    encode (Monoid.Alt a) = encode a-    size (Monoid.Alt a) = size a-    decode = Monoid.Alt <$> decode- -- | @since 0.4.4 instance Flat a => Flat (Semigroup.Min a) where     encode (Semigroup.Min a) = encode a@@ -129,12 +140,6 @@     encode (Semigroup.Last a) = encode a     size (Semigroup.Last a) = size a     decode = Semigroup.Last <$> decode---- | @since 0.4.4-instance Flat a => Flat (Semigroup.Option a) where-    encode (Semigroup.Option a) = encode a-    size (Semigroup.Option a) = size a-    decode = Semigroup.Option <$> decode #endif  {- |@@ -150,7 +155,7 @@      decode = pure () -{-|+{- | One bit is plenty for a Bool.  >>> test False@@ -166,10 +171,10 @@      decode = dBool -{-|+{- | Char's are mapped to Word32 and then encoded. -For ascii characters, the encoding is standard ascii. +For ascii characters, the encoding is standard ascii.  >>> test 'a' (True,8,"01100001")@@ -203,16 +208,16 @@ -} instance Flat a => Flat (Maybe a) -{-|+{- | >>> test (Left False::Either Bool ()) (True,2,"00")  >>> test (Right ()::Either Bool ()) (True,1,"1") -}-instance ( Flat a, Flat b ) => Flat (Either a b)+instance (Flat a, Flat b) => Flat (Either a b) -{-|+{- | >>> test (MkFixed 123 :: Fixed E0) (True,16,"11110110 00000001") @@ -272,11 +277,11 @@         | V127 @ -Values between as 0 and 127 fit in a single byte. +Values between as 0 and 127 fit in a single byte.  127 (0b1111111) is represented as Elem V127 and encoded as: Elem=0 127=1111111 ->>> test (127::Word) +>>> test (127::Word) (True,8,"01111111")  254 (0b11111110) is represented as Cons V126 (Elem V1) (254=128+126) and encoded as: Cons=1 V126=1111110 (Elem=0 V1=0000001):@@ -302,7 +307,7 @@     decode = dWord  {- |-Naturals are encoded just as the fixed size Words. +Naturals are encoded just as the fixed size Words.  >>> test (0::Natural) (True,8,"00000000")@@ -317,7 +322,6 @@      decode = dNatural - instance Flat Word16 where     encode = eWord16 @@ -339,7 +343,6 @@      size = sWord64 - {- | Integer, Int, Int16, Int32 and Int64 are defined as the <https://developers.google.com/protocol-buffers/docs/encoding#signed-integers ZigZag> encoded version of the equivalent unsigned Word: @@ -382,7 +385,7 @@     decode = dInt  {- |-Integers are encoded just as the fixed size Ints. +Integers are encoded just as the fixed size Ints.  >>> test (0::Integer) (True,8,"00000000")@@ -412,7 +415,7 @@      decode = dInteger -{-|+{- | >>> test (0::Int8) (True,8,"00000000") @@ -490,7 +493,6 @@      decode = dInt64 - {- | Floats are encoded as standard IEEE binary32 values: @@ -532,35 +534,44 @@      decode = dDouble -{-|+{- | >>> test (4 :+ 2 :: Complex Word8) (True,16,"00000100 00000010") -} instance Flat a => Flat (Complex a) -{-|+{- | Ratios are encoded as tuples of (numerator,denominator)  >>> test (3%4::Ratio Word8) (True,16,"00000011 00000100") -}-instance ( Integral a, Flat a ) => Flat (Ratio a) where-    size a = size ( numerator a, denominator a )+instance (Integral a, Flat a) => Flat (Ratio a) where+    size a = size (numerator a, denominator a) -    encode a = encode ( numerator a, denominator a )+    encode a = encode (numerator a, denominator a)      -- decode = uncurry (%) <$> decode     decode = liftM2 (%) decode decode -{-|+{- | >>> test ([]::[Bool]) (True,1,"0")  >>> test [False,False] (True,5,"10100")++This instance and other similar ones are declared as @OVERLAPPABLE@, because for better encoding/decoding+performance it can be useful to declare instances of concrete types, such as @[Char]@ (not provided out of the box). -}-instance {-# OVERLAPPABLE #-}Flat a => Flat [ a ]+instance {-# OVERLAPPABLE #-} Flat a => Flat [a] +{-+>>> import Weigh+>>> flat [1..10::Int]+-}++ -- Generic list instance (stack overflows with ETA, see https://github.com/typelead/eta/issues/901) -- where --size [] n = n+1@@ -578,27 +589,17 @@ -- trampolineIO = id -- #endif -{- |-For better encoding/decoding performance, it is useful to declare instances of concrete list types, such as [Char].-->>> test ""-(True,1,"0")-->>> test "aaa"-(True,28,"10110000 11011000 01101100 0010")--}-instance {-# OVERLAPPING #-}Flat [ Char ]-- -- #if MIN_VERSION_base(4,9,0)-{-|++{- | >>> test (B.fromList [True]) (True,2,"10")  >>> test (B.fromList [False,False]) (True,4,"0100") -}-instance {-# OVERLAPPABLE #-}Flat a => Flat (B.NonEmpty a)+instance {-# OVERLAPPABLE #-} Flat a => Flat (B.NonEmpty a)+ -- #endif  {- |@@ -620,26 +621,33 @@ -}  -- Not sure if these should be OVERLAPPABLE-instance {-# OVERLAPPABLE #-}( Flat a, Flat b ) => Flat ( a, b )--instance {-# OVERLAPPABLE #-}( Flat a, Flat b, Flat c ) => Flat ( a, b, c )--instance {-# OVERLAPPABLE #-}( Flat a, Flat b, Flat c, Flat d )-    => Flat ( a, b, c, d )+instance {-# OVERLAPPABLE #-} (Flat a, Flat b) => Flat (a, b) -instance {-# OVERLAPPABLE #-}( Flat a, Flat b, Flat c, Flat d, Flat e )-    => Flat ( a, b, c, d, e )+instance {-# OVERLAPPABLE #-} (Flat a, Flat b, Flat c) => Flat (a, b, c) -instance {-# OVERLAPPABLE #-}( Flat a, Flat b, Flat c, Flat d, Flat e, Flat f )-    => Flat ( a, b, c, d, e, f )+instance+    {-# OVERLAPPABLE #-}+    (Flat a, Flat b, Flat c, Flat d) =>+    Flat (a, b, c, d) -instance {-# OVERLAPPABLE #-}( Flat a-                             , Flat b-                             , Flat c-                             , Flat d-                             , Flat e-                             , Flat f-                             , Flat g-                             ) => Flat ( a, b, c, d, e, f, g )+instance+    {-# OVERLAPPABLE #-}+    (Flat a, Flat b, Flat c, Flat d, Flat e) =>+    Flat (a, b, c, d, e) +instance+    {-# OVERLAPPABLE #-}+    (Flat a, Flat b, Flat c, Flat d, Flat e, Flat f) =>+    Flat (a, b, c, d, e, f) +instance+    {-# OVERLAPPABLE #-}+    ( Flat a+    , Flat b+    , Flat c+    , Flat d+    , Flat e+    , Flat f+    , Flat g+    ) =>+    Flat (a, b, c, d, e, f, g)
src/Flat/Instances/DList.hs view
@@ -2,9 +2,9 @@   () where -import           Flat.Class-import           Flat.Instances.Mono-import           Data.DList+import           Data.DList          (DList, fromList, toList)+import           Flat.Class          (Flat (..))+import           Flat.Instances.Mono (decodeList, encodeList, sizeList)  -- $setup -- >>> import Flat.Instances.Test
+ src/Flat/Instances/Extra.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE FlexibleInstances #-}+module Flat.Instances.Extra where++import           Flat.Instances.Base ()+import Flat.Class ( Flat )++-- $setup+-- >>> import Flat.Instances.Test++{- |+For better encoding/decoding performance, it is useful to declare instances of concrete list types, such as [Char].++>>> tstBits ""+(True,1,"0")++>>> tstBits "aaa"+(True,28,"10110000 11011000 01101100 0010")+-}+instance {-# OVERLAPPING #-} Flat [Char]+
src/Flat/Instances/Mono.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances,UndecidableInstances ,NoMonomorphismRestriction #-}+{-# LANGUAGE FlexibleContexts          #-}+{-# LANGUAGE FlexibleInstances         #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE UndecidableInstances      #-} module Flat.Instances.Mono   ( sizeSequence   , encodeSequence@@ -20,24 +22,20 @@   ) where -import           Data.MonoTraversable           ( Element-                                                , ofoldl'-                                                , otoList-                                                --, olength-                                                , MonoFoldable-                                                )-import           Data.Sequences                 ( IsSequence )-import qualified Data.Sequences                as S import           Data.Containers+import qualified Data.Foldable        as F+import           Data.MonoTraversable (Element, MonoFoldable, ofoldl', otoList)+import           Data.Sequences       (IsSequence)+import qualified Data.Sequences       as S import           Flat.Instances.Util-import qualified Data.Foldable                 as F --- $setup--- >>> import Flat.Instances.Base()--- >>> import Flat.Instances.Test--- >>> import Data.Word    --- >>> import qualified Data.Set--- >>> import qualified Data.Map+{- $setup+>>> import Flat.Instances.Base()+>>> import Flat.Instances.Test+>>> import Data.Word+>>> import qualified Data.Set+>>> import qualified Data.Map+-}  {-| Sequences are defined as Arrays:@@ -55,23 +53,55 @@ List a ≡  Nil         | Cons a (List a) -The AsList/AsArray wrappers can be used to serialise sequences as Lists or Arrays+In practice, this means that the list elements will be prefixed with a 1 bit and followed by a final 0 bit. ->>> tst $ AsArray ([]::[()])-(True,8,[0])+The AsList/AsArray wrappers can be used to serialise sequences as Lists or Arrays. ->>> tst $ AsArray [11::Word8,22,33]-(True,40,[3,11,22,33,0])+Let's see some examples. ->>> tst $ AsList ([]::[()])-(True,1,[0])+>>> flatBits $ AsList [True,True,True]+"1111110" +So we have Cons True (11) repeated three times, followed by a final Nil (0).++The list encoding is the default one for lists so AsList is in this case unnecessary:++>>> flatBits $ [True,True,True]+"1111110"++We can force a list to be encoded as an Array with AsArray:++>>> flatBits $ AsArray [True,True,True]+"00000011 11100000 000"++We have the initial block with a count of 3 (3 == 00000011) followed by the elements True True True (111) and then the final block of 0 elements ("00000 000").++>>> flatBits $ [AsArray [True,True,True]]+"10000001 11110000 00000"++>>> flatBits $ (True,True,True,AsArray $ replicate 7 True)+"11100000 11111111 11000000 00"++>>> flatBits $ AsArray ([]::[()])+"00000000"++>>> flatBits $ AsList ([]::[()])+"0"+ >>> tst (AsList [11::Word8,22,33]) (True,28,[133,197,164,32])  >>> tst (AsSet (Data.Set.fromList [11::Word8,22,33])) (True,28,[133,197,164,32]) +>>> tst [AsArray [1..3], AsArray [4..8]]+(True,99,[129,129,2,3,0,65,66,2,131,3,132,0,0])++>>> tst $ [AsArray [(1::Word8)..3], AsArray [4..8]]+(True,99,[129,128,129,1,128,65,65,1,65,129,194,0,0])++>>> tst $ [AsArray [(1::Int)..3]]+(True,42,[129,129,2,3,0,0]) -} newtype AsArray a =   AsArray@@ -83,9 +113,13 @@   encode (AsArray a) = encodeSequence a   decode = AsArray <$> decodeSequence --- |Calculate size of an instance of IsSequence as the sum:--- * of the size of all the elements--- * plus the size of the array constructors (1 byte every 255 elements plus one final byte)+{- |+Calculate size of an instance of IsSequence as the sum:++* of the size of all the elements++* plus the size of the array constructors (1 byte every 255 elements plus one final byte)+-} sizeSequence   :: (IsSequence mono, Flat (Element mono)) => mono -> NumBits -> NumBits sizeSequence s acc =@@ -145,7 +179,7 @@   decode = AsSet <$> decodeSet  sizeSet :: (IsSet set, Flat (Element set)) => Size set-sizeSet l acc = ofoldl' (\acc e -> size e (acc + 1)) (acc + 1) $ l+sizeSet l acc = ofoldl' (\acc e -> size e (acc + 1)) (acc + 1) l {-# INLINE sizeSet #-}  encodeSet :: (IsSet set, Flat (Element set)) => set -> Encoding
src/Flat/Instances/Test.hs view
@@ -1,36 +1,36 @@ -- | doctest utilities-module Flat.Instances.Test-  ( tst-  , tstBits-  , asList-  , flatBits-  , allBits-  , prettyShow-  , module Data.Word-  )-where+module Flat.Instances.Test (+    tst,+    tstBits,+    asList,+    flatBits,+    allBits,+    encBits,+    prettyShow,+    module Data.Word,+) where -import           Flat.Class                     ( Flat(..) )-import           Flat.Run                       ( flat-                                                , unflat-                                                )-import           Flat.Bits                      ( bits-                                                , asBytes-                                                , paddedBits-                                                )-import           Flat.Types                     ( NumBits )+import           Control.Monad                  ((>=>)) import           Data.Word-import           Text.PrettyPrint.HughesPJClass ( prettyShow )+import           Flat.Bits                      (Bits, asBytes, bits,+                                                 paddedBits, takeBits)+import           Flat.Class                     (Flat (..))+import           Flat.Encoder.Prim              (eFillerF)+import           Flat.Encoder.Strict            (Encoding (Encoding),+                                                 numEncodedBits, strictEncoder)+import           Flat.Run                       (flat, unflat)+import           Flat.Types                     (NumBits)+import           Text.PrettyPrint.HughesPJClass (prettyShow) --- |Returns: result of flat/unflat test, encoding size in bits, byte encoding+-- | Returns: result of flat/unflat test, encoding size in bits, byte encoding tst :: (Eq a, Flat a) => a -> (Bool, NumBits, [Word8]) tst v = (unflat (flat v) == Right v, size v 0, showBytes v) --- |Returns: result of flat/unflat test, encoding size in bits, bits encoding+-- | Returns: result of flat/unflat test, encoding size in bits, bits encoding tstBits :: (Eq a, Flat a) => a -> (Bool, NumBits, String) tstBits v = (unflat (flat v) == Right v, Flat.Class.size v 0, flatBits v) --- |Test that container is serialised as a List+-- | Test that container is serialised as a List asList :: (Eq a1, Eq a2, Flat a1, Flat a2) => (a2 -> a1) -> a2 -> Bool asList f l = tst (f l) == tst l @@ -39,6 +39,10 @@  allBits :: Flat a => a -> String allBits = prettyShow . paddedBits++-- |@since 0.5+encBits :: NumBits -> Encoding -> Bits+encBits maxNumBits e@(Encoding enc) = takeBits (numEncodedBits maxNumBits e) (strictEncoder maxNumBits (Encoding $ enc >=> eFillerF))  showBytes :: Flat a => a -> [Word8] showBytes = asBytes . bits
src/Flat/Instances/Text.hs view
@@ -39,7 +39,7 @@ (True,120,[1,12,240,144,141,136,240,144,141,136,240,144,141,136,0]) #endif -Strict and Lazy Text has the same encoding:+Strict and Lazy Text have the same encoding:  >>> tst (T.pack "abc") == tst (TL.pack "abc") True
src/Flat/Memory.hs view
@@ -5,7 +5,7 @@ {- | Memory access primitives. -Includes code from the store-core package.+Includes code from the [store-core](https://hackage.haskell.org/package/store-core) package. -} module Flat.Memory   ( chunksToByteString@@ -15,10 +15,11 @@   , pokeByteString   , unsafeCreateUptoN'   , minusPtr+  --, peekByteString   ) where -import           Control.Monad+import Control.Monad ( foldM_, when ) import           Control.Monad.Primitive        ( PrimMonad(..) ) import qualified Data.ByteString.Internal      as BS import           Data.Primitive.ByteArray       ( MutableByteArray(..)@@ -27,7 +28,7 @@                                                 , newByteArray                                                 , unsafeFreezeByteArray                                                 )-import           Foreign                 hiding ( void )+import Foreign ( Word8, Ptr, withForeignPtr, minusPtr, plusPtr ) import           GHC.Prim                       ( copyAddrToByteArray#                                                 , copyByteArrayToAddr#                                                 )@@ -35,7 +36,7 @@ import           GHC.Types                      ( IO(..)                                                 , Int(..)                                                 )-import           System.IO.Unsafe+import System.IO.Unsafe ( unsafeDupablePerformIO, unsafePerformIO ) import qualified Data.ByteString               as B  unsafeCreateUptoN' :: Int -> (Ptr Word8 -> IO (Int, a)) -> (BS.ByteString, a)@@ -64,6 +65,11 @@       sourceLength     return (destPointer `plusPtr` sourceLength) +-- Create a new bytestring, copying from sourcePtr sourceLength number of bytes+-- peekByteString :: Ptr Word8 -> Int -> BS.ByteString+-- peekByteString sourcePtr sourceLength = BS.unsafeCreate sourceLength $ \destPointer -> BS.memcpy destPointer sourcePtr sourceLength++-- |Copy ByteArray to given pointer, returns new pointer pokeByteArray :: ByteArray# -> Int -> Int -> Ptr Word8 -> IO (Ptr Word8) pokeByteArray sourceArr sourceOffset len dest = do   copyByteArrayToAddr sourceArr sourceOffset dest len@@ -71,19 +77,18 @@   return dest' {-# INLINE pokeByteArray #-} + -- | Wrapper around @copyByteArrayToAddr#@ primop.+-- -- Copied from the store-core package copyByteArrayToAddr :: ByteArray# -> Int -> Ptr a -> Int -> IO () copyByteArrayToAddr arr (I# offset) (Ptr addr) (I# len) =   IO (\s -> (# copyByteArrayToAddr# arr offset addr len s, () #)) {-# INLINE copyByteArrayToAddr #-} --- toByteString :: Ptr Word8 -> Int -> BS.ByteString--- toByteString sourcePtr sourceLength = BS.unsafeCreate sourceLength $ \destPointer -> BS.memcpy destPointer sourcePtr sourceLength- chunksToByteString :: (Ptr Word8, [Int]) -> BS.ByteString chunksToByteString (sourcePtr0, lens) =-  BS.unsafeCreate (sum lens) $ \destPtr0 -> void $ foldM+  BS.unsafeCreate (sum lens) $ \destPtr0 -> foldM_     (\(destPtr, sourcePtr) sourceLength ->       BS.memcpy destPtr sourcePtr sourceLength         >> return@@ -110,6 +115,7 @@   -- | Wrapper around @copyAddrToByteArray#@ primop.+--  -- Copied from the store-core package copyAddrToByteArray   :: Ptr a -> MutableByteArray (PrimState IO) -> Int -> Int -> IO ()
+ src/Flat/Repr.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE InstanceSigs        #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Flat.Repr where++import qualified Data.ByteString    as B+import           Flat.Class         (Flat (..))+import           Flat.Decoder.Types (Get)+import           Flat.Run           (flat, unflat)++-- $setup+-- >>> :set -XScopedTypeVariables+-- >>> import Flat.Instances.Base+-- >>> import Flat.Decoder.Types+-- >>> import Flat.Types+-- >>> import Flat.Run+-- >>> import Flat.Class++{- | Flat representation of a value++== Repr +It is occasionally useful to keep a decoded value, or part of it, in its encoded binary representation and decode it later on demand.++To do so, just decode a value `a` to a `Repr a`.++For example, we encode a list of Ints and then decode it to a list of Repr Int:++>>> unflat (flat [1::Int .. 5]) :: Decoded ([Repr Int])+Right [Repr {repr = "\STX\SOH"},Repr {repr = "\EOT\SOH"},Repr {repr = "\ACK\SOH"},Repr {repr = "\b\SOH"},Repr {repr = "\n\SOH"}]++To decode a `Repr a` to an `a`, we use `unrepr`:++>>> let Right l = unflat (flat [1..5]) :: Decoded [Repr Int] in unrepr (l  !! 2)+3++See "test/FlatRepr.hs" for a test and a longer example of use.++== SizeOf+If a decoded value is not required, it can be skipped completely using `SizeOf a`.++For example, to ignore the second and fourth component of the following tuple, it can be decoded as:++>>> let v = flat ('a',"abc",'z',True) in unflat v :: Decoded (Char,SizeOf String,Char,SizeOf Bool)+Right ('a',SizeOf 28,'z',SizeOf 1)++The unused values have not been decoded and instead their size (in bits) is returned.+-}++newtype Repr a = Repr {repr :: B.ByteString} deriving Show++-- Get the underlying value+unrepr :: Flat a => Repr a -> a+unrepr (Repr bs)=+    case unflat bs of+        Right a -> a+        Left _  -> error "impossible"++instance Flat a => Flat (Repr a) where+    size = error "unused"+    encode = error "unused"++    -- To create the representation we just re 'flat' the parsed value (this could be optimised by copying directly the parsed representation)+    decode = Repr . flat <$> (decode :: Get a)
src/Flat/Run.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+ -- |Encoding and decoding functions module Flat.Run (     flat,@@ -10,21 +11,21 @@     unflatWith,     unflatRaw,     unflatRawWith,-    ) where+) where -import qualified Data.ByteString         as B-import           Data.ByteString.Convert-import           Flat.Class-import           Flat.Decoder-import qualified Flat.Encoder       as E-import           Flat.Filler+import qualified Data.ByteString as B+import Data.ByteString.Convert (AsByteString (..))+import Flat.Class (Flat (decode, encode), getSize)+import Flat.Decoder (Decoded, Get, strictDecoder)+import qualified Flat.Encoder as E+import Flat.Filler (postAligned, postAlignedDecoder)  -- |Encode padded value. flat :: Flat a => a -> B.ByteString flat = flatRaw . postAligned  -- |Decode padded value.-unflat :: (Flat a,AsByteString b) => b -> Decoded a+unflat :: (Flat a, AsByteString b) => b -> Decoded a unflat = unflatWith decode  -- |Decode padded value, using the provided unpadded decoder.@@ -32,7 +33,7 @@ unflatWith dec = unflatRawWith (postAlignedDecoder dec)  -- |Decode unpadded value.-unflatRaw :: (Flat a,AsByteString b) => b -> Decoded a+unflatRaw :: (Flat a, AsByteString b) => b -> Decoded a unflatRaw = unflatRawWith decode  -- |Unflat unpadded value, using provided decoder@@ -41,16 +42,18 @@  -- |Encode unpadded value flatRaw :: (Flat a, AsByteString b) => a -> b-flatRaw a = fromByteString $ -    E.strictEncoder -        (getSize a) -#ifdef ETA_VERSION    +flatRaw a =+    fromByteString $+        E.strictEncoder+            (getSize a)++#ifdef ETA_VERSION         (E.trampolineEncoding (encode a)) #else         (encode a) #endif --- #ifdef ETA_VERSION    +-- #ifdef ETA_VERSION --   deriving (Show, Eq, Ord, Typeable, Generic, NFData)  -- instance Flat a => Flat (PostAligned a) where@@ -59,6 +62,3 @@ -- #else --   deriving (Show, Eq, Ord, Typeable, Generic, NFData,Flat) -- #endif---
src/Flat/Tutorial.hs view
@@ -100,62 +100,6 @@  >>> flatBits $ Just True "11"--== Compatibility-#compatibility#--=== <https://www.haskell.org/ghc/ GHC>--* x32 and x64: 7.10.3, 8.0.2, 8.2.2, 8.4.4, 8.6.5, 8.8.3.--* <https://en.wikipedia.org/wiki/ARM7 ARM7-armv7hf> and <https://en.wikipedia.org/wiki/ARM_architecture#AArch64_features ARM8-aaarch64>: 8.0.2. --=== <https://github.com/ghcjs/ghcjs GHCJS>--* @ghcjs-8.4.0.1@.--NOTE: Some tests are not run for @ghcjs@ as they are related to unsupported features such as UTF16 encoding of Text and short <https://hackage.haskell.org/package/bytestring/docs/Data-ByteString-Short.html ByteString>.--For details of what tests are skipped search @test/Spec.hs@ for @ghcjs_HOST_OS@.--NOTE: Some older versions of @ghcjs@ and versions of @flat@ prior to 0.33 encoded @Double@ values incorrectly when not aligned with a byte boundary.--=== <https://eta-lang.org/ ETA>--It builds (with @etlas 1.5.0.0@ and @eta-0.8.6b2@) and passes the @doctest-static@ test but it won't complete the main @spec@ test probably because of a recursive iteration issue, see <https://github.com/typelead/eta/issues/901>.--Support for @eta@ is not currently being actively mantained.--== Known Bugs and Infelicities-#known-bugs-and-infelicities#--=== Longish compilation times--Relies more than other serialisation libraries on extensive inlining for its good performance, this unfortunately leads to longer compilation times.--If you have many data types or very large ones this might become an issue.--A couple of good practices that will eliminate or mitigate this problem are:---   During development, turn optimisations off (@stack --fast@ or @-O0@-    in the cabal file).---   Keep your serialisation code in a separate module(s).--=== Data types with more than 512 constructors are currently unsupported--This limit could be easily extended, shout if you need it.--=== Other--<https://github.com/Quid2/flat/issues Full list of open issues>.--== Acknowledgements-#acknowledgements#--@flat@ reuses ideas and readapts code from various packages, mainly:-@store@, @binary-bits@ and @binary@ and includes contributions from-Justus Sagemüller. -}  
− stack-6.35.yaml
@@ -1,13 +0,0 @@-resolver: lts-6.35--packages:-  - .--allow-newer: true--extra-deps:-  - quickcheck-instances-0.3.22-  - QuickCheck-2.13.2-  - splitmix-0.0.2-  - time-compat-1.9.3-  - hashable-1.2.6.1
− stack-9.21.yaml
@@ -1,13 +0,0 @@-resolver: lts-9.21--packages:-  - .--allow-newer: true--extra-deps:-  - quickcheck-instances-0.3.22-  - QuickCheck-2.13.2-  - splitmix-0.0.2-  - time-compat-1.9.3-  - hashable-1.2.6.1
stack.yaml view
@@ -1,10 +1,43 @@-resolver: lts-14.27+# For ghc 7.10.3, use cabal instead +# Supported stack versions++# resolver: lts-9.21 # ghc 8.0.2++# resolver: lts-11.22 # ghc 8.2.2++# resolver: lts-12.26 # ghc 8.4.4++# resolver: lts-14.27 # ghc 8.6.5++# resolver: lts-16.31 # ghc 8.8.4++resolver: lts-18.28 # ghc 8.10.7++# resolver: lts-19.26 # ghc 9.0.2++# resolver: nightly-2022-09-30 # ghc 9.2.4+ packages:   - .-#  - ../EXTERNAL/doctest +  # for test only+  # - ../EXTERNAL/doctest+ extra-deps:-  # Modified doctest, used to generate static tests-  # - git: https://github.com/tittoassini/doctest-  #   commit: c9cdbe4eee086cb8aa46e96532160320dd367f09+  # Modified doctest, used to generate static tests (run by doc-static)+  - git: https://github.com/tittoassini/doctest+    commit: 3954e94449901764e28cfed1c35490af970e9b01++  # - hashable-1.4.0.2@sha256:0cddd0229d1aac305ea0404409c0bbfab81f075817bd74b8b2929eff58333e55,5005++  # for ghcjs-cons+  # - jsaddle-0.9.8.2@sha256:e8c003801eb9364fcd6b1e0cda34f072a537bcfa767e6eb8c626836dae77ba04,4419+  # - ref-tf-0.4.0.2@sha256:69de3550250e0cd69f45d080359cb314a9487c915024349c75b78732bbee9332,1134++  # for text-2.0:+  # - text-2.0+  # - Cabal-3.6.3.0@sha256:ff97c442b0c679c1c9876acd15f73ac4f602b973c45bde42b43ec28265ee48f4,12459+  # - parsec-3.1.15.0@sha256:a162d4cc8884014ba35192545cad293af0529fe11497aad8834bbaaa3dfffc26,4429++allow-newer: true
test/DocTest/Data/FloatCast.hs view
@@ -8,4 +8,4 @@ import Data.Word  tests :: IO TestTree-tests = testGroup "Data.FloatCast" <$> sequence [  DocTest.testProp "src/Data/FloatCast.hs:41" ( \f -> wordToFloat (floatToWord f ) == f ),  DocTest.test "src/Data/FloatCast.hs:43" "[ExpectedLine [LineChunk \"3189768192\"]]" (DocTest.asPrint( floatToWord (-0.15625) )),  DocTest.test "src/Data/FloatCast.hs:46" "[ExpectedLine [LineChunk \"-0.15625\"]]" (DocTest.asPrint( wordToFloat 3189768192 )),  DocTest.test "src/Data/FloatCast.hs:49" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( floatToWord (-5.828125) == 0xC0BA8000 )),  DocTest.testProp "src/Data/FloatCast.hs:67" ( \f -> wordToDouble (doubleToWord f ) == f ),  DocTest.test "src/Data/FloatCast.hs:69" "[ExpectedLine [LineChunk \"\\\"3ff0000000000002\\\"\"]]" (DocTest.asPrint( showHex (doubleToWord 1.0000000000000004) "" )),  DocTest.test "src/Data/FloatCast.hs:72" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( doubleToWord 1.0000000000000004 == 0x3FF0000000000002 )),  DocTest.test "src/Data/FloatCast.hs:75" "[ExpectedLine [LineChunk \"\\\"bfc4000000000000\\\"\"]]" (DocTest.asPrint( showHex (doubleToWord (-0.15625)) "" )),  DocTest.test "src/Data/FloatCast.hs:78" "[ExpectedLine [LineChunk \"-0.15625\"]]" (DocTest.asPrint( wordToDouble 0xbfc4000000000000 )),  DocTest.test "src/Data/FloatCast.hs:93" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( runST (cast (0xF0F1F2F3F4F5F6F7::Word64)) == (0xF0F1F2F3F4F5F6F7::Word64) ))]+tests = testGroup "Data.FloatCast" <$> sequence [  DocTest.testProp "src/Data/FloatCast.hs:42" ( \f -> wordToFloat (floatToWord f ) == f ),  DocTest.test "src/Data/FloatCast.hs:45" "[ExpectedLine [LineChunk \"3189768192\"]]" (DocTest.asPrint( floatToWord (-0.15625) )),  DocTest.test "src/Data/FloatCast.hs:48" "[ExpectedLine [LineChunk \"-0.15625\"]]" (DocTest.asPrint( wordToFloat 3189768192 )),  DocTest.test "src/Data/FloatCast.hs:51" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( floatToWord (-5.828125) == 0xC0BA8000 )),  DocTest.testProp "src/Data/FloatCast.hs:70" ( \f -> wordToDouble (doubleToWord f ) == f ),  DocTest.test "src/Data/FloatCast.hs:73" "[ExpectedLine [LineChunk \"\\\"3ff0000000000002\\\"\"]]" (DocTest.asPrint( showHex (doubleToWord 1.0000000000000004) "" )),  DocTest.test "src/Data/FloatCast.hs:76" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( doubleToWord 1.0000000000000004 == 0x3FF0000000000002 )),  DocTest.test "src/Data/FloatCast.hs:79" "[ExpectedLine [LineChunk \"\\\"bfc4000000000000\\\"\"]]" (DocTest.asPrint( showHex (doubleToWord (-0.15625)) "" )),  DocTest.test "src/Data/FloatCast.hs:82" "[ExpectedLine [LineChunk \"-0.15625\"]]" (DocTest.asPrint( wordToDouble 0xbfc4000000000000 )),  DocTest.test "src/Data/FloatCast.hs:97" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( runST (cast (0xF0F1F2F3F4F5F6F7::Word64)) == (0xF0F1F2F3F4F5F6F7::Word64) ))]
test/DocTest/Data/ZigZag.hs view
@@ -8,7 +8,8 @@ import Data.Word import Data.Int import Numeric.Natural-import Test.QuickCheck.Instances.Natural+import Test.QuickCheck.Arbitrary+instance Arbitrary Natural where arbitrary = arbitrarySizedNatural; shrink    = shrinkIntegral  tests :: IO TestTree-tests = testGroup "Data.ZigZag" <$> sequence [  DocTest.testProp "src/Data/ZigZag.hs:66" ( \(f::Integer) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:68" ( \(f::Natural) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:70" ( \(f::Int8) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:71" ( \(f::Word8) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:72" ( \(s::Int8) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer)) ),  DocTest.testProp "src/Data/ZigZag.hs:73" ( \(u::Word8) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural)) ),  DocTest.testProp "src/Data/ZigZag.hs:75" ( \(f::Int64) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:76" ( \(f::Word64) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:77" ( \(s::Int64) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer)) ),  DocTest.testProp "src/Data/ZigZag.hs:78" ( \(u::Word64) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural)) ),  DocTest.test "src/Data/ZigZag.hs:33" "[ExpectedLine [LineChunk \"0\"]]" (DocTest.asPrint( zigZag (0::Int8) )),  DocTest.test "src/Data/ZigZag.hs:36" "[ExpectedLine [LineChunk \"1\"]]" (DocTest.asPrint( zigZag (-1::Int16) )),  DocTest.test "src/Data/ZigZag.hs:39" "[ExpectedLine [LineChunk \"2\"]]" (DocTest.asPrint( zigZag (1::Int32) )),  DocTest.test "src/Data/ZigZag.hs:42" "[ExpectedLine [LineChunk \"3\"]]" (DocTest.asPrint( zigZag (-2::Int16) )),  DocTest.test "src/Data/ZigZag.hs:45" "[ExpectedLine [LineChunk \"99\"]]" (DocTest.asPrint( zigZag (-50::Integer) )),  DocTest.test "src/Data/ZigZag.hs:48" "[ExpectedLine [LineChunk \"100\"]]" (DocTest.asPrint( zigZag (50::Integer) )),  DocTest.test "src/Data/ZigZag.hs:51" "[ExpectedLine [LineChunk \"128\"]]" (DocTest.asPrint( zigZag (64::Integer) )),  DocTest.test "src/Data/ZigZag.hs:54" "[ExpectedLine [LineChunk \"511\"]]" (DocTest.asPrint( zigZag (-256::Integer) )),  DocTest.test "src/Data/ZigZag.hs:57" "[ExpectedLine [LineChunk \"512\"]]" (DocTest.asPrint( zigZag (256::Integer) )),  DocTest.test "src/Data/ZigZag.hs:60" "[ExpectedLine [LineChunk \"[5,3,1,0,2,4,6]\"]]" (DocTest.asPrint( map zigZag [-3..3::Integer] )),  DocTest.test "src/Data/ZigZag.hs:63" "[ExpectedLine [LineChunk \"[0,-1,1,-2,2,-3,3]\"]]" (DocTest.asPrint( map zagZig [0..6::Word8] ))]+tests = testGroup "Data.ZigZag" <$> sequence [  DocTest.testProp "src/Data/ZigZag.hs:67" ( \(f::Integer) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:70" ( \(f::Natural) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:73" ( \(f::Int8) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:76" ( \(f::Word8) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:79" ( \(s::Int8) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer)) ),  DocTest.testProp "src/Data/ZigZag.hs:82" ( \(u::Word8) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural)) ),  DocTest.testProp "src/Data/ZigZag.hs:85" ( \(f::Int64) -> zagZig (zigZag f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:88" ( \(f::Word64) -> zigZag (zagZig f) == f ),  DocTest.testProp "src/Data/ZigZag.hs:91" ( \(s::Int64) -> zigZag s == fromIntegral (zigZag (fromIntegral s :: Integer)) ),  DocTest.testProp "src/Data/ZigZag.hs:94" ( \(u::Word64) -> zagZig u == fromIntegral (zagZig (fromIntegral u :: Natural)) ),  DocTest.test "src/Data/ZigZag.hs:34" "[ExpectedLine [LineChunk \"0\"]]" (DocTest.asPrint( zigZag (0::Int8) )),  DocTest.test "src/Data/ZigZag.hs:37" "[ExpectedLine [LineChunk \"1\"]]" (DocTest.asPrint( zigZag (-1::Int16) )),  DocTest.test "src/Data/ZigZag.hs:40" "[ExpectedLine [LineChunk \"2\"]]" (DocTest.asPrint( zigZag (1::Int32) )),  DocTest.test "src/Data/ZigZag.hs:43" "[ExpectedLine [LineChunk \"3\"]]" (DocTest.asPrint( zigZag (-2::Int16) )),  DocTest.test "src/Data/ZigZag.hs:46" "[ExpectedLine [LineChunk \"99\"]]" (DocTest.asPrint( zigZag (-50::Integer) )),  DocTest.test "src/Data/ZigZag.hs:49" "[ExpectedLine [LineChunk \"100\"]]" (DocTest.asPrint( zigZag (50::Integer) )),  DocTest.test "src/Data/ZigZag.hs:52" "[ExpectedLine [LineChunk \"128\"]]" (DocTest.asPrint( zigZag (64::Integer) )),  DocTest.test "src/Data/ZigZag.hs:55" "[ExpectedLine [LineChunk \"511\"]]" (DocTest.asPrint( zigZag (-256::Integer) )),  DocTest.test "src/Data/ZigZag.hs:58" "[ExpectedLine [LineChunk \"512\"]]" (DocTest.asPrint( zigZag (256::Integer) )),  DocTest.test "src/Data/ZigZag.hs:61" "[ExpectedLine [LineChunk \"[5,3,1,0,2,4,6]\"]]" (DocTest.asPrint( map zigZag [-3..3::Integer] )),  DocTest.test "src/Data/ZigZag.hs:64" "[ExpectedLine [LineChunk \"[0,-1,1,-2,2,-3,3]\"]]" (DocTest.asPrint( map zagZig [0..6::Word8] ))]
test/DocTest/Flat/Bits.hs view
@@ -6,7 +6,7 @@ import Flat.Bits import Data.Word import Flat.Instances.Base-import Flat.Instances.Test+import Flat.Instances.Test(tst,prettyShow)  tests :: IO TestTree-tests = testGroup "Flat.Bits" <$> sequence [  DocTest.test "src/Flat/Bits.hs:44" "[ExpectedLine [LineChunk \"[True]\"]]" (DocTest.asPrint( bits True )),  DocTest.test "src/Flat/Bits.hs:55" "[ExpectedLine [LineChunk \"[True,False,False,False,False,False,False,True]\"]]" (DocTest.asPrint( paddedBits True )),  DocTest.test "src/Flat/Bits.hs:71" "[ExpectedLine [LineChunk \"[False,False,False,False,False,True,False,True]\"]]" (DocTest.asPrint( asBits (5::Word8) )),  DocTest.test "src/Flat/Bits.hs:79" "[ExpectedLine [LineChunk \"[1,3]\"]]" (DocTest.asPrint( asBytes $ asBits (256+3::Word16) )),  DocTest.test "src/Flat/Bits.hs:96" "[ExpectedLine [LineChunk \"\\\"00000001 00000011\\\"\"]]" (DocTest.asPrint( prettyShow $ asBits (256+3::Word16) ))]+tests = testGroup "Flat.Bits" <$> sequence [  DocTest.test "src/Flat/Bits.hs:50" "[ExpectedLine [LineChunk \"[True]\"]]" (DocTest.asPrint( bits True )),  DocTest.test "src/Flat/Bits.hs:62" "[ExpectedLine [LineChunk \"[True,False,False,False,False,False,False,True]\"]]" (DocTest.asPrint( paddedBits True )),  DocTest.test "src/Flat/Bits.hs:82" "[ExpectedLine [LineChunk \"[False,False,False,False,False,True,False,True]\"]]" (DocTest.asPrint( asBits (5::Word8) )),  DocTest.test "src/Flat/Bits.hs:90" "[ExpectedLine [LineChunk \"[1,3]\"]]" (DocTest.asPrint( asBytes $ asBits (256+3::Word16) )),  DocTest.test "src/Flat/Bits.hs:106" "[ExpectedLine [LineChunk \"\\\"00000001 00000011\\\"\"]]" (DocTest.asPrint( prettyShow $ asBits (256+3::Word16) ))]
test/DocTest/Flat/Decoder/Prim.hs view
@@ -8,6 +8,8 @@ import Data.Word import Data.Int import Flat.Run+import Flat.Bits+import Text.PrettyPrint.HughesPJClass (Pretty (pPrint))  tests :: IO TestTree-tests = testGroup "Flat.Decoder.Prim" <$> sequence [  DocTest.test "src/Flat/Decoder/Prim.hs:187" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( unflatWith (dBEBits8 3) [0b11100001::Word8] == Right 0b00000111 ))]+tests = testGroup "Flat.Decoder.Prim" <$> sequence [  DocTest.test "src/Flat/Decoder/Prim.hs:199" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( unflatWith (dBEBits8 3) [0b11100001::Word8] == Right 0b00000111 )),  DocTest.test "src/Flat/Decoder/Prim.hs:202" "[ExpectedLine [LineChunk \"Left (BadOp \\\"read8: cannot read 9 bits\\\")\"]]" (DocTest.asPrint( unflatWith (dBEBits8 9) [0b11100001::Word8,0b11111111] )),  DocTest.test "src/Flat/Decoder/Prim.hs:215" "[ExpectedLine [LineChunk \"Right 00000101 10111111\"]]" (DocTest.asPrint( pPrint . asBits <$> unflatWith (dBEBits16 11) [0b10110111::Word8,0b11100001] )),  DocTest.test "src/Flat/Decoder/Prim.hs:220" "[ExpectedLine [LineChunk \"Right 00000111 11111111\"]]" (DocTest.asPrint( pPrint . asBits <$> unflatWith (dBEBits16 19) [0b00000000::Word8,0b11111111,0b11100001] ))]
+ test/DocTest/Flat/Encoder/Prim.hs view
@@ -0,0 +1,14 @@++{-# LANGUAGE NoMonomorphismRestriction, ExtendedDefaultRules#-}+module DocTest.Flat.Encoder.Prim where+import qualified DocTest+import Test.Tasty(TestTree,testGroup)+import Flat.Encoder.Prim+import Flat.Instances.Test+import Flat.Bits+import Flat.Encoder.Strict+import Control.Monad+enc e = prettyShow $ encBits 256 (Encoding e)++tests :: IO TestTree+tests = testGroup "Flat.Encoder.Prim" <$> sequence [  DocTest.test "src/Flat/Encoder/Prim.hs:376" "[ExpectedLine [LineChunk \"\\\"1\\\"\"]]" (DocTest.asPrint( enc eTrueF )),  DocTest.test "src/Flat/Encoder/Prim.hs:384" "[ExpectedLine [LineChunk \"\\\"0\\\"\"]]" (DocTest.asPrint( enc eFalseF )),  DocTest.test "src/Flat/Encoder/Prim.hs:394" "[ExpectedLine [LineChunk \"\\\"10000001\\\"\"]]" (DocTest.asPrint( enc $ eTrueF >=> eFillerF )),  DocTest.test "src/Flat/Encoder/Prim.hs:397" "[ExpectedLine [LineChunk \"\\\"00000001\\\"\"]]" (DocTest.asPrint( enc eFillerF )),  DocTest.test "src/Flat/Encoder/Prim.hs:430" "[ExpectedLine [LineChunk \"\\\"11111111\\\"\"]]" (DocTest.asPrint( enc $ \s-> eWord8F 0 s >>= updateWord8 255 s )),  DocTest.test "src/Flat/Encoder/Prim.hs:433" "[ExpectedLine [LineChunk \"\\\"10000000 01111111 1\\\"\"]]" (DocTest.asPrint( enc $ \s0 -> eTrueF s0 >>= \s1 -> eWord8F 255 s1 >>= eWord8F 255 >>= updateWord8 0 s1 )),  DocTest.test "src/Flat/Encoder/Prim.hs:436" "[ExpectedLine [LineChunk \"\\\"01111111 1\\\"\"]]" (DocTest.asPrint( enc $ \s0 -> eFalseF s0 >>= \s1 -> eWord8F 0 s1 >>= updateWord8 255 s1 )),  DocTest.test "src/Flat/Encoder/Prim.hs:439" "[ExpectedLine [LineChunk \"\\\"01111111 10\\\"\"]]" (DocTest.asPrint( enc $ \s0 -> eFalseF s0 >>= \s1 -> eWord8F 0 s1 >>= updateWord8 255 s1 >>= eFalseF )),  DocTest.test "src/Flat/Encoder/Prim.hs:442" "[ExpectedLine [LineChunk \"\\\"10000000 011\\\"\"]]" (DocTest.asPrint( enc $ \s0 -> eTrueF s0 >>= \s1 -> eWord8F 255 s1 >>= eTrueF >>= updateWord8 0 s1 >>= eTrueF ))]
test/DocTest/Flat/Endian.hs view
@@ -7,4 +7,4 @@ import Numeric (showHex)  tests :: IO TestTree-tests = testGroup "Flat.Endian" <$> sequence [  DocTest.test "src/Flat/Endian.hs:36" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE64 0xF0F1F2F3F4F5F6F7 == if isBigEndian then 0xF0F1F2F3F4F5F6F7 else 0xF7F6F5F4F3F2F1F0 )),  DocTest.test "src/Flat/Endian.hs:49" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE32 0xF0F1F2F3 == if isBigEndian then 0xF0F1F2F3 else 0xF3F2F1F0 )),  DocTest.test "src/Flat/Endian.hs:62" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE16 0xF0F1 == if isBigEndian then 0xF0F1 else 0xF1F0 ))]+tests = testGroup "Flat.Endian" <$> sequence [  DocTest.test "src/Flat/Endian.hs:38" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE64 0xF0F1F2F3F4F5F6F7 == if isBigEndian then 0xF0F1F2F3F4F5F6F7 else 0xF7F6F5F4F3F2F1F0 )),  DocTest.test "src/Flat/Endian.hs:51" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE32 0xF0F1F2F3 == if isBigEndian then 0xF0F1F2F3 else 0xF3F2F1F0 )),  DocTest.test "src/Flat/Endian.hs:64" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( toBE16 0xF0F1 == if isBigEndian then 0xF0F1 else 0xF1F0 ))]
test/DocTest/Flat/Instances/Base.hs view
@@ -16,6 +16,7 @@ import Data.Monoid import qualified Data.List.NonEmpty as B test = tstBits+y = 33  tests :: IO TestTree-tests = testGroup "Flat.Instances.Base" <$> sequence [  DocTest.test "src/Flat/Instances/Base.hs:96" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( let w = Just (11::Word8); a = Alt w <> Alt (Just 24) in tst a == tst w )),  DocTest.test "src/Flat/Instances/Base.hs:99" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( let w = Just (11::Word8); a = Alt Nothing <> Alt w in tst a == tst w )),  DocTest.test "src/Flat/Instances/Base.hs:143" "[ExpectedLine [LineChunk \"(True,0,\\\"\\\")\"]]" (DocTest.asPrint( test () )),  DocTest.test "src/Flat/Instances/Base.hs:156" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test False )),  DocTest.test "src/Flat/Instances/Base.hs:159" "[ExpectedLine [LineChunk \"(True,1,\\\"1\\\")\"]]" (DocTest.asPrint( test True )),  DocTest.test "src/Flat/Instances/Base.hs:174" "[ExpectedLine [LineChunk \"(True,8,\\\"01100001\\\")\"]]" (DocTest.asPrint( test 'a' )),  DocTest.test "src/Flat/Instances/Base.hs:179" "[ExpectedLine [LineChunk \"(True,16,\\\"11001000 00000001\\\")\"]]" (DocTest.asPrint( test 'È' )),  DocTest.test "src/Flat/Instances/Base.hs:182" "[ExpectedLine [LineChunk \"(True,24,\\\"10001101 10011100 00000001\\\")\"]]" (DocTest.asPrint( test '不' )),  DocTest.test "src/Flat/Instances/Base.hs:198" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test (Nothing::Maybe Bool) )),  DocTest.test "src/Flat/Instances/Base.hs:201" "[ExpectedLine [LineChunk \"(True,2,\\\"10\\\")\"]]" (DocTest.asPrint( test (Just False::Maybe Bool) )),  DocTest.test "src/Flat/Instances/Base.hs:207" "[ExpectedLine [LineChunk \"(True,2,\\\"00\\\")\"]]" (DocTest.asPrint( test (Left False::Either Bool ()) )),  DocTest.test "src/Flat/Instances/Base.hs:210" "[ExpectedLine [LineChunk \"(True,1,\\\"1\\\")\"]]" (DocTest.asPrint( test (Right ()::Either Bool ()) )),  DocTest.test "src/Flat/Instances/Base.hs:216" "[ExpectedLine [LineChunk \"(True,16,\\\"11110110 00000001\\\")\"]]" (DocTest.asPrint( test (MkFixed 123 :: Fixed E0) )),  DocTest.test "src/Flat/Instances/Base.hs:219" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( test (MkFixed 123 :: Fixed E0) == test (MkFixed 123 :: Fixed E2) )),  DocTest.test "src/Flat/Instances/Base.hs:232" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:235" "[ExpectedLine [LineChunk \"(True,8,\\\"11111111\\\")\"]]" (DocTest.asPrint( test (255::Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:279" "[ExpectedLine [LineChunk \"(True,8,\\\"01111111\\\")\"]]" (DocTest.asPrint( test (127::Word) )),  DocTest.test "src/Flat/Instances/Base.hs:284" "[ExpectedLine [LineChunk \"(True,16,\\\"11111110 00000001\\\")\"]]" (DocTest.asPrint( test (254::Word) )),  DocTest.test "src/Flat/Instances/Base.hs:289" "[ExpectedLine [LineChunk \"(True,24,\\\"10000000 10000000 00000010\\\")\"]]" (DocTest.asPrint( test (32768::Word32) )),  DocTest.test "src/Flat/Instances/Base.hs:294" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( all (test (3::Word) ==) [test (3::Word16),test (3::Word32),test (3::Word64)] )),  DocTest.test "src/Flat/Instances/Base.hs:307" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Natural) )),  DocTest.test "src/Flat/Instances/Base.hs:310" "[ExpectedLine [LineChunk \"(True,144,\\\"10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 00000010\\\")\"]]" (DocTest.asPrint( test (2^120::Natural) )),  DocTest.test "src/Flat/Instances/Base.hs:362" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:365" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:368" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:371" "[ExpectedLine [LineChunk \"(True,8,\\\"00000011\\\")\"]]" (DocTest.asPrint( test (-2::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:374" "[ExpectedLine [LineChunk \"(True,8,\\\"00000100\\\")\"]]" (DocTest.asPrint( test (2::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:387" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:390" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:393" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:396" "[ExpectedLine [LineChunk \"(True,8,\\\"00011111\\\")\"]]" (DocTest.asPrint( test (-(2^4)::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:399" "[ExpectedLine [LineChunk \"(True,8,\\\"00100000\\\")\"]]" (DocTest.asPrint( test (2^4::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:402" "[ExpectedLine [LineChunk \"(True,144,\\\"11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (-(2^120)::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:405" "[ExpectedLine [LineChunk \"(True,144,\\\"10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 00000100\\\")\"]]" (DocTest.asPrint( test (2^120::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:416" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:419" "[ExpectedLine [LineChunk \"(True,8,\\\"11111110\\\")\"]]" (DocTest.asPrint( test (127::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:422" "[ExpectedLine [LineChunk \"(True,8,\\\"11111111\\\")\"]]" (DocTest.asPrint( test (-128::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:433" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:436" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:439" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:442" "[ExpectedLine [LineChunk \"(True,24,\\\"11111111 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (minBound::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:447" "[ExpectedLine [LineChunk \"(True,24,\\\"11111110 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (maxBound::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:460" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:463" "[ExpectedLine [LineChunk \"(True,40,\\\"11111111 11111111 11111111 11111111 00001111\\\")\"]]" (DocTest.asPrint( test (minBound::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:466" "[ExpectedLine [LineChunk \"(True,40,\\\"11111110 11111111 11111111 11111111 00001111\\\")\"]]" (DocTest.asPrint( test (maxBound::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:477" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:480" "[ExpectedLine [LineChunk \"(True,80,\\\"11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000001\\\")\"]]" (DocTest.asPrint( test (minBound::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:483" "[ExpectedLine [LineChunk \"(True,80,\\\"11111110 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000001\\\")\"]]" (DocTest.asPrint( test (maxBound::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:503" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 00000000 00000000 00000000\\\")\"]]" (DocTest.asPrint( test (0::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:506" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 00000000 00000000 00000001\\\")\"]]" (DocTest.asPrint( test (1.4012984643E-45::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:509" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 01111111 11111111 11111111\\\")\"]]" (DocTest.asPrint( test (1.1754942107E-38::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:536" "[ExpectedLine [LineChunk \"(True,16,\\\"00000100 00000010\\\")\"]]" (DocTest.asPrint( test (4 :+ 2 :: Complex Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:544" "[ExpectedLine [LineChunk \"(True,16,\\\"00000011 00000100\\\")\"]]" (DocTest.asPrint( test (3%4::Ratio Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:556" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test ([]::[Bool]) )),  DocTest.test "src/Flat/Instances/Base.hs:559" "[ExpectedLine [LineChunk \"(True,5,\\\"10100\\\")\"]]" (DocTest.asPrint( test [False,False] )),  DocTest.test "src/Flat/Instances/Base.hs:584" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test "" )),  DocTest.test "src/Flat/Instances/Base.hs:587" "[ExpectedLine [LineChunk \"(True,28,\\\"10110000 11011000 01101100 0010\\\")\"]]" (DocTest.asPrint( test "aaa" )),  DocTest.test "src/Flat/Instances/Base.hs:595" "[ExpectedLine [LineChunk \"(True,2,\\\"10\\\")\"]]" (DocTest.asPrint( test (B.fromList [True]) )),  DocTest.test "src/Flat/Instances/Base.hs:598" "[ExpectedLine [LineChunk \"(True,4,\\\"0100\\\")\"]]" (DocTest.asPrint( test (B.fromList [False,False]) )),  DocTest.test "src/Flat/Instances/Base.hs:607" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test (False,()) )),  DocTest.test "src/Flat/Instances/Base.hs:610" "[ExpectedLine [LineChunk \"(True,0,\\\"\\\")\"]]" (DocTest.asPrint( test ((),()) )),  DocTest.test "src/Flat/Instances/Base.hs:615" "[ExpectedLine [LineChunk \"(True,7,\\\"0111011\\\")\"]]" (DocTest.asPrint( test (False,True,True,True,False,True,True) ))]+tests = testGroup "Flat.Instances.Base" <$> sequence [  DocTest.test "src/Flat/Instances/Base.hs:73" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( let w = Just (11::Word8); a = Alt w <> Alt (Just 24) in tst a == tst w )),  DocTest.test "src/Flat/Instances/Base.hs:76" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( let w = Just (11::Word8); a = Alt Nothing <> Alt w in tst a == tst w )),  DocTest.test "src/Flat/Instances/Base.hs:148" "[ExpectedLine [LineChunk \"(True,0,\\\"\\\")\"]]" (DocTest.asPrint( test () )),  DocTest.test "src/Flat/Instances/Base.hs:161" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test False )),  DocTest.test "src/Flat/Instances/Base.hs:164" "[ExpectedLine [LineChunk \"(True,1,\\\"1\\\")\"]]" (DocTest.asPrint( test True )),  DocTest.test "src/Flat/Instances/Base.hs:179" "[ExpectedLine [LineChunk \"(True,8,\\\"01100001\\\")\"]]" (DocTest.asPrint( test 'a' )),  DocTest.test "src/Flat/Instances/Base.hs:184" "[ExpectedLine [LineChunk \"(True,16,\\\"11001000 00000001\\\")\"]]" (DocTest.asPrint( test 'È' )),  DocTest.test "src/Flat/Instances/Base.hs:187" "[ExpectedLine [LineChunk \"(True,24,\\\"10001101 10011100 00000001\\\")\"]]" (DocTest.asPrint( test '不' )),  DocTest.test "src/Flat/Instances/Base.hs:203" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test (Nothing::Maybe Bool) )),  DocTest.test "src/Flat/Instances/Base.hs:206" "[ExpectedLine [LineChunk \"(True,2,\\\"10\\\")\"]]" (DocTest.asPrint( test (Just False::Maybe Bool) )),  DocTest.test "src/Flat/Instances/Base.hs:212" "[ExpectedLine [LineChunk \"(True,2,\\\"00\\\")\"]]" (DocTest.asPrint( test (Left False::Either Bool ()) )),  DocTest.test "src/Flat/Instances/Base.hs:215" "[ExpectedLine [LineChunk \"(True,1,\\\"1\\\")\"]]" (DocTest.asPrint( test (Right ()::Either Bool ()) )),  DocTest.test "src/Flat/Instances/Base.hs:221" "[ExpectedLine [LineChunk \"(True,16,\\\"11110110 00000001\\\")\"]]" (DocTest.asPrint( test (MkFixed 123 :: Fixed E0) )),  DocTest.test "src/Flat/Instances/Base.hs:224" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( test (MkFixed 123 :: Fixed E0) == test (MkFixed 123 :: Fixed E2) )),  DocTest.test "src/Flat/Instances/Base.hs:237" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:240" "[ExpectedLine [LineChunk \"(True,8,\\\"11111111\\\")\"]]" (DocTest.asPrint( test (255::Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:284" "[ExpectedLine [LineChunk \"(True,8,\\\"01111111\\\")\"]]" (DocTest.asPrint( test (127::Word) )),  DocTest.test "src/Flat/Instances/Base.hs:289" "[ExpectedLine [LineChunk \"(True,16,\\\"11111110 00000001\\\")\"]]" (DocTest.asPrint( test (254::Word) )),  DocTest.test "src/Flat/Instances/Base.hs:294" "[ExpectedLine [LineChunk \"(True,24,\\\"10000000 10000000 00000010\\\")\"]]" (DocTest.asPrint( test (32768::Word32) )),  DocTest.test "src/Flat/Instances/Base.hs:299" "[ExpectedLine [LineChunk \"True\"]]" (DocTest.asPrint( all (test (3::Word) ==) [test (3::Word16),test (3::Word32),test (3::Word64)] )),  DocTest.test "src/Flat/Instances/Base.hs:312" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Natural) )),  DocTest.test "src/Flat/Instances/Base.hs:315" "[ExpectedLine [LineChunk \"(True,144,\\\"10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 00000010\\\")\"]]" (DocTest.asPrint( test (2^120::Natural) )),  DocTest.test "src/Flat/Instances/Base.hs:365" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:368" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:371" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:374" "[ExpectedLine [LineChunk \"(True,8,\\\"00000011\\\")\"]]" (DocTest.asPrint( test (-2::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:377" "[ExpectedLine [LineChunk \"(True,8,\\\"00000100\\\")\"]]" (DocTest.asPrint( test (2::Int) )),  DocTest.test "src/Flat/Instances/Base.hs:390" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:393" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:396" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:399" "[ExpectedLine [LineChunk \"(True,8,\\\"00011111\\\")\"]]" (DocTest.asPrint( test (-(2^4)::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:402" "[ExpectedLine [LineChunk \"(True,8,\\\"00100000\\\")\"]]" (DocTest.asPrint( test (2^4::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:405" "[ExpectedLine [LineChunk \"(True,144,\\\"11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (-(2^120)::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:408" "[ExpectedLine [LineChunk \"(True,144,\\\"10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000 00000100\\\")\"]]" (DocTest.asPrint( test (2^120::Integer) )),  DocTest.test "src/Flat/Instances/Base.hs:419" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:422" "[ExpectedLine [LineChunk \"(True,8,\\\"11111110\\\")\"]]" (DocTest.asPrint( test (127::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:425" "[ExpectedLine [LineChunk \"(True,8,\\\"11111111\\\")\"]]" (DocTest.asPrint( test (-128::Int8) )),  DocTest.test "src/Flat/Instances/Base.hs:436" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:439" "[ExpectedLine [LineChunk \"(True,8,\\\"00000010\\\")\"]]" (DocTest.asPrint( test (1::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:442" "[ExpectedLine [LineChunk \"(True,8,\\\"00000001\\\")\"]]" (DocTest.asPrint( test (-1::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:445" "[ExpectedLine [LineChunk \"(True,24,\\\"11111111 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (minBound::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:450" "[ExpectedLine [LineChunk \"(True,24,\\\"11111110 11111111 00000011\\\")\"]]" (DocTest.asPrint( test (maxBound::Int16) )),  DocTest.test "src/Flat/Instances/Base.hs:463" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:466" "[ExpectedLine [LineChunk \"(True,40,\\\"11111111 11111111 11111111 11111111 00001111\\\")\"]]" (DocTest.asPrint( test (minBound::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:469" "[ExpectedLine [LineChunk \"(True,40,\\\"11111110 11111111 11111111 11111111 00001111\\\")\"]]" (DocTest.asPrint( test (maxBound::Int32) )),  DocTest.test "src/Flat/Instances/Base.hs:480" "[ExpectedLine [LineChunk \"(True,8,\\\"00000000\\\")\"]]" (DocTest.asPrint( test (0::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:483" "[ExpectedLine [LineChunk \"(True,80,\\\"11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000001\\\")\"]]" (DocTest.asPrint( test (minBound::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:486" "[ExpectedLine [LineChunk \"(True,80,\\\"11111110 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000001\\\")\"]]" (DocTest.asPrint( test (maxBound::Int64) )),  DocTest.test "src/Flat/Instances/Base.hs:505" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 00000000 00000000 00000000\\\")\"]]" (DocTest.asPrint( test (0::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:508" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 00000000 00000000 00000001\\\")\"]]" (DocTest.asPrint( test (1.4012984643E-45::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:511" "[ExpectedLine [LineChunk \"(True,32,\\\"00000000 01111111 11111111 11111111\\\")\"]]" (DocTest.asPrint( test (1.1754942107E-38::Float) )),  DocTest.test "src/Flat/Instances/Base.hs:538" "[ExpectedLine [LineChunk \"(True,16,\\\"00000100 00000010\\\")\"]]" (DocTest.asPrint( test (4 :+ 2 :: Complex Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:546" "[ExpectedLine [LineChunk \"(True,16,\\\"00000011 00000100\\\")\"]]" (DocTest.asPrint( test (3%4::Ratio Word8) )),  DocTest.test "src/Flat/Instances/Base.hs:558" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test ([]::[Bool]) )),  DocTest.test "src/Flat/Instances/Base.hs:561" "[ExpectedLine [LineChunk \"(True,5,\\\"10100\\\")\"]]" (DocTest.asPrint( test [False,False] )),  DocTest.test "src/Flat/Instances/Base.hs:595" "[ExpectedLine [LineChunk \"(True,2,\\\"10\\\")\"]]" (DocTest.asPrint( test (B.fromList [True]) )),  DocTest.test "src/Flat/Instances/Base.hs:598" "[ExpectedLine [LineChunk \"(True,4,\\\"0100\\\")\"]]" (DocTest.asPrint( test (B.fromList [False,False]) )),  DocTest.test "src/Flat/Instances/Base.hs:608" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( test (False,()) )),  DocTest.test "src/Flat/Instances/Base.hs:611" "[ExpectedLine [LineChunk \"(True,0,\\\"\\\")\"]]" (DocTest.asPrint( test ((),()) )),  DocTest.test "src/Flat/Instances/Base.hs:616" "[ExpectedLine [LineChunk \"(True,7,\\\"0111011\\\")\"]]" (DocTest.asPrint( test (False,True,True,True,False,True,True) ))]
+ test/DocTest/Flat/Instances/Extra.hs view
@@ -0,0 +1,10 @@++{-# LANGUAGE NoMonomorphismRestriction, ExtendedDefaultRules#-}+module DocTest.Flat.Instances.Extra where+import qualified DocTest+import Test.Tasty(TestTree,testGroup)+import Flat.Instances.Extra+import Flat.Instances.Test++tests :: IO TestTree+tests = testGroup "Flat.Instances.Extra" <$> sequence [  DocTest.test "src/Flat/Instances/Extra.hs:13" "[ExpectedLine [LineChunk \"(True,1,\\\"0\\\")\"]]" (DocTest.asPrint( tstBits "" )),  DocTest.test "src/Flat/Instances/Extra.hs:16" "[ExpectedLine [LineChunk \"(True,28,\\\"10110000 11011000 01101100 0010\\\")\"]]" (DocTest.asPrint( tstBits "aaa" ))]
test/DocTest/Flat/Instances/Mono.hs view
@@ -11,4 +11,4 @@ import qualified Data.Map  tests :: IO TestTree-tests = testGroup "Flat.Instances.Mono" <$> sequence [  DocTest.test "src/Flat/Instances/Mono.hs:60" "[ExpectedLine [LineChunk \"(True,8,[0])\"]]" (DocTest.asPrint( tst $ AsArray ([]::[()]) )),  DocTest.test "src/Flat/Instances/Mono.hs:63" "[ExpectedLine [LineChunk \"(True,40,[3,11,22,33,0])\"]]" (DocTest.asPrint( tst $ AsArray [11::Word8,22,33] )),  DocTest.test "src/Flat/Instances/Mono.hs:66" "[ExpectedLine [LineChunk \"(True,1,[0])\"]]" (DocTest.asPrint( tst $ AsList ([]::[()]) )),  DocTest.test "src/Flat/Instances/Mono.hs:69" "[ExpectedLine [LineChunk \"(True,28,[133,197,164,32])\"]]" (DocTest.asPrint( tst (AsList [11::Word8,22,33]) )),  DocTest.test "src/Flat/Instances/Mono.hs:72" "[ExpectedLine [LineChunk \"(True,28,[133,197,164,32])\"]]" (DocTest.asPrint( tst (AsSet (Data.Set.fromList [11::Word8,22,33])) )),  DocTest.test "src/Flat/Instances/Mono.hs:162" "[ExpectedLine [LineChunk \"(True,1,[0])\"]]" (DocTest.asPrint( tst (AsMap (Data.Map.fromList ([]::[(Word8,())]))) )),  DocTest.test "src/Flat/Instances/Mono.hs:165" "[ExpectedLine [LineChunk \"(True,18,[129,132,128])\"]]" (DocTest.asPrint( tst (AsMap (Data.Map.fromList [(3::Word,9::Word)])) ))]+tests = testGroup "Flat.Instances.Mono" <$> sequence [  DocTest.test "src/Flat/Instances/Mono.hs:62" "[ExpectedLine [LineChunk \"\\\"1111110\\\"\"]]" (DocTest.asPrint( flatBits $ AsList [True,True,True] )),  DocTest.test "src/Flat/Instances/Mono.hs:69" "[ExpectedLine [LineChunk \"\\\"1111110\\\"\"]]" (DocTest.asPrint( flatBits $ [True,True,True] )),  DocTest.test "src/Flat/Instances/Mono.hs:74" "[ExpectedLine [LineChunk \"\\\"00000011 11100000 000\\\"\"]]" (DocTest.asPrint( flatBits $ AsArray [True,True,True] )),  DocTest.test "src/Flat/Instances/Mono.hs:79" "[ExpectedLine [LineChunk \"\\\"10000001 11110000 00000\\\"\"]]" (DocTest.asPrint( flatBits $ [AsArray [True,True,True]] )),  DocTest.test "src/Flat/Instances/Mono.hs:82" "[ExpectedLine [LineChunk \"\\\"11100000 11111111 11000000 00\\\"\"]]" (DocTest.asPrint( flatBits $ (True,True,True,AsArray $ replicate 7 True) )),  DocTest.test "src/Flat/Instances/Mono.hs:85" "[ExpectedLine [LineChunk \"\\\"00000000\\\"\"]]" (DocTest.asPrint( flatBits $ AsArray ([]::[()]) )),  DocTest.test "src/Flat/Instances/Mono.hs:88" "[ExpectedLine [LineChunk \"\\\"0\\\"\"]]" (DocTest.asPrint( flatBits $ AsList ([]::[()]) )),  DocTest.test "src/Flat/Instances/Mono.hs:91" "[ExpectedLine [LineChunk \"(True,28,[133,197,164,32])\"]]" (DocTest.asPrint( tst (AsList [11::Word8,22,33]) )),  DocTest.test "src/Flat/Instances/Mono.hs:94" "[ExpectedLine [LineChunk \"(True,28,[133,197,164,32])\"]]" (DocTest.asPrint( tst (AsSet (Data.Set.fromList [11::Word8,22,33])) )),  DocTest.test "src/Flat/Instances/Mono.hs:97" "[ExpectedLine [LineChunk \"(True,99,[129,129,2,3,0,65,66,2,131,3,132,0,0])\"]]" (DocTest.asPrint( tst [AsArray [1..3], AsArray [4..8]] )),  DocTest.test "src/Flat/Instances/Mono.hs:100" "[ExpectedLine [LineChunk \"(True,99,[129,128,129,1,128,65,65,1,65,129,194,0,0])\"]]" (DocTest.asPrint( tst $ [AsArray [(1::Word8)..3], AsArray [4..8]] )),  DocTest.test "src/Flat/Instances/Mono.hs:103" "[ExpectedLine [LineChunk \"(True,42,[129,129,2,3,0,0])\"]]" (DocTest.asPrint( tst $ [AsArray [(1::Int)..3]] )),  DocTest.test "src/Flat/Instances/Mono.hs:196" "[ExpectedLine [LineChunk \"(True,1,[0])\"]]" (DocTest.asPrint( tst (AsMap (Data.Map.fromList ([]::[(Word8,())]))) )),  DocTest.test "src/Flat/Instances/Mono.hs:199" "[ExpectedLine [LineChunk \"(True,18,[129,132,128])\"]]" (DocTest.asPrint( tst (AsMap (Data.Map.fromList [(3::Word,9::Word)])) ))]
+ test/DocTest/Flat/Repr.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE ScopedTypeVariables#-}++{-# LANGUAGE NoMonomorphismRestriction, ExtendedDefaultRules#-}+module DocTest.Flat.Repr where+import qualified DocTest+import Test.Tasty(TestTree,testGroup)+import Flat.Repr+import Flat.Instances.Base+import Flat.Decoder.Types+import Flat.Types+import Flat.Run+import Flat.Class++tests :: IO TestTree+tests = testGroup "Flat.Repr" <$> sequence [  DocTest.test "src/Flat/Repr.hs:27" "[ExpectedLine [LineChunk \"Right [Repr {repr = \\\"\\\\STX\\\\SOH\\\"},Repr {repr = \\\"\\\\EOT\\\\SOH\\\"},Repr {repr = \\\"\\\\ACK\\\\SOH\\\"},Repr {repr = \\\"\\\\b\\\\SOH\\\"},Repr {repr = \\\"\\\\n\\\\SOH\\\"}]\"]]" (DocTest.asPrint( unflat (flat [1::Int .. 5]) :: Decoded ([Repr Int]) )),  DocTest.test "src/Flat/Repr.hs:32" "[ExpectedLine [LineChunk \"3\"]]" (DocTest.asPrint( let Right l = unflat (flat [1..5]) :: Decoded [Repr Int] in unrepr (l  !! 2) )),  DocTest.test "src/Flat/Repr.hs:42" "[ExpectedLine [LineChunk \"Right ('a',SizeOf 28,'z',SizeOf 1)\"]]" (DocTest.asPrint( let v = flat ('a',"abc",'z',True) in unflat v :: Decoded (Char,SizeOf String,Char,SizeOf Bool) ))]
test/DocTests.hs view
@@ -2,19 +2,22 @@ import           Test.Tasty import           Test.Tasty.HUnit import qualified DocTest.Flat.Bits+import qualified DocTest.Flat.Repr import qualified DocTest.Flat.Instances.Array import qualified DocTest.Flat.Instances.ByteString import qualified DocTest.Flat.Instances.DList+import qualified DocTest.Flat.Instances.Extra import qualified DocTest.Flat.Instances.Containers import qualified DocTest.Flat.Instances.Base import qualified DocTest.Flat.Instances.Unordered import qualified DocTest.Flat.Instances.Vector import qualified DocTest.Flat.Instances.Mono import qualified DocTest.Flat.Instances.Text+import qualified DocTest.Flat.Encoder.Prim import qualified DocTest.Flat.Tutorial import qualified DocTest.Flat.Decoder.Prim import qualified DocTest.Flat.Endian import qualified DocTest.Data.ZigZag import qualified DocTest.Data.FloatCast -main = (testGroup "DocTests" <$> sequence [DocTest.Flat.Bits.tests,DocTest.Flat.Instances.Array.tests,DocTest.Flat.Instances.ByteString.tests,DocTest.Flat.Instances.DList.tests,DocTest.Flat.Instances.Containers.tests,DocTest.Flat.Instances.Base.tests,DocTest.Flat.Instances.Unordered.tests,DocTest.Flat.Instances.Vector.tests,DocTest.Flat.Instances.Mono.tests,DocTest.Flat.Instances.Text.tests,DocTest.Flat.Tutorial.tests,DocTest.Flat.Decoder.Prim.tests,DocTest.Flat.Endian.tests,DocTest.Data.ZigZag.tests,DocTest.Data.FloatCast.tests]) >>= defaultMain+main = (testGroup "DocTests" <$> sequence [DocTest.Flat.Bits.tests,DocTest.Flat.Repr.tests,DocTest.Flat.Instances.Array.tests,DocTest.Flat.Instances.ByteString.tests,DocTest.Flat.Instances.DList.tests,DocTest.Flat.Instances.Extra.tests,DocTest.Flat.Instances.Containers.tests,DocTest.Flat.Instances.Base.tests,DocTest.Flat.Instances.Unordered.tests,DocTest.Flat.Instances.Vector.tests,DocTest.Flat.Instances.Mono.tests,DocTest.Flat.Instances.Text.tests,DocTest.Flat.Encoder.Prim.tests,DocTest.Flat.Tutorial.tests,DocTest.Flat.Decoder.Prim.tests,DocTest.Flat.Endian.tests,DocTest.Data.ZigZag.tests,DocTest.Data.FloatCast.tests]) >>= defaultMain
+ test/FlatRepr.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Main where+import qualified Data.ByteString as B+import           Data.List       (foldl')+import           Flat            (Decoded, Flat (..), flat, unflat, unflatWith)+import           Flat.Decoder    (Get, listTDecoder)+import           Flat.Repr       (Repr, unrepr)+import qualified ListT           as L+import           System.TimeIt   (timeIt)++-- Big is a type that has a small encoded representation but a very large in-memory footprint.+-- It is a very large bytestring whose bytes are all set to 0+newtype Big = Big B.ByteString++newBig :: Int -> Big+newBig gigas = Big $ B.replicate (gigas*giga) 0++-- length of Big in gigas+gigas :: Big -> Int+gigas (Big b) = B.length b `div` giga++giga :: Int+giga = 1000000000++instance Show Big where show b = "Big of " ++ show (gigas b) ++ "Gbytes"++instance Flat Big where+    -- The encoded form is just the number of giga zeros (e.g. 5 for 5Giga zeros)+    size big = size (gigas big)+    encode big = encode (gigas big)++    -- The decoded form is massive+    decode = newBig <$> decode++-- Run this as: cabal run FlatRepr -- +RTS  -M2g+main :: IO ()+main = tbig++tbig = do+    let numOfBigs = 5++    -- A serialised list of Big values+    let bigsFile = flat $ replicate numOfBigs $ newBig 1+    timeIt $ print $ B.length bigsFile++    -- tstSize bigsFile++    tstListT bigsFile++    tstRepr bigsFile++    tstBig bigsFile++-- If we unserialise a list of Bigs and then process them (e.g. print them out) we end up in trouble, too much memory is required.+tstBig :: B.ByteString -> IO ()+tstBig bigsFile = timeIt $ do+    print "Decode to [Big]:"+    let Right (bs :: [Big]) = unflat bigsFile+    mapM_ print bs++-- So instead we unserialise them to a list of their flat representations, to be unflatted on demand later on+tstRepr :: B.ByteString -> IO ()+tstRepr bigsFile = timeIt $ do+    print "Decode to [FlatRepl Big]:"+    let Right (bsR :: [Repr Big]) = unflat bigsFile+    let bs = map unrepr bsR+    mapM_ print bs++-- Or: we extract one element at the time via a ListT+-- See http://hackage.haskell.org/package/list-t-1.0.4/docs/ListT.html+tstListT :: B.ByteString -> IO ()+tstListT bigsFile = timeIt $ do+    print "Decode to ListT IO Big:"+    stream :: L.ListT IO Big <- listTDecoder decode bigsFile+    L.traverse_ print stream
test/Spec.hs view
@@ -26,6 +26,7 @@ import           Data.Int import           Data.Proxy import qualified Data.Sequence as Seq+import           Data.String (fromString) import qualified Data.Text as T import           Data.Word import           Numeric.Natural@@ -260,9 +261,9 @@             dropBits (len * 8 - numBitsToTake - pre)             return r           -- we expect the first numBitsToTake bits of the value-          expectedD @ (Right expected) :: Decoded a = Right+          expectedD@(Right expected) :: Decoded a = Right             $ val `shR` (sz - numBitsToTake) -- ghcjs: shiftR fails, see: https://github.com/ghcjs/ghcjs/issues/706-          actualD @ (Right actual) :: Decoded a = unflatRawWith dec vs+          actualD@(Right actual) :: Decoded a = unflatRawWith dec vs       in testCase            (unwords               [ "take"@@ -420,6 +421,7 @@       errDec (Proxy :: Proxy Bool) [] -- no data     , errDec (Proxy :: Proxy Bool) [128] -- no filler     , errDec (Proxy :: Proxy Bool) [128 + 1, 1, 2, 4, 8] -- additional bytes+    , errDec (Proxy :: Proxy Text) (B.unpack (flat ((fromString "\x80") :: B.ByteString))) -- invalid UTF-8     , encRaw () []     , encRaw ((), (), Unit) []     , encRaw (Unit, 'a', Unit, 'a', Unit, 'a', Unit) [97, 97, 97]
test/Test/Data/Arbitrary.hs view
@@ -16,7 +16,7 @@  import Numeric.Natural (Natural) --- #if MIN_VERSION_base(4,9,0) && MIN_VERSION_QuickCheck(2,10,0)+#if MIN_VERSION_base(4,8,0) && MIN_VERSION_QuickCheck(2,10,0) instance Arbitrary a => Arbitrary (BI.NonEmpty a) where   arbitrary = BI.fromList . getNonEmpty <$> (arbitrary :: Gen (NonEmptyList a))   shrink xs = BI.fromList <$> shrink (BI.toList xs)@@ -24,7 +24,7 @@ instance Arbitrary Natural where   arbitrary = arbitrarySizedNatural   shrink    = shrinkIntegral--- #endif+#endif  -- Copied from quickcheck-instances (not used directly as it requires old-time that is incompatible with ghcjs) 
test/Test/Data/Flat.hs view
@@ -1,6 +1,5 @@- {-# LANGUAGE UndecidableInstances, DeriveGeneric-             , FlexibleContexts, FlexibleInstances, StandaloneDeriving #-}+             , FlexibleContexts, FlexibleInstances, StandaloneDeriving , CPP #-}  module Test.Data.Flat   ( module Test.Data@@ -33,9 +32,11 @@ -- instance Flat C0 -- instance Flat D0 -- instance Flat E0+#if MIN_VERSION_base(4,9,0) && ! MIN_VERSION_base(4,16,0) deriving instance Generic (a, b, c, d, e, f, g, h)  deriving instance Generic (a, b, c, d, e, f, g, h, i)+#endif  instance {-# OVERLAPPABLE #-}( Flat a                              , Flat b