Skip to content

Commit a8fe8c3

Browse files
committed
Introduce "Compat.Binary" compat-layer
This also renders the dependency on `data-binary-ieee754` redundant
1 parent f100e09 commit a8fe8c3

File tree

7 files changed

+83
-34
lines changed

7 files changed

+83
-34
lines changed

msgpack/msgpack.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ library
6666
Data.MessagePack.Put
6767

6868
other-modules: Data.MessagePack.Tags
69+
Compat.Binary
6970

7071
build-depends: base >= 4.7 && < 4.13
7172
, mtl >= 2.1.3.1 && < 2.3
@@ -77,8 +78,8 @@ library
7778
, vector >= 0.10.11 && < 0.13
7879
, deepseq >= 1.3 && < 1.5
7980
, binary >= 0.7.1 && < 0.9
80-
, data-binary-ieee754 >= 0.4.4 && < 0.5
8181
, time >= 1.4.2 && < 1.9
82+
, array >= 0.5.0 && < 0.6
8283

8384
ghc-options: -Wall
8485

msgpack/src/Compat/Binary.hs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{-# LANGUAGE FlexibleContexts #-}
2+
3+
-- | Compat layer for "Data.Binary"
4+
--
5+
-- Supports @binary-0.7.1@ and later
6+
module Compat.Binary
7+
( Binary(put, get)
8+
9+
, runPut', runPut, PutM, Put
10+
, runGet', runGet, Get
11+
12+
, getWord64be, putWord64be
13+
, getWord32be, putWord32be
14+
, getWord16be, putWord16be
15+
, getWord8 , putWord8
16+
17+
, getFloat32be, putFloat32be
18+
, getFloat64be, putFloat64be
19+
20+
, getByteString, putByteString
21+
22+
-- convenience
23+
, Data.Word.Word, Word8, Word16, Word32, Word64
24+
, Data.Int.Int, Int8, Int16, Int32, Int64
25+
) where
26+
27+
import qualified Data.ByteString as BS
28+
import qualified Data.ByteString.Lazy as BL
29+
30+
import Data.Array.ST (MArray, STUArray, newArray, readArray)
31+
import Data.Array.Unsafe (castSTUArray)
32+
import Data.Binary
33+
import Data.Binary.Get
34+
import Data.Binary.Put
35+
import Data.Int
36+
import Data.Word
37+
import GHC.ST (ST, runST)
38+
39+
40+
runGet' :: BS.ByteString -> Get a -> Maybe a
41+
runGet' bs0 g = case pushEndOfInput (runGetIncremental g `pushChunk` bs0) of
42+
Done bs _ x
43+
| BS.null bs -> return x
44+
| otherwise -> fail "trailing data"
45+
Partial _ -> fail "eof"
46+
Fail _ _ msg -> fail msg
47+
48+
runPut' :: Put -> BS.ByteString
49+
runPut' = BL.toStrict . runPut
50+
51+
52+
-- NB: Once we drop support for binary < 0.8.4 we can use @binary@'s own {get,put}{Double,Float}be operations
53+
54+
putFloat32be :: Float -> Put
55+
putFloat32be x = putWord32be (runST (cast x))
56+
57+
putFloat64be :: Double -> Put
58+
putFloat64be x = putWord64be (runST (cast x))
59+
60+
getFloat32be :: Get Float
61+
getFloat32be = do
62+
x <- getWord32be
63+
return (runST (cast x))
64+
65+
getFloat64be :: Get Double
66+
getFloat64be = do
67+
x <- getWord64be
68+
return (runST (cast x))
69+
70+
-- See https://stackoverflow.com/questions/6976684/converting-ieee-754-floating-point-in-haskell-word32-64-to-and-from-haskell-floa/7002812#7002812
71+
72+
{-# INLINE cast #-}
73+
cast :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) => a -> ST s b
74+
cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0

msgpack/src/Data/MessagePack/Get.hs

+1-4
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,13 @@ module Data.MessagePack.Get(
2020

2121
import Control.Applicative
2222
import Control.Monad
23-
import Data.Binary
24-
import Data.Binary.Get (getByteString, getWord16be,
25-
getWord32be)
26-
import Data.Binary.IEEE754 (getFloat32be, getFloat64be)
2723
import qualified Data.ByteString as S
2824
import Data.Int
2925
import qualified Data.Text as T
3026
import qualified Data.Text.Encoding as T
3127
import qualified Data.Vector as V
3228

29+
import Compat.Binary
3330
import Data.MessagePack.Integer
3431
import Data.MessagePack.Tags
3532

msgpack/src/Data/MessagePack/Integer.hs

+1-8
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,8 @@ import Control.Applicative
2020
import Control.DeepSeq (NFData (rnf))
2121
import Control.Exception (ArithException (DivideByZero, Overflow, Underflow),
2222
throw)
23-
import Data.Int
24-
import Data.Word
25-
26-
import Data.Binary (Binary (get, put))
27-
import Data.Binary.Get (Get, getWord16be, getWord32be,
28-
getWord64be, getWord8)
29-
import Data.Binary.Put (Put, putWord16be, putWord32be,
30-
putWord64be, putWord8)
3123

24+
import Compat.Binary
3225
import Data.MessagePack.Tags
3326

3427
-- | Integer type that represents the value range of integral numbers in MessagePack; i.e. \( \left[ -2^{63}, 2^{64}-1 \right] \).

msgpack/src/Data/MessagePack/Object.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ module Data.MessagePack.Object (
2828
import Control.Applicative
2929
import Control.Arrow
3030
import Control.DeepSeq
31-
import Data.Binary
3231
import qualified Data.ByteString as S
3332
import qualified Data.ByteString.Lazy as L
3433
import qualified Data.ByteString.Short as SBS
@@ -48,6 +47,8 @@ import Data.MessagePack.Get
4847
import Data.MessagePack.Integer
4948
import Data.MessagePack.Put
5049

50+
import Compat.Binary
51+
5152
import Prelude hiding (putStr)
5253

5354

msgpack/src/Data/MessagePack/Put.hs

+1-5
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,15 @@ module Data.MessagePack.Put (
1818
) where
1919

2020
import Control.Applicative
21-
import Data.Binary
22-
import Data.Binary.IEEE754 (putFloat32be, putFloat64be)
23-
import Data.Binary.Put (PutM, putByteString, putWord16be,
24-
putWord32be)
2521
import Data.Bits
2622
import qualified Data.ByteString as S
27-
import Data.Int
2823
import qualified Data.Text as T
2924
import qualified Data.Text.Encoding as T
3025
import qualified Data.Vector as V
3126

3227
import Prelude hiding (putStr)
3328

29+
import Compat.Binary
3430
import Data.MessagePack.Integer
3531
import Data.MessagePack.Tags
3632

msgpack/src/Data/MessagePack/Timestamp.hs

+2-15
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,13 @@ module Data.MessagePack.Timestamp
2828
import Control.Applicative
2929
import Control.DeepSeq (NFData (rnf))
3030
import Control.Monad
31-
import qualified Data.Binary as Bin
32-
import qualified Data.Binary.Get as Bin
33-
import qualified Data.Binary.Put as Bin
3431
import Data.Bits
3532
import qualified Data.ByteString as S
36-
import qualified Data.ByteString.Lazy as L
3733
import Data.Fixed
38-
import Data.Int
3934
import qualified Data.Time.Clock as Time
4035
import qualified Data.Time.Clock.POSIX as Time
41-
import Data.Word
4236

37+
import Compat.Binary as Bin
4338
import Data.MessagePack.Get
4439
import Data.MessagePack.Object
4540
import Data.MessagePack.Put
@@ -160,19 +155,11 @@ instance MessagePack MPTimestamp where
160155

161156
-- helpers for 'MessagePack' instance
162157
mptsEncode :: MPTimestamp -> S.ByteString
163-
mptsEncode = L.toStrict . Bin.runPut . snd . mptsPutExtData
158+
mptsEncode = runPut' . snd . mptsPutExtData
164159

165160
mptsDecode :: S.ByteString -> Maybe MPTimestamp
166161
mptsDecode bs = runGet' bs (mptsGetExtData (fromIntegral $ S.length bs)) -- FIXME: overflow-check
167162

168-
runGet' :: S.ByteString -> Bin.Get a -> Maybe a
169-
runGet' bs0 g = case Bin.pushEndOfInput (Bin.runGetIncremental g `Bin.pushChunk` bs0) of
170-
Bin.Done bs _ x
171-
| S.null bs -> pure x
172-
| otherwise -> fail "trailing data"
173-
Bin.Partial _ -> fail "eof"
174-
Bin.Fail _ _ msg -> fail msg
175-
176163
-- | This 'Binary' instance encodes\/decodes to\/from MessagePack format
177164
instance Bin.Binary MPTimestamp where
178165
get = getExt' $ \typ sz -> do

0 commit comments

Comments
 (0)