{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Chain.Common.NetworkMagic (
  NetworkMagic (..),
  makeNetworkMagic,
)
where

import Cardano.Crypto.ProtocolMagic (
  AProtocolMagic (..),
  RequiresNetworkMagic (..),
  getProtocolMagic,
 )
import Cardano.HeapWords (HeapWords (..))
import Cardano.Ledger.Binary (
  DecCBOR (..),
  DecoderError (..),
  EncCBOR (..),
  FromCBOR (..),
  ToCBOR (..),
  cborError,
  decodeListLen,
  decodeWord8,
  encodeListLen,
  fromByronCBOR,
  matchSize,
  toByronCBOR,
 )
import Cardano.Prelude hiding (cborError, (%))
import Data.Aeson (ToJSON)
import Formatting (bprint, build, (%))
import qualified Formatting.Buildable as B
import NoThunks.Class (NoThunks (..))

--------------------------------------------------------------------------------
-- NetworkMagic
--------------------------------------------------------------------------------

data NetworkMagic
  = NetworkMainOrStage
  | NetworkTestnet {-# UNPACK #-} !Word32
  deriving (Int -> NetworkMagic -> ShowS
[NetworkMagic] -> ShowS
NetworkMagic -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NetworkMagic] -> ShowS
$cshowList :: [NetworkMagic] -> ShowS
show :: NetworkMagic -> String
$cshow :: NetworkMagic -> String
showsPrec :: Int -> NetworkMagic -> ShowS
$cshowsPrec :: Int -> NetworkMagic -> ShowS
Show, NetworkMagic -> NetworkMagic -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NetworkMagic -> NetworkMagic -> Bool
$c/= :: NetworkMagic -> NetworkMagic -> Bool
== :: NetworkMagic -> NetworkMagic -> Bool
$c== :: NetworkMagic -> NetworkMagic -> Bool
Eq, Eq NetworkMagic
NetworkMagic -> NetworkMagic -> Bool
NetworkMagic -> NetworkMagic -> Ordering
NetworkMagic -> NetworkMagic -> NetworkMagic
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NetworkMagic -> NetworkMagic -> NetworkMagic
$cmin :: NetworkMagic -> NetworkMagic -> NetworkMagic
max :: NetworkMagic -> NetworkMagic -> NetworkMagic
$cmax :: NetworkMagic -> NetworkMagic -> NetworkMagic
>= :: NetworkMagic -> NetworkMagic -> Bool
$c>= :: NetworkMagic -> NetworkMagic -> Bool
> :: NetworkMagic -> NetworkMagic -> Bool
$c> :: NetworkMagic -> NetworkMagic -> Bool
<= :: NetworkMagic -> NetworkMagic -> Bool
$c<= :: NetworkMagic -> NetworkMagic -> Bool
< :: NetworkMagic -> NetworkMagic -> Bool
$c< :: NetworkMagic -> NetworkMagic -> Bool
compare :: NetworkMagic -> NetworkMagic -> Ordering
$ccompare :: NetworkMagic -> NetworkMagic -> Ordering
Ord, forall x. Rep NetworkMagic x -> NetworkMagic
forall x. NetworkMagic -> Rep NetworkMagic x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NetworkMagic x -> NetworkMagic
$cfrom :: forall x. NetworkMagic -> Rep NetworkMagic x
Generic, NetworkMagic -> ()
forall a. (a -> ()) -> NFData a
rnf :: NetworkMagic -> ()
$crnf :: NetworkMagic -> ()
NFData, Context -> NetworkMagic -> IO (Maybe ThunkInfo)
Proxy NetworkMagic -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy NetworkMagic -> String
$cshowTypeOf :: Proxy NetworkMagic -> String
wNoThunks :: Context -> NetworkMagic -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> NetworkMagic -> IO (Maybe ThunkInfo)
noThunks :: Context -> NetworkMagic -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> NetworkMagic -> IO (Maybe ThunkInfo)
NoThunks)

instance B.Buildable NetworkMagic where
  build :: NetworkMagic -> Builder
build NetworkMagic
NetworkMainOrStage = Builder
"NetworkMainOrStage"
  build (NetworkTestnet Word32
n) = forall a. Format Builder a -> a
bprint (Format (Word32 -> Builder) (Word32 -> Builder)
"NetworkTestnet (" forall r a r'. Format r a -> Format r' r -> Format r' a
% forall a r. Buildable a => Format r (a -> r)
build forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Builder Builder
")") Word32
n

-- Used for debugging purposes only
instance ToJSON NetworkMagic

instance HeapWords NetworkMagic where
  heapWords :: NetworkMagic -> Int
heapWords NetworkMagic
NetworkMainOrStage = Int
0
  heapWords (NetworkTestnet Word32
_) = Int
2

instance ToCBOR NetworkMagic where
  toCBOR :: NetworkMagic -> Encoding
toCBOR = forall a. EncCBOR a => a -> Encoding
toByronCBOR

instance FromCBOR NetworkMagic where
  fromCBOR :: forall s. Decoder s NetworkMagic
fromCBOR = forall a s. DecCBOR a => Decoder s a
fromByronCBOR

instance EncCBOR NetworkMagic where
  encCBOR :: NetworkMagic -> Encoding
encCBOR = \case
    NetworkMagic
NetworkMainOrStage ->
      Word -> Encoding
encodeListLen Word
1 forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR @Word8 Word8
0
    NetworkTestnet Word32
n ->
      Word -> Encoding
encodeListLen Word
2 forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR @Word8 Word8
1 forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR Word32
n

instance DecCBOR NetworkMagic where
  decCBOR :: forall s. Decoder s NetworkMagic
decCBOR = do
    Int
len <- forall s. Decoder s Int
decodeListLen
    Word8
tag <- forall s. Decoder s Word8
decodeWord8
    case Word8
tag of
      Word8
0 -> forall s. Text -> Int -> Int -> Decoder s ()
matchSize Text
"NetworkMagic" Int
1 Int
len forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> NetworkMagic
NetworkMainOrStage
      Word8
1 -> forall s. Text -> Int -> Int -> Decoder s ()
matchSize Text
"NetworkMagic" Int
2 Int
len forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word32 -> NetworkMagic
NetworkTestnet forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. DecCBOR a => Decoder s a
decCBOR
      Word8
_ -> forall (m :: * -> *) e a. (MonadFail m, Buildable e) => e -> m a
cborError forall a b. (a -> b) -> a -> b
$ Text -> Word8 -> DecoderError
DecoderErrorUnknownTag Text
"NetworkMagic" Word8
tag

makeNetworkMagic :: AProtocolMagic a -> NetworkMagic
makeNetworkMagic :: forall a. AProtocolMagic a -> NetworkMagic
makeNetworkMagic AProtocolMagic a
pm = case forall a. AProtocolMagic a -> RequiresNetworkMagic
getRequiresNetworkMagic AProtocolMagic a
pm of
  RequiresNetworkMagic
RequiresNoMagic -> NetworkMagic
NetworkMainOrStage
  RequiresNetworkMagic
RequiresMagic -> Word32 -> NetworkMagic
NetworkTestnet (forall a. AProtocolMagic a -> Word32
getProtocolMagic AProtocolMagic a
pm)