datadog-tracing-1.3.2: library/Data/MessagePack/Aeson.hs
-- | This file is copied and pasted from
-- http://hackage.haskell.org/package/msgpack-aeson-0.1.0.0/docs/src/Data-MessagePack-Aeson.html#toAeson
-- with only minor changes to use the data-msgpack fork (mostly changing Vector to list).
{-# LANGUAGE LambdaCase #-}
-- | Aeson bridge for MessagePack
--
-- Copyright: (c) 2015 Hideyuki Tanaka
module Data.MessagePack.Aeson where
import Control.Arrow
import Data.Aeson as A
import Data.ByteString.Lazy (ByteString)
import qualified Data.HashMap.Strict as HM
import Data.MessagePack as MP
import Data.Scientific
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
toAeson :: MP.Object -> A.Result Value
toAeson = \case
ObjectNil -> pure Null
ObjectBool b -> pure . Bool $ b
ObjectInt n -> pure . Number $ fromIntegral n
ObjectFloat f -> pure . Number $ realToFrac f
ObjectDouble d -> pure . Number $ realToFrac d
ObjectStr t -> pure . String $ t
ObjectBin b -> String <$> either (fail . show) pure (T.decodeUtf8' b)
ObjectArray v -> Array <$> V.mapM toAeson v
ObjectMap m ->
A.Object . HM.fromList . V.toList
<$> V.mapM (\(k, v) -> (,) <$> from k <*> toAeson v) m
where from = maybe (fail "bad object") pure . MP.fromObject
ObjectExt _ _ -> fail "ObjectExt is not supported"
fromAeson :: Value -> MP.Object
fromAeson = \case
Null -> ObjectNil
Bool b -> ObjectBool b
Number s ->
case floatingOrInteger s of
Left f -> ObjectDouble f
Right n -> ObjectInt n
String t -> ObjectStr t
Array v -> ObjectArray $ V.map fromAeson v
A.Object o -> ObjectMap $ V.fromList $ map (toObject *** fromAeson) $ HM.toList o
packToJSON :: ToJSON a => a -> ByteString
packToJSON = pack . fromAeson . toJSON
unpackFromJSON :: FromJSON a => ByteString -> Result a
unpackFromJSON b = fromJSON =<< toAeson =<< maybe (fail "msgpack") pure (unpack b)