{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}

module Cardano.Chain.Common.Compact
  ( CompactAddress,
    toCompactAddress,
    fromCompactAddress,
    unsafeGetCompactAddress,
  )
where

import Cardano.Binary (FromCBOR (..), ToCBOR (..), decodeFull', serialize')
import Cardano.Chain.Common.Address (Address (..))
import Cardano.Prelude
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as BSS (fromShort, toShort)
import NoThunks.Class (NoThunks (..))

--------------------------------------------------------------------------------
-- Compact Address
--------------------------------------------------------------------------------

-- | A compact in-memory representation for an 'Address'.
--
-- Convert using 'toCompactAddress' and 'fromCompactAddress'.
newtype CompactAddress = CompactAddress ShortByteString
  deriving (CompactAddress -> CompactAddress -> Bool
(CompactAddress -> CompactAddress -> Bool)
-> (CompactAddress -> CompactAddress -> Bool) -> Eq CompactAddress
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompactAddress -> CompactAddress -> Bool
$c/= :: CompactAddress -> CompactAddress -> Bool
== :: CompactAddress -> CompactAddress -> Bool
$c== :: CompactAddress -> CompactAddress -> Bool
Eq, Eq CompactAddress
Eq CompactAddress
-> (CompactAddress -> CompactAddress -> Ordering)
-> (CompactAddress -> CompactAddress -> Bool)
-> (CompactAddress -> CompactAddress -> Bool)
-> (CompactAddress -> CompactAddress -> Bool)
-> (CompactAddress -> CompactAddress -> Bool)
-> (CompactAddress -> CompactAddress -> CompactAddress)
-> (CompactAddress -> CompactAddress -> CompactAddress)
-> Ord CompactAddress
CompactAddress -> CompactAddress -> Bool
CompactAddress -> CompactAddress -> Ordering
CompactAddress -> CompactAddress -> CompactAddress
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 :: CompactAddress -> CompactAddress -> CompactAddress
$cmin :: CompactAddress -> CompactAddress -> CompactAddress
max :: CompactAddress -> CompactAddress -> CompactAddress
$cmax :: CompactAddress -> CompactAddress -> CompactAddress
>= :: CompactAddress -> CompactAddress -> Bool
$c>= :: CompactAddress -> CompactAddress -> Bool
> :: CompactAddress -> CompactAddress -> Bool
$c> :: CompactAddress -> CompactAddress -> Bool
<= :: CompactAddress -> CompactAddress -> Bool
$c<= :: CompactAddress -> CompactAddress -> Bool
< :: CompactAddress -> CompactAddress -> Bool
$c< :: CompactAddress -> CompactAddress -> Bool
compare :: CompactAddress -> CompactAddress -> Ordering
$ccompare :: CompactAddress -> CompactAddress -> Ordering
$cp1Ord :: Eq CompactAddress
Ord, (forall x. CompactAddress -> Rep CompactAddress x)
-> (forall x. Rep CompactAddress x -> CompactAddress)
-> Generic CompactAddress
forall x. Rep CompactAddress x -> CompactAddress
forall x. CompactAddress -> Rep CompactAddress x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CompactAddress x -> CompactAddress
$cfrom :: forall x. CompactAddress -> Rep CompactAddress x
Generic, Int -> CompactAddress -> ShowS
[CompactAddress] -> ShowS
CompactAddress -> String
(Int -> CompactAddress -> ShowS)
-> (CompactAddress -> String)
-> ([CompactAddress] -> ShowS)
-> Show CompactAddress
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CompactAddress] -> ShowS
$cshowList :: [CompactAddress] -> ShowS
show :: CompactAddress -> String
$cshow :: CompactAddress -> String
showsPrec :: Int -> CompactAddress -> ShowS
$cshowsPrec :: Int -> CompactAddress -> ShowS
Show)
  deriving newtype (CompactAddress -> Int
(CompactAddress -> Int) -> HeapWords CompactAddress
forall a. (a -> Int) -> HeapWords a
heapWords :: CompactAddress -> Int
$cheapWords :: CompactAddress -> Int
HeapWords, Context -> CompactAddress -> IO (Maybe ThunkInfo)
Proxy CompactAddress -> String
(Context -> CompactAddress -> IO (Maybe ThunkInfo))
-> (Context -> CompactAddress -> IO (Maybe ThunkInfo))
-> (Proxy CompactAddress -> String)
-> NoThunks CompactAddress
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy CompactAddress -> String
$cshowTypeOf :: Proxy CompactAddress -> String
wNoThunks :: Context -> CompactAddress -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> CompactAddress -> IO (Maybe ThunkInfo)
noThunks :: Context -> CompactAddress -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> CompactAddress -> IO (Maybe ThunkInfo)
NoThunks)
  deriving anyclass (CompactAddress -> ()
(CompactAddress -> ()) -> NFData CompactAddress
forall a. (a -> ()) -> NFData a
rnf :: CompactAddress -> ()
$crnf :: CompactAddress -> ()
NFData)

instance FromCBOR CompactAddress where
  fromCBOR :: Decoder s CompactAddress
fromCBOR = ShortByteString -> CompactAddress
CompactAddress (ShortByteString -> CompactAddress)
-> (ByteString -> ShortByteString) -> ByteString -> CompactAddress
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> ShortByteString
BSS.toShort (ByteString -> CompactAddress)
-> Decoder s ByteString -> Decoder s CompactAddress
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s ByteString
forall a s. FromCBOR a => Decoder s a
fromCBOR

instance ToCBOR CompactAddress where
  toCBOR :: CompactAddress -> Encoding
toCBOR (CompactAddress ShortByteString
sbs) = ByteString -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR (ShortByteString -> ByteString
BSS.fromShort ShortByteString
sbs)

toCompactAddress :: Address -> CompactAddress
toCompactAddress :: Address -> CompactAddress
toCompactAddress Address
addr =
  ShortByteString -> CompactAddress
CompactAddress (ByteString -> ShortByteString
BSS.toShort (Address -> ByteString
forall a. ToCBOR a => a -> ByteString
serialize' Address
addr))

fromCompactAddress :: CompactAddress -> Address
fromCompactAddress :: CompactAddress -> Address
fromCompactAddress (CompactAddress ShortByteString
addr) =
  case ByteString -> Either DecoderError Address
forall a. FromCBOR a => ByteString -> Either DecoderError a
decodeFull' (ShortByteString -> ByteString
BSS.fromShort ShortByteString
addr) of
    Left DecoderError
err -> Text -> Address
forall a. HasCallStack => Text -> a
panic (Text
"fromCompactAddress: impossible: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DecoderError -> Text
forall a b. (Show a, ConvertText String b) => a -> b
show DecoderError
err)
    Right Address
decAddr -> Address
decAddr

unsafeGetCompactAddress :: CompactAddress -> ShortByteString
unsafeGetCompactAddress :: CompactAddress -> ShortByteString
unsafeGetCompactAddress (CompactAddress ShortByteString
sbs) = ShortByteString
sbs