{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
module Cardano.Ledger.Binary.Version (
Version,
getVersion,
MinVersion,
MaxVersion,
natVersion,
natVersionProxy,
succVersion,
mkVersion,
mkVersion64,
getVersion64,
allVersions,
byronProtVer,
shelleyProtVer,
)
where
import Cardano.Binary (FromCBOR (..), ToCBOR (..))
import Control.DeepSeq (NFData)
import Control.Monad.Trans.Fail.String (errorFail)
import Data.Aeson (FromJSON (..), ToJSON (..))
import Data.Proxy (Proxy (..))
import Data.Word (Word64)
import GHC.TypeLits (KnownNat, natVal, type (<=))
import NoThunks.Class (NoThunks)
newtype Version = Version Word64
deriving (Version -> Version -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Version -> Version -> Bool
$c/= :: Version -> Version -> Bool
== :: Version -> Version -> Bool
$c== :: Version -> Version -> Bool
Eq, Eq Version
Version -> Version -> Bool
Version -> Version -> Ordering
Version -> Version -> Version
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 :: Version -> Version -> Version
$cmin :: Version -> Version -> Version
max :: Version -> Version -> Version
$cmax :: Version -> Version -> Version
>= :: Version -> Version -> Bool
$c>= :: Version -> Version -> Bool
> :: Version -> Version -> Bool
$c> :: Version -> Version -> Bool
<= :: Version -> Version -> Bool
$c<= :: Version -> Version -> Bool
< :: Version -> Version -> Bool
$c< :: Version -> Version -> Bool
compare :: Version -> Version -> Ordering
$ccompare :: Version -> Version -> Ordering
Ord, Int -> Version -> ShowS
[Version] -> ShowS
Version -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Version] -> ShowS
$cshowList :: [Version] -> ShowS
show :: Version -> String
$cshow :: Version -> String
showsPrec :: Int -> Version -> ShowS
$cshowsPrec :: Int -> Version -> ShowS
Show, Version -> ()
forall a. (a -> ()) -> NFData a
rnf :: Version -> ()
$crnf :: Version -> ()
NFData, Context -> Version -> IO (Maybe ThunkInfo)
Proxy Version -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy Version -> String
$cshowTypeOf :: Proxy Version -> String
wNoThunks :: Context -> Version -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> Version -> IO (Maybe ThunkInfo)
noThunks :: Context -> Version -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> Version -> IO (Maybe ThunkInfo)
NoThunks, Typeable Version
Version -> Encoding
(forall t. ToCBOR t => Proxy t -> Size) -> Proxy [Version] -> Size
(forall t. ToCBOR t => Proxy t -> Size) -> Proxy Version -> Size
forall a.
Typeable a
-> (a -> Encoding)
-> ((forall t. ToCBOR t => Proxy t -> Size) -> Proxy a -> Size)
-> ((forall t. ToCBOR t => Proxy t -> Size) -> Proxy [a] -> Size)
-> ToCBOR a
encodedListSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size) -> Proxy [Version] -> Size
$cencodedListSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size) -> Proxy [Version] -> Size
encodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size) -> Proxy Version -> Size
$cencodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size) -> Proxy Version -> Size
toCBOR :: Version -> Encoding
$ctoCBOR :: Version -> Encoding
ToCBOR, [Version] -> Encoding
[Version] -> Value
Version -> Bool
Version -> Encoding
Version -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
omitField :: Version -> Bool
$comitField :: Version -> Bool
toEncodingList :: [Version] -> Encoding
$ctoEncodingList :: [Version] -> Encoding
toJSONList :: [Version] -> Value
$ctoJSONList :: [Version] -> Value
toEncoding :: Version -> Encoding
$ctoEncoding :: Version -> Encoding
toJSON :: Version -> Value
$ctoJSON :: Version -> Value
ToJSON)
type MinVersion = 0
type MaxVersion = 11
instance Enum Version where
toEnum :: Int -> Version
toEnum = forall a. HasCallStack => Fail a -> a
errorFail forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i (m :: * -> *). (Integral i, MonadFail m) => i -> m Version
mkVersion
fromEnum :: Version -> Int
fromEnum (Version Word64
v) = forall a. Enum a => a -> Int
fromEnum Word64
v
instance Bounded Version where
minBound :: Version
minBound = Word64 -> Version
Version (forall a. Num a => Integer -> a
fromInteger (forall (n :: Natural) (proxy :: Natural -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall {k} (t :: k). Proxy t
Proxy @MinVersion)))
maxBound :: Version
maxBound = Word64 -> Version
Version (forall a. Num a => Integer -> a
fromInteger (forall (n :: Natural) (proxy :: Natural -> *).
KnownNat n =>
proxy n -> Integer
natVal (forall {k} (t :: k). Proxy t
Proxy @MaxVersion)))
instance FromCBOR Version where
fromCBOR :: forall s. Decoder s Version
fromCBOR = forall a s. FromCBOR a => Decoder s a
fromCBOR forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). MonadFail m => Word64 -> m Version
mkVersion64
{-# INLINE fromCBOR #-}
instance FromJSON Version where
parseJSON :: Value -> Parser Version
parseJSON Value
v = forall a. FromJSON a => Value -> Parser a
parseJSON Value
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). MonadFail m => Word64 -> m Version
mkVersion64
natVersion :: forall v. (KnownNat v, MinVersion <= v, v <= MaxVersion) => Version
natVersion :: forall (v :: Natural).
(KnownNat v, MinVersion <= v, v <= MaxVersion) =>
Version
natVersion = forall (v :: Natural).
(KnownNat v, MinVersion <= v, v <= MaxVersion) =>
Proxy v -> Version
natVersionProxy (forall {k} (t :: k). Proxy t
Proxy @v)
{-# INLINE natVersion #-}
natVersionProxy :: (KnownNat v, MinVersion <= v, v <= MaxVersion) => Proxy v -> Version
natVersionProxy :: forall (v :: Natural).
(KnownNat v, MinVersion <= v, v <= MaxVersion) =>
Proxy v -> Version
natVersionProxy = Word64 -> Version
Version forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Integer -> a
fromInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Natural) (proxy :: Natural -> *).
KnownNat n =>
proxy n -> Integer
natVal
{-# INLINE natVersionProxy #-}
mkVersion :: (Integral i, MonadFail m) => i -> m Version
mkVersion :: forall i (m :: * -> *). (Integral i, MonadFail m) => i -> m Version
mkVersion i
v
| Integer
vi forall a. Ord a => a -> a -> Bool
< forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
minBound :: Word64) = forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Version is too small: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Integer
vi
| Integer
vi forall a. Ord a => a -> a -> Bool
> forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
maxBound :: Word64) = forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Version is too big: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Integer
vi
| Bool
otherwise = forall (m :: * -> *). MonadFail m => Word64 -> m Version
mkVersion64 (forall a b. (Integral a, Num b) => a -> b
fromIntegral i
v)
where
vi :: Integer
vi = forall a. Integral a => a -> Integer
toInteger i
v
{-# INLINE mkVersion #-}
mkVersion64 :: MonadFail m => Word64 -> m Version
mkVersion64 :: forall (m :: * -> *). MonadFail m => Word64 -> m Version
mkVersion64 Word64
v
| Word64
minVersion forall a. Ord a => a -> a -> Bool
<= Word64
v Bool -> Bool -> Bool
&& Word64
v forall a. Ord a => a -> a -> Bool
<= Word64
maxVersion =
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Version
Version (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
v))
| Bool
otherwise =
forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$
String
"Unsupported version value: "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Word64
v
forall a. [a] -> [a] -> [a]
++ String
". Expected value in bounds: ["
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Word64
minVersion
forall a. [a] -> [a] -> [a]
++ String
", "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Word64
maxVersion
forall a. [a] -> [a] -> [a]
++ String
"]"
where
Version Word64
minVersion = forall a. Bounded a => a
minBound
Version Word64
maxVersion = forall a. Bounded a => a
maxBound
{-# INLINE mkVersion64 #-}
getVersion :: Integral i => Version -> i
getVersion :: forall i. Integral i => Version -> i
getVersion (Version Word64
w64) = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w64
{-# INLINE getVersion #-}
getVersion64 :: Version -> Word64
getVersion64 :: Version -> Word64
getVersion64 (Version Word64
w64) = Word64
w64
{-# INLINE getVersion64 #-}
succVersion :: MonadFail m => Version -> m Version
succVersion :: forall (m :: * -> *). MonadFail m => Version -> m Version
succVersion (Version Word64
v64) = forall (m :: * -> *). MonadFail m => Word64 -> m Version
mkVersion64 (Word64
v64 forall a. Num a => a -> a -> a
+ Word64
1)
{-# INLINE succVersion #-}
allVersions :: [Version]
allVersions :: [Version]
allVersions = [forall a. Bounded a => a
minBound .. forall a. Bounded a => a
maxBound]
byronProtVer :: Version
byronProtVer :: Version
byronProtVer = forall (v :: Natural).
(KnownNat v, MinVersion <= v, v <= MaxVersion) =>
Version
natVersion @1
{-# INLINE byronProtVer #-}
shelleyProtVer :: Version
shelleyProtVer :: Version
shelleyProtVer = forall (v :: Natural).
(KnownNat v, MinVersion <= v, v <= MaxVersion) =>
Version
natVersion @2
{-# INLINE shelleyProtVer #-}