{-# LANGUAGE LambdaCase #-}
--------------------------------------------------------------------
-- |
-- Module    : Data.MessagePack.Put
-- Copyright : (c) Hideyuki Tanaka, 2009-2015
-- License   : BSD3
--
-- Maintainer:  tanaka.hideyuki@gmail.com
-- Stability :  experimental
-- Portability: portable
--
-- MessagePack Serializer using @Data.Binary@
--
--------------------------------------------------------------------

module Data.MessagePack.Put
  ( putObject
  , putNil
  , putBool
  , putInt
  , putWord
  , putFloat
  , putDouble
  , putStr
  , putBin
  , putArray
  , putMap
  , putExt
  ) where

import           Data.Binary            (Put)
import           Data.Binary.IEEE754    (putFloat32be, putFloat64be)
import           Data.Binary.Put        (putByteString, putWord16be,
                                         putWord32be, putWord64be, putWord8)
import           Data.Bits              ((.|.))
import qualified Data.ByteString        as S
import           Data.Int               (Int64)
import qualified Data.Text              as T
import qualified Data.Text.Encoding     as T
import qualified Data.Vector            as V
import           Data.Word              (Word64, Word8)

import           Prelude                hiding (putStr)

import           Data.MessagePack.Tags
import           Data.MessagePack.Types (Object (..))


putObject :: Object -> Put
putObject :: Object -> Put
putObject = \case
  Object
ObjectNil      -> Put
putNil
  ObjectBool   Bool
b -> Bool -> Put
putBool Bool
b
  ObjectInt    Int64
n -> Int64 -> Put
putInt Int64
n
  ObjectWord   Word64
n -> Word64 -> Put
putWord Word64
n
  ObjectFloat  Float
f -> Float -> Put
putFloat Float
f
  ObjectDouble Double
d -> Double -> Put
putDouble Double
d
  ObjectStr    Text
t -> Text -> Put
putStr Text
t
  ObjectBin    ByteString
b -> ByteString -> Put
putBin ByteString
b
  ObjectArray  Vector Object
a -> (Object -> Put) -> Vector Object -> Put
forall a. (a -> Put) -> Vector a -> Put
putArray Object -> Put
putObject Vector Object
a
  ObjectMap    Vector (Object, Object)
m -> (Object -> Put)
-> (Object -> Put) -> Vector (Object, Object) -> Put
forall a b. (a -> Put) -> (b -> Put) -> Vector (a, b) -> Put
putMap Object -> Put
putObject Object -> Put
putObject Vector (Object, Object)
m
  ObjectExt  Word8
b ByteString
r -> Word8 -> ByteString -> Put
putExt Word8
b ByteString
r

putNil :: Put
putNil :: Put
putNil = Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_nil

putBool :: Bool -> Put
putBool :: Bool -> Put
putBool Bool
False = Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_false
putBool Bool
True  = Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_true

putInt :: Int64 -> Put
putInt :: Int64 -> Put
putInt Int64
n
  | -Int64
0x20 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n Bool -> Bool -> Bool
&& Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0x80 =
                            Word8 -> Put
putWord8    (Int64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | Int64
0     Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n Bool -> Bool -> Bool
&& Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0x100 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_8  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Int64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | Int64
0     Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n Bool -> Bool -> Bool
&& Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0x10000 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | Int64
0     Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n Bool -> Bool -> Bool
&& Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0x100000000 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | Int64
0     Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_64 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word64 -> Put
putWord64be (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | -Int64
0x80 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_int_8   Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Int64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | -Int64
0x8000 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_int_16  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | -Int64
0x80000000 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_int_32  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
  | Bool
otherwise =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_int_64  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word64 -> Put
putWord64be (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)

putWord :: Word64 -> Put
putWord :: Word64 -> Put
putWord Word64
n
  | Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x80 =
                            Word8 -> Put
putWord8    (Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n)
  | Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_8  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n)
  | Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x10000 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n)
  | Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
0x100000000 =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n)
  | Bool
otherwise =
    Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_uint_64 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word64 -> Put
putWord64be Word64
n

putFloat :: Float -> Put
putFloat :: Float -> Put
putFloat Float
f = do
  Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_float_32
  Float -> Put
putFloat32be Float
f

putDouble :: Double -> Put
putDouble :: Double -> Put
putDouble Double
d = do
  Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_float_64
  Double -> Put
putFloat64be Double
d

putStr :: T.Text -> Put
putStr :: Text -> Put
putStr Text
t = do
  let bs :: ByteString
bs = Text -> ByteString
T.encodeUtf8 Text
t
  case ByteString -> Int
S.length ByteString
bs of
    Int
len | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
31 ->
          Word8 -> Put
putWord8 (Word8 -> Put) -> Word8 -> Put
forall a b. (a -> b) -> a -> b
$ Word8
0xA0 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x100 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_str_8  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_str_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Bool
otherwise ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_str_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
  ByteString -> Put
putByteString ByteString
bs

putBin :: S.ByteString -> Put
putBin :: ByteString -> Put
putBin ByteString
bs = do
  case ByteString -> Int
S.length ByteString
bs of
    Int
len | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x100 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_bin_8  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_bin_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Bool
otherwise ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_bin_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
  ByteString -> Put
putByteString ByteString
bs

putArray :: (a -> Put) -> V.Vector a -> Put
putArray :: (a -> Put) -> Vector a -> Put
putArray a -> Put
p Vector a
xs = do
  case Vector a -> Int
forall a. Vector a -> Int
V.length Vector a
xs of
    Int
len | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
15 ->
          Word8 -> Put
putWord8 (Word8 -> Put) -> Word8 -> Put
forall a b. (a -> b) -> a -> b
$ Word8
0x90 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_array_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Bool
otherwise ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_array_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
  (a -> Put) -> Vector a -> Put
forall (m :: * -> *) a b. Monad m => (a -> m b) -> Vector a -> m ()
V.mapM_ a -> Put
p Vector a
xs

putMap :: (a -> Put) -> (b -> Put) -> V.Vector (a, b) -> Put
putMap :: (a -> Put) -> (b -> Put) -> Vector (a, b) -> Put
putMap a -> Put
p b -> Put
q Vector (a, b)
xs = do
  case Vector (a, b) -> Int
forall a. Vector a -> Int
V.length Vector (a, b)
xs of
    Int
len | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
15 ->
          Word8 -> Put
putWord8 (Word8 -> Put) -> Word8 -> Put
forall a b. (a -> b) -> a -> b
$ Word8
0x80 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_map_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Bool
otherwise ->
          Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_map_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
  ((a, b) -> Put) -> Vector (a, b) -> Put
forall (m :: * -> *) a b. Monad m => (a -> m b) -> Vector a -> m ()
V.mapM_ (\(a
a, b
b) -> a -> Put
p a
a Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> Put
q b
b) Vector (a, b)
xs

putExt :: Word8 -> S.ByteString -> Put
putExt :: Word8 -> ByteString -> Put
putExt Word8
typ ByteString
dat = do
  case ByteString -> Int
S.length ByteString
dat of
    Int
1  -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_fixext_1
    Int
2  -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_fixext_2
    Int
4  -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_fixext_4
    Int
8  -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_fixext_8
    Int
16 -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_fixext_16
    Int
len | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x100   -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_ext_8  Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Put
putWord8    (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0x10000 -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_ext_16 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word16 -> Put
putWord16be (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
        | Bool
otherwise     -> Word8 -> Put
putWord8 Word8
forall a. (Eq a, Num a) => a
TAG_ext_32 Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> Put
putWord32be (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
  Word8 -> Put
putWord8 Word8
typ
  ByteString -> Put
putByteString ByteString
dat