{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS -Wall #-} {-# OPTIONS -Werror #-} module Types ( Op(..) ) where import Control.Monad (mzero) import Data.Aeson (FromJSON(..), Object, Value(..)) import Data.ByteString.Base16 (decode, encode) import Data.ByteString.Char8 (ByteString, unpack) import Data.HashMap.Strict as HashMap (lookup) import Data.Text as Text (Text, drop) import Data.Text.Encoding (encodeUtf8) data Op = Insert ByteString ByteString | Delete ByteString | Lookup ByteString (Maybe ByteString) | Merkleize ByteString instance FromJSON Op where parseJSON = \ case Object object -> maybe mzero pure $ parse object _ -> mzero instance Show Op where show = \ case Insert key value -> "Insert" ++ pretty key ++ pretty value Delete key -> "Delete" ++ pretty key Lookup key value -> "Lookup" ++ pretty key ++ maybe " null" pretty value Merkleize value -> "Merkleize" ++ pretty value where pretty = mappend " 0x" . unpack . encode parse :: Object -> Maybe Op parse object = do op <- HashMap.lookup "op" object case op of "set" -> do key <- get "key" object value <- get "value" object pure $ Insert key value "delete" -> do key <- get "key" object pure $ Delete key "get" -> do key <- get "key" object let value = get "value" object pure $ Lookup key value "stateRoot" -> do value <- get "value" object pure $ Merkleize value _ -> Nothing get :: Text -> Object -> Maybe ByteString get key object = do value <- HashMap.lookup key object case value of String text -> Just $ fst $ decode $ encodeUtf8 $ Text.drop 2 text _ -> Nothing