-- SPDX-FileCopyrightText: 2022 Serokell <https://serokell.io>
-- SPDX-License-Identifier: MPL-2.0

{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE RoleAnnotations #-}

-- | Types for lower-level bindings
module Crypto.BLST.Internal.Bindings.Types
  ( module Crypto.BLST.Internal.Bindings.Types
  ) where

import Prelude hiding (length)

import Control.DeepSeq (NFData(..))
import Data.ByteArray (Bytes, ScrubbedBytes)
import Data.ByteArray.Sized (SizedByteArray(..))
import Data.Coerce (coerce)
import Data.Kind (Type)
import GHC.TypeNats (Nat)

import Crypto.BLST.Internal.Demote

-- | Kind of point.
data PointKind = P1 | P2

instance Demote 'P1 where demote :: PointKind
demote = PointKind
P1
instance Demote 'P2 where demote :: PointKind
demote = PointKind
P2

-- | Size of type's representation in bytes.
type SizeOf :: Type -> Nat
type family SizeOf t

type role Point nominal
-- | Point representation.
newtype Point (a :: PointKind) = Point ( SizedByteArray (SizeOf (Point a)) Bytes )
  deriving stock (Int -> Point a -> ShowS
[Point a] -> ShowS
Point a -> String
(Int -> Point a -> ShowS)
-> (Point a -> String) -> ([Point a] -> ShowS) -> Show (Point a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (a :: PointKind). Int -> Point a -> ShowS
forall (a :: PointKind). [Point a] -> ShowS
forall (a :: PointKind). Point a -> String
$cshowsPrec :: forall (a :: PointKind). Int -> Point a -> ShowS
showsPrec :: Int -> Point a -> ShowS
$cshow :: forall (a :: PointKind). Point a -> String
show :: Point a -> String
$cshowList :: forall (a :: PointKind). [Point a] -> ShowS
showList :: [Point a] -> ShowS
Show, Point a -> Point a -> Bool
(Point a -> Point a -> Bool)
-> (Point a -> Point a -> Bool) -> Eq (Point a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (a :: PointKind). Point a -> Point a -> Bool
$c== :: forall (a :: PointKind). Point a -> Point a -> Bool
== :: Point a -> Point a -> Bool
$c/= :: forall (a :: PointKind). Point a -> Point a -> Bool
/= :: Point a -> Point a -> Bool
Eq)

instance NFData (Point a) where
  rnf :: Point a -> ()
rnf = forall a. NFData a => a -> ()
rnf @Bytes (Bytes -> ()) -> (Point a -> Bytes) -> Point a -> ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizedByteArray Any Bytes -> Bytes
forall (n :: Nat) ba. SizedByteArray n ba -> ba
unSizedByteArray (SizedByteArray Any Bytes -> Bytes)
-> (Point a -> SizedByteArray Any Bytes) -> Point a -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point a -> SizedByteArray Any Bytes
forall a b. Coercible a b => a -> b
coerce

type role Affine nominal
-- | Affine point representation.
newtype Affine (a :: PointKind) = Affine { forall (a :: PointKind).
Affine a -> SizedByteArray (SizeOf (Affine a)) Bytes
unAffine :: SizedByteArray (SizeOf (Affine a)) Bytes }
  deriving stock (Int -> Affine a -> ShowS
[Affine a] -> ShowS
Affine a -> String
(Int -> Affine a -> ShowS)
-> (Affine a -> String) -> ([Affine a] -> ShowS) -> Show (Affine a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (a :: PointKind). Int -> Affine a -> ShowS
forall (a :: PointKind). [Affine a] -> ShowS
forall (a :: PointKind). Affine a -> String
$cshowsPrec :: forall (a :: PointKind). Int -> Affine a -> ShowS
showsPrec :: Int -> Affine a -> ShowS
$cshow :: forall (a :: PointKind). Affine a -> String
show :: Affine a -> String
$cshowList :: forall (a :: PointKind). [Affine a] -> ShowS
showList :: [Affine a] -> ShowS
Show, Affine a -> Affine a -> Bool
(Affine a -> Affine a -> Bool)
-> (Affine a -> Affine a -> Bool) -> Eq (Affine a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (a :: PointKind). Affine a -> Affine a -> Bool
$c== :: forall (a :: PointKind). Affine a -> Affine a -> Bool
== :: Affine a -> Affine a -> Bool
$c/= :: forall (a :: PointKind). Affine a -> Affine a -> Bool
/= :: Affine a -> Affine a -> Bool
Eq)

instance NFData (Affine a) where
  rnf :: Affine a -> ()
rnf = forall a. NFData a => a -> ()
rnf @Bytes (Bytes -> ()) -> (Affine a -> Bytes) -> Affine a -> ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizedByteArray Any Bytes -> Bytes
forall (n :: Nat) ba. SizedByteArray n ba -> ba
unSizedByteArray (SizedByteArray Any Bytes -> Bytes)
-> (Affine a -> SizedByteArray Any Bytes) -> Affine a -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Affine a -> SizedByteArray Any Bytes
forall a b. Coercible a b => a -> b
coerce

-- | Scalar value representation.
newtype Scalar = Scalar ( SizedByteArray (SizeOf Scalar) ScrubbedBytes )
  deriving stock (Int -> Scalar -> ShowS
[Scalar] -> ShowS
Scalar -> String
(Int -> Scalar -> ShowS)
-> (Scalar -> String) -> ([Scalar] -> ShowS) -> Show Scalar
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Scalar -> ShowS
showsPrec :: Int -> Scalar -> ShowS
$cshow :: Scalar -> String
show :: Scalar -> String
$cshowList :: [Scalar] -> ShowS
showList :: [Scalar] -> ShowS
Show, Scalar -> Scalar -> Bool
(Scalar -> Scalar -> Bool)
-> (Scalar -> Scalar -> Bool) -> Eq Scalar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Scalar -> Scalar -> Bool
== :: Scalar -> Scalar -> Bool
$c/= :: Scalar -> Scalar -> Bool
/= :: Scalar -> Scalar -> Bool
Eq)

instance NFData Scalar where
  rnf :: Scalar -> ()
rnf = forall a. NFData a => a -> ()
rnf @ScrubbedBytes (ScrubbedBytes -> ()) -> (Scalar -> ScrubbedBytes) -> Scalar -> ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizedByteArray Any ScrubbedBytes -> ScrubbedBytes
forall (n :: Nat) ba. SizedByteArray n ba -> ba
unSizedByteArray (SizedByteArray Any ScrubbedBytes -> ScrubbedBytes)
-> (Scalar -> SizedByteArray Any ScrubbedBytes)
-> Scalar
-> ScrubbedBytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scalar -> SizedByteArray Any ScrubbedBytes
forall a b. Coercible a b => a -> b
coerce

-- | Pairing context.
newtype PairingCtx = PairingCtx Bytes
  deriving newtype PairingCtx -> ()
(PairingCtx -> ()) -> NFData PairingCtx
forall a. (a -> ()) -> NFData a
$crnf :: PairingCtx -> ()
rnf :: PairingCtx -> ()
NFData

-- | Flag to choose whether values are hashed or encoded to the curve.
data EncodeMethod = Encode | Hash
  deriving stock (EncodeMethod -> EncodeMethod -> Bool
(EncodeMethod -> EncodeMethod -> Bool)
-> (EncodeMethod -> EncodeMethod -> Bool) -> Eq EncodeMethod
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EncodeMethod -> EncodeMethod -> Bool
== :: EncodeMethod -> EncodeMethod -> Bool
$c/= :: EncodeMethod -> EncodeMethod -> Bool
/= :: EncodeMethod -> EncodeMethod -> Bool
Eq, Int -> EncodeMethod
EncodeMethod -> Int
EncodeMethod -> [EncodeMethod]
EncodeMethod -> EncodeMethod
EncodeMethod -> EncodeMethod -> [EncodeMethod]
EncodeMethod -> EncodeMethod -> EncodeMethod -> [EncodeMethod]
(EncodeMethod -> EncodeMethod)
-> (EncodeMethod -> EncodeMethod)
-> (Int -> EncodeMethod)
-> (EncodeMethod -> Int)
-> (EncodeMethod -> [EncodeMethod])
-> (EncodeMethod -> EncodeMethod -> [EncodeMethod])
-> (EncodeMethod -> EncodeMethod -> [EncodeMethod])
-> (EncodeMethod -> EncodeMethod -> EncodeMethod -> [EncodeMethod])
-> Enum EncodeMethod
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: EncodeMethod -> EncodeMethod
succ :: EncodeMethod -> EncodeMethod
$cpred :: EncodeMethod -> EncodeMethod
pred :: EncodeMethod -> EncodeMethod
$ctoEnum :: Int -> EncodeMethod
toEnum :: Int -> EncodeMethod
$cfromEnum :: EncodeMethod -> Int
fromEnum :: EncodeMethod -> Int
$cenumFrom :: EncodeMethod -> [EncodeMethod]
enumFrom :: EncodeMethod -> [EncodeMethod]
$cenumFromThen :: EncodeMethod -> EncodeMethod -> [EncodeMethod]
enumFromThen :: EncodeMethod -> EncodeMethod -> [EncodeMethod]
$cenumFromTo :: EncodeMethod -> EncodeMethod -> [EncodeMethod]
enumFromTo :: EncodeMethod -> EncodeMethod -> [EncodeMethod]
$cenumFromThenTo :: EncodeMethod -> EncodeMethod -> EncodeMethod -> [EncodeMethod]
enumFromThenTo :: EncodeMethod -> EncodeMethod -> EncodeMethod -> [EncodeMethod]
Enum, EncodeMethod
EncodeMethod -> EncodeMethod -> Bounded EncodeMethod
forall a. a -> a -> Bounded a
$cminBound :: EncodeMethod
minBound :: EncodeMethod
$cmaxBound :: EncodeMethod
maxBound :: EncodeMethod
Bounded, Int -> EncodeMethod -> ShowS
[EncodeMethod] -> ShowS
EncodeMethod -> String
(Int -> EncodeMethod -> ShowS)
-> (EncodeMethod -> String)
-> ([EncodeMethod] -> ShowS)
-> Show EncodeMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EncodeMethod -> ShowS
showsPrec :: Int -> EncodeMethod -> ShowS
$cshow :: EncodeMethod -> String
show :: EncodeMethod -> String
$cshowList :: [EncodeMethod] -> ShowS
showList :: [EncodeMethod] -> ShowS
Show)

instance Demote 'Hash where demote :: EncodeMethod
demote = EncodeMethod
Hash
instance Demote 'Encode where demote :: EncodeMethod
demote = EncodeMethod
Encode

-- | Serialized size of 'P1'.
type P1SerializeSize = 96

-- | Compressed serialized size of 'P1'.
type P1CompressSize = 48

-- | Serialized size of 'P2'.
type P2SerializeSize = 192

-- | Compressed serialized size of 'P2'.
type P2CompressSize = 96

-- | Scalar serialized size.
type SkSerializeSize = 32