extism-pdk-0.2.0.0: src/Extism/PDK/MsgPack.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Provides the ability to use MessagePack for plugin input/output
module Extism.PDK.MsgPack
( module Extism.PDK.MsgPack,
module Data.MessagePack,
module Map,
)
where
import Data.Bifunctor (bimap)
import qualified Data.ByteString as B
import Data.ByteString.Internal (c2w, w2c)
import Data.Int
import qualified Data.Map.Strict as Map
import Data.MessagePack
import qualified Data.Serialize as S
import Data.Word
import GHC.Generics
class MsgPack a where
toMsgPack :: a -> Object
fromMsgPack :: Object -> Maybe a
class GMsgPack f where
toGMsgPack :: f a -> Object
fromGMsgPack :: Object -> Maybe (f a)
fromGMsgPack _ = Nothing
instance GMsgPack U1 where
toGMsgPack U1 = ObjectNil
fromGMsgPack ObjectNil = Just U1
instance (GMsgPack a, GMsgPack b) => GMsgPack (a :*: b) where
toGMsgPack (x :*: y) = array [toGMsgPack x, toGMsgPack y]
-- fromGMsgPack (ObjectArray [a, b]) = Just (a :*: b)
instance (GMsgPack a, GMsgPack b) => GMsgPack (a :+: b) where
toGMsgPack (L1 x) = toGMsgPack x
toGMsgPack (R1 x) = toGMsgPack x
instance (GMsgPack a) => GMsgPack (M1 i c a) where
toGMsgPack (M1 x) = toGMsgPack x
instance (MsgPack a) => GMsgPack (K1 i a) where
toGMsgPack (K1 x) = toMsgPack x
toByteString x = B.pack (Prelude.map c2w x)
fromByteString bs = Prelude.map w2c $ B.unpack bs
instance MsgPack Bool where
toMsgPack = ObjectBool
fromMsgPack (ObjectBool b) = Just b
fromMsgPack _ = Nothing
instance MsgPack String where
toMsgPack s = ObjectString (toByteString s)
fromMsgPack (ObjectString s) = Just (fromByteString s)
fromMsgPack _ = Nothing
instance MsgPack B.ByteString where
toMsgPack = ObjectBinary
fromMsgPack (ObjectString s) = Just s
fromMsgPack (ObjectBinary s) = Just s
fromMsgPack _ = Nothing
instance MsgPack Int where
toMsgPack i = ObjectInt (fromIntegral i)
fromMsgPack (ObjectInt i) = Just (fromIntegral i)
fromMsgPack _ = Nothing
instance MsgPack Int64 where
toMsgPack = ObjectInt
fromMsgPack (ObjectInt i) = Just i
fromMsgPack _ = Nothing
instance MsgPack Word where
toMsgPack w = ObjectUInt (fromIntegral w)
fromMsgPack (ObjectUInt x) = Just (fromIntegral x)
fromMsgPack _ = Nothing
instance MsgPack Word64 where
toMsgPack = ObjectUInt
fromMsgPack (ObjectUInt x) = Just x
fromMsgPack _ = Nothing
instance (MsgPack a) => MsgPack (Maybe a) where
toMsgPack Nothing = ObjectNil
toMsgPack (Just a) = toMsgPack a
fromMsgPack = fromMsgPack
instance MsgPack () where
toMsgPack () = ObjectNil
fromMsgPack ObjectNil = Just ()
fromMsgPack _ = Nothing
instance MsgPack Float where
toMsgPack = ObjectFloat
fromMsgPack (ObjectFloat f) = Just f
fromMsgPack _ = Nothing
instance MsgPack Double where
toMsgPack = ObjectDouble
fromMsgPack (ObjectDouble d) = Just d
fromMsgPack _ = Nothing
instance MsgPack Object where
toMsgPack x = x
fromMsgPack = Just
(.=) :: (MsgPack a) => (MsgPack b) => a -> b -> (Object, Object)
(.=) k v = (toMsgPack k, toMsgPack v)
lookup :: (MsgPack a) => (MsgPack b) => a -> Object -> Maybe b
lookup k (ObjectMap map) =
let x = Map.lookup (toMsgPack k) map
in fromMsgPack =<< x
lookup _ _ = Nothing
set k v (ObjectMap map) =
ObjectMap $ Map.insert (toMsgPack k) (toMsgPack v) map
(.?) :: (MsgPack a) => (MsgPack b) => Object -> a -> Maybe b
(.?) a b = Extism.PDK.MsgPack.lookup b a
object :: (MsgPack a) => (MsgPack b) => [(a, b)] -> Object
object l = ObjectMap (Map.fromList $ map (bimap toMsgPack toMsgPack) l)
array :: (MsgPack a) => [a] -> Object
array l = ObjectArray (map toMsgPack l)
encode :: (MsgPack a) => a -> B.ByteString
encode x =
let y = toMsgPack x
in S.encode y
decode :: (MsgPack a) => B.ByteString -> Either String a
decode bs =
case S.decode bs of
Right a -> case fromMsgPack a of
Nothing -> Left "Invalid type conversion"
Just x -> Right x
Left s -> Left s