{-# LANGUAGE BangPatterns #-}
module Data.Binary.Serialise.CBOR.JSON (
cborToJson,
jsonToCbor,
encodeJSON,
decodeJSON,
) where
import qualified Data.Aeson as JSON
import qualified Data.Scientific as Scientific
import qualified Data.Vector as Vec
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.Text.Lazy as Text.Lazy
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Base64 as Base64
import qualified Data.ByteString.Base16 as Base16
import Codec.Serialise.Decoding
import Codec.Serialise.Encoding
import Codec.CBOR.Term as CBOR
import Codec.Serialise
import Control.Applicative
import Prelude
instance Serialise JSON.Value where
encode :: Value -> Encoding
encode = Value -> Encoding
encodeJSON
decode :: Decoder s Value
decode = Decoder s Value
forall s. Decoder s Value
decodeJSON
encodeJSON :: JSON.Value -> Encoding
encodeJSON :: Value -> Encoding
encodeJSON = Term -> Encoding
forall a. Serialise a => a -> Encoding
encode (Term -> Encoding) -> (Value -> Term) -> Value -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Term
jsonToCbor
decodeJSON :: Decoder s JSON.Value
decodeJSON :: Decoder s Value
decodeJSON = Term -> Value
cborToJson (Term -> Value) -> Decoder s Term -> Decoder s Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Term
forall a s. Serialise a => Decoder s a
decode
cborToJson :: CBOR.Term -> JSON.Value
cborToJson :: Term -> Value
cborToJson (CBOR.TInt Int
n) = Term -> Value
cborToJson (Integer -> Term
CBOR.TInteger (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n))
cborToJson (CBOR.TBytes ByteString
bs) = Text -> Value
JSON.String (ByteString -> Text
base64url ByteString
bs)
cborToJson (CBOR.TBytesI ByteString
bs) = Text -> Value
JSON.String (ByteString -> Text
base64url (ByteString -> ByteString
LBS.toStrict ByteString
bs))
cborToJson (CBOR.TString Text
s) = Text -> Value
JSON.String Text
s
cborToJson (CBOR.TStringI Text
s) = Text -> Value
JSON.String (Text -> Text
Text.Lazy.toStrict Text
s)
cborToJson (TList [Term]
vs) = Array -> Value
JSON.Array ([Value] -> Array
forall a. [a] -> Vector a
Vec.fromList ((Term -> Value) -> [Term] -> [Value]
forall a b. (a -> b) -> [a] -> [b]
map Term -> Value
cborToJson [Term]
vs))
cborToJson (TMap [(Term, Term)]
kvs) = [Pair] -> Value
JSON.object [ (Term -> Text
cborToJsonString Term
k, Term -> Value
cborToJson Term
v)
| (Term
k, Term
v) <- [(Term, Term)]
kvs ]
cborToJson (TBool Bool
b) = Bool -> Value
JSON.Bool Bool
b
cborToJson Term
TNull = Value
JSON.Null
cborToJson (THalf Float
f)
| Float -> Bool
forall a. RealFloat a => a -> Bool
isNaN Float
f Bool -> Bool -> Bool
|| Float -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Float
f = Value
JSON.Null
| Bool
otherwise = Scientific -> Value
JSON.Number (Float -> Scientific
forall a. RealFloat a => a -> Scientific
Scientific.fromFloatDigits Float
f)
cborToJson (TFloat Float
f)
| Float -> Bool
forall a. RealFloat a => a -> Bool
isNaN Float
f Bool -> Bool -> Bool
|| Float -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Float
f = Value
JSON.Null
| Bool
otherwise = Scientific -> Value
JSON.Number (Float -> Scientific
forall a. RealFloat a => a -> Scientific
Scientific.fromFloatDigits Float
f)
cborToJson (TDouble Double
f)
| Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
f Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
f = Value
JSON.Null
| Bool
otherwise = Scientific -> Value
JSON.Number (Double -> Scientific
forall a. RealFloat a => a -> Scientific
Scientific.fromFloatDigits Double
f)
cborToJson (TSimple Word8
_) = Value
JSON.Null
cborToJson (TInteger Integer
n) = Scientific -> Value
JSON.Number (Integer -> Scientific
forall a. Num a => Integer -> a
fromInteger Integer
n)
cborToJson (TTagged Word64
21 (CBOR.TBytes ByteString
bs)) = Text -> Value
JSON.String (ByteString -> Text
base64url ByteString
bs)
cborToJson (TTagged Word64
22 (CBOR.TBytes ByteString
bs)) = Text -> Value
JSON.String (ByteString -> Text
base64 ByteString
bs)
cborToJson (TTagged Word64
23 (CBOR.TBytes ByteString
bs)) = Text -> Value
JSON.String (ByteString -> Text
base16 ByteString
bs)
cborToJson (TTagged Word64
_tag Term
term) = Term -> Value
cborToJson Term
term
cborToJson (TListI [Term]
kvs) = Term -> Value
cborToJson ([Term] -> Term
TList [Term]
kvs)
cborToJson (TMapI [(Term, Term)]
kvs) = Term -> Value
cborToJson ([(Term, Term)] -> Term
TMap [(Term, Term)]
kvs)
cborToJsonString :: CBOR.Term -> Text.Text
cborToJsonString :: Term -> Text
cborToJsonString (TInt Int
n) = String -> Text
Text.pack (Int -> String
forall a. Show a => a -> String
show Int
n)
cborToJsonString (TInteger Integer
n) = String -> Text
Text.pack (Integer -> String
forall a. Show a => a -> String
show Integer
n)
cborToJsonString (TString Text
s) = Text
s
cborToJsonString (TStringI Text
s) = Text -> Text
Text.Lazy.toStrict Text
s
cborToJsonString (TBytes ByteString
bs) = ByteString -> Text
base64url ByteString
bs
cborToJsonString (TBytesI ByteString
bs) = ByteString -> Text
base64url (ByteString -> ByteString
LBS.toStrict ByteString
bs)
base64url :: ByteString -> Text
base64url :: ByteString -> Text
base64url = ByteString -> Text
base64
base64 :: ByteString -> Text
base64 :: ByteString -> Text
base64 = ByteString -> Text
Text.decodeLatin1 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base64.encode
base16 :: ByteString -> Text
base16 :: ByteString -> Text
base16 = ByteString -> Text
Text.decodeLatin1 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base16.encode
jsonToCbor :: JSON.Value -> CBOR.Term
jsonToCbor :: Value -> Term
jsonToCbor (JSON.Object Object
kvs) = [(Term, Term)] -> Term
CBOR.TMap [ (Text -> Term
CBOR.TString Text
k, Value -> Term
jsonToCbor Value
v)
| (Text
k, Value
v) <- Object -> [Pair]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList Object
kvs ]
jsonToCbor (JSON.Array Array
vs) = [Term] -> Term
CBOR.TList [ Value -> Term
jsonToCbor Value
v | Value
v <- Array -> [Value]
forall a. Vector a -> [a]
Vec.toList Array
vs ]
jsonToCbor (JSON.String Text
str) = Text -> Term
CBOR.TString Text
str
jsonToCbor (JSON.Number Scientific
n) = case Scientific -> Either Double Integer
forall r i. (RealFloat r, Integral i) => Scientific -> Either r i
Scientific.floatingOrInteger Scientific
n of
Left Double
d -> Double -> Term
CBOR.TDouble Double
d
Right Integer
i
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
minBound :: Int) Bool -> Bool -> Bool
&&
Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
-> Int -> Term
CBOR.TInt (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i)
| Bool
otherwise -> Integer -> Term
CBOR.TInteger Integer
i
jsonToCbor (JSON.Bool Bool
b) = Bool -> Term
CBOR.TBool Bool
b
jsonToCbor Value
JSON.Null = Term
CBOR.TNull