module Serokell.Data.Variant.Serialization
(
) where
import qualified Data.Aeson as Aeson
import Data.Bifunctor (bimap)
import Data.Binary (Binary)
import Data.Binary.Orphans ()
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM hiding (HashMap)
import Data.SafeCopy (SafeCopy)
import Data.Scientific (floatingOrInteger)
import qualified Data.Serialize as Cereal
import Data.Text (Text)
import qualified Data.Text.Encoding as TE
import Data.Vector.Serialize ()
import Serokell.Data.Variant.Variant (VarMap, Variant (..))
import Serokell.Util.Base64 (JsonByteString (JsonByteString))
import Serokell.Util.Text (show')
varMapToObject :: VarMap -> Aeson.Object
varMapToObject = HM.fromList . map (bimap show' Aeson.toJSON) . HM.toList
instance Aeson.ToJSON Variant where
toJSON VarNone = Aeson.Null
toJSON (VarBool v) = Aeson.toJSON v
toJSON (VarInt v) = Aeson.toJSON v
toJSON (VarUInt v) = Aeson.toJSON v
toJSON (VarFloat v) = Aeson.toJSON v
toJSON (VarBytes v) = Aeson.toJSON . JsonByteString $ v
toJSON (VarString v) = Aeson.toJSON v
toJSON (VarList v) = Aeson.toJSON v
toJSON (VarMap v) = Aeson.Object . varMapToObject $ v
toEncoding VarNone = Aeson.toEncoding Aeson.Null
toEncoding (VarBool v) = Aeson.toEncoding v
toEncoding (VarInt v) = Aeson.toEncoding v
toEncoding (VarUInt v) = Aeson.toEncoding v
toEncoding (VarFloat v) = Aeson.toEncoding v
toEncoding (VarBytes v) = Aeson.toEncoding . JsonByteString $ v
toEncoding (VarString v) = Aeson.toEncoding v
toEncoding (VarList v) = Aeson.toEncoding v
toEncoding (VarMap v) = Aeson.toEncoding . varMapToObject $ v
instance Aeson.FromJSON Variant where
parseJSON Aeson.Null = pure VarNone
parseJSON (Aeson.Bool v) = pure . VarBool $ v
parseJSON (Aeson.Number v) =
pure . either VarFloat convertInt . floatingOrInteger $ v
where
convertInt :: Integer -> Variant
convertInt i
| i < 0 = VarInt $ fromIntegral i
| otherwise = VarUInt $ fromIntegral i
parseJSON (Aeson.String v) = pure . VarString $ v
parseJSON (Aeson.Array v) = fmap VarList . mapM Aeson.parseJSON $ v
parseJSON (Aeson.Object v) =
fmap (VarMap . HM.fromList) .
mapM
(\(key,val) ->
(VarString key, ) <$> Aeson.parseJSON val) .
HM.toList $
v
instance Cereal.Serialize Text where
put = Cereal.put . TE.encodeUtf8
get = TE.decodeUtf8 <$> Cereal.get
instance (Eq a, Hashable a, Cereal.Serialize a, Cereal.Serialize b) =>
Cereal.Serialize (HashMap a b) where
put = Cereal.put . HM.toList
get = HM.fromList <$> Cereal.get
instance Cereal.Serialize Variant
instance SafeCopy Variant
instance Binary Variant