{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Test.Crypto.PackedBytes (
  AnyPackedBytes (..),
  genPackedBytes,
) where

import Cardano.Crypto.PackedBytes
import Control.Monad.Trans.Fail.String (errorFail)
import Data.Proxy
import Data.Reflection (reifyNat)
import GHC.TypeLits
import Test.Cardano.Base.Bytes (genShortByteString)
import Test.QuickCheck

instance KnownNat n => Arbitrary (PackedBytes n) where
  arbitrary :: Gen (PackedBytes n)
arbitrary = Proxy n -> Gen (PackedBytes n)
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Gen (PackedBytes n)
genPackedBytes (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n)

genPackedBytes :: KnownNat n => proxy n -> Gen (PackedBytes n)
genPackedBytes :: forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Gen (PackedBytes n)
genPackedBytes proxy n
proxy =
  Fail (PackedBytes n) -> PackedBytes n
forall a. HasCallStack => Fail a -> a
errorFail (Fail (PackedBytes n) -> PackedBytes n)
-> (ShortByteString -> Fail (PackedBytes n))
-> ShortByteString
-> PackedBytes n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> Fail (PackedBytes n)
forall (n :: Nat) (m :: * -> *).
(KnownNat n, MonadFail m) =>
ShortByteString -> m (PackedBytes n)
packShortByteString (ShortByteString -> PackedBytes n)
-> Gen ShortByteString -> Gen (PackedBytes n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen ShortByteString
genShortByteString (Integer -> Int
forall a. Num a => Integer -> a
fromInteger (proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal proxy n
proxy))

data AnyPackedBytes where
  AnyPackedBytes :: KnownNat n => PackedBytes n -> AnyPackedBytes

instance Show AnyPackedBytes where
  show :: AnyPackedBytes -> String
show (AnyPackedBytes PackedBytes n
pb) = PackedBytes n -> String
forall a. Show a => a -> String
show PackedBytes n
pb

instance Arbitrary AnyPackedBytes where
  arbitrary :: Gen AnyPackedBytes
arbitrary = do
    NonNegative Integer
n <- Gen (NonNegative Integer)
forall a. Arbitrary a => Gen a
arbitrary
    Integer
-> (forall (n :: Nat). KnownNat n => Proxy n -> Gen AnyPackedBytes)
-> Gen AnyPackedBytes
forall r.
Integer -> (forall (n :: Nat). KnownNat n => Proxy n -> r) -> r
reifyNat Integer
n ((PackedBytes n -> AnyPackedBytes)
-> Gen (PackedBytes n) -> Gen AnyPackedBytes
forall a b. (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PackedBytes n -> AnyPackedBytes
forall (n :: Nat). KnownNat n => PackedBytes n -> AnyPackedBytes
AnyPackedBytes (Gen (PackedBytes n) -> Gen AnyPackedBytes)
-> (Proxy n -> Gen (PackedBytes n))
-> Proxy n
-> Gen AnyPackedBytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy n -> Gen (PackedBytes n)
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Gen (PackedBytes n)
genPackedBytes)