{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric  #-}

-- |
-- Module      :  Network.Polkadot.Metadata.MagicNumber
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  portable
--
-- Metadata V9 data type.
--

module Network.Polkadot.Metadata.MagicNumber where

import           Codec.Scale.Class (Decode (..), Encode (..))
import           Codec.Scale.Core  ()
import           Control.Monad     (when)
import           Data.Aeson        (FromJSON (..), ToJSON (..), Value (Number))
import           Data.Word         (Word32)

-- | `meta`, reversed for Little Endian encoding
magic_number :: Word32
magic_number :: Word32
magic_number = Word32
0x6174656d

-- | 32-bit prefix magic sentence.
data MagicNumber = MagicNumber
    deriving (MagicNumber -> MagicNumber -> Bool
(MagicNumber -> MagicNumber -> Bool)
-> (MagicNumber -> MagicNumber -> Bool) -> Eq MagicNumber
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MagicNumber -> MagicNumber -> Bool
== :: MagicNumber -> MagicNumber -> Bool
$c/= :: MagicNumber -> MagicNumber -> Bool
/= :: MagicNumber -> MagicNumber -> Bool
Eq, Int -> MagicNumber -> ShowS
[MagicNumber] -> ShowS
MagicNumber -> String
(Int -> MagicNumber -> ShowS)
-> (MagicNumber -> String)
-> ([MagicNumber] -> ShowS)
-> Show MagicNumber
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MagicNumber -> ShowS
showsPrec :: Int -> MagicNumber -> ShowS
$cshow :: MagicNumber -> String
show :: MagicNumber -> String
$cshowList :: [MagicNumber] -> ShowS
showList :: [MagicNumber] -> ShowS
Show)

instance Decode MagicNumber where
    get :: Get MagicNumber
get = do
        Word32
n <- Get Word32
forall a. Decode a => Get a
get
        Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word32
n Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32
magic_number) (Get () -> Get ()) -> Get () -> Get ()
forall a b. (a -> b) -> a -> b
$
            String -> Get ()
forall a. String -> Get a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Bad magic number"
        MagicNumber -> Get MagicNumber
forall a. a -> Get a
forall (m :: * -> *) a. Monad m => a -> m a
return MagicNumber
MagicNumber

instance Encode MagicNumber where
    put :: Putter MagicNumber
put MagicNumber
_ = Putter Word32
forall a. Encode a => Putter a
put Word32
magic_number

instance FromJSON MagicNumber where
    parseJSON :: Value -> Parser MagicNumber
parseJSON (Number Scientific
n) = do
        Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Scientific
n Scientific -> Scientific -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32 -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
magic_number) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$
            String -> Parser ()
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Bad magic number"
        MagicNumber -> Parser MagicNumber
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return MagicNumber
MagicNumber
    parseJSON Value
_ = String -> Parser MagicNumber
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Magic number should be a number"

instance ToJSON MagicNumber where
    toJSON :: MagicNumber -> Value
toJSON MagicNumber
_ = Word32 -> Value
forall a. ToJSON a => a -> Value
toJSON Word32
magic_number