packages feed

morley-1.4.0: src/Morley/Micheline/Json.hs

-- SPDX-FileCopyrightText: 2018 obsidian.systems
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-obsidian-systems

-- | Module that defines helper types and functions that are related
-- to Micheline.
module Morley.Micheline.Json
  ( StringEncode (..)
  , TezosBigNum
  , TezosInt64
  ) where

import Data.Aeson (FromJSON, ToJSON, parseJSON, toEncoding, toJSON)
import qualified Data.Aeson.Encoding as AE
import qualified Data.Aeson.Types as Aeson
import Data.Bits (Bits)
import Data.Typeable (typeRep)
import qualified Text.Show as T

parseAsString :: forall a. (Read a, Typeable a) => Aeson.Value -> Aeson.Parser a
parseAsString = Aeson.withText (T.show $ typeRep (Proxy :: Proxy a)) $ \txt ->
  maybe (fail "Failed to parse string") pure $ readMaybe (toString txt)

parseStringEncodedIntegral :: (Read a, Typeable a) => Aeson.Value -> Aeson.Parser (StringEncode a)
parseStringEncodedIntegral x = StringEncode <$> parseAsString x

newtype StringEncode a = StringEncode { unStringEncode :: a }
  deriving stock (Generic, Eq, Ord, Bounded, Read, Show)
  deriving newtype (Enum, Num, Integral, Bits, Real, NFData, Hashable)

type TezosBigNum = StringEncode Integer

instance FromJSON TezosBigNum where
  parseJSON = parseStringEncodedIntegral

instance ToJSON TezosBigNum where
  toJSON (StringEncode x) = Aeson.String $ show x
  toEncoding (StringEncode x) = AE.integerText x

type TezosInt64 = StringEncode Int64

instance FromJSON TezosInt64 where
  parseJSON = parseStringEncodedIntegral

instance ToJSON TezosInt64 where
  toJSON (StringEncode x) = Aeson.String $ show x
  toEncoding (StringEncode x) = AE.int64Text x