{-|
Description: 'cryptoids' with implied namespaces
License: BSD3

When unambiguous it can be convenient to automatically infer the namespace based on the plaintext type.

Consider using newtype wrappers in order to do so.
-}
module Data.CryptoID.Class.ImplicitNamespace
  ( E.MonadCrypto(..)
  , CryptoIDNamespace
  , HasCryptoID
  , CryptoID, pattern E.CryptoID, E.ciphertext
  , encrypt, decrypt
  ) where

import qualified Data.CryptoID.Class as E
import qualified Data.CryptoID as E

import GHC.TypeLits (Symbol)
  

-- | Type family of @namespace@s associated to certain @plaintext@-types (parameterized over @ciphertext@ for completeness)
type family CryptoIDNamespace (ciphertext :: *) (plaintext :: *) :: Symbol

-- | 'E.HasCryptoID' reformulated to utilize 'CryptoIDNamespace'
type HasCryptoID ciphertext plaintext = E.HasCryptoID (CryptoIDNamespace ciphertext plaintext) ciphertext plaintext

-- | 'E.CryptoID' reformulated to utilize 'CryptoIDNamespace'
type CryptoID ciphertext plaintext = E.CryptoID (CryptoIDNamespace ciphertext plaintext) ciphertext


encrypt :: HasCryptoID ciphertext plaintext m => plaintext -> m (CryptoID ciphertext plaintext)
-- ^ Specialised version of 'encrypt' for when @(plaintext, ciphertext)@ uniquely determines the namespace
encrypt = E.encrypt

decrypt :: HasCryptoID ciphertext plaintext m => CryptoID ciphertext plaintext -> m plaintext
-- ^ Specialised version of 'decrypt' for when @(plaintext, ciphertext)@ uniquely determines the namespace
decrypt = E.decrypt