content: -- {-# LANGUAGE FlexibleInstances #-}
  
  -- |
  -- Module      : Crypto.Saltine.Class
  -- Copyright   : (c) Joseph Abrahamson 2013
  -- License     : MIT
  --
  -- Maintainer  : me@jspha.com
  -- Stability   : experimental
  -- Portability : non-portable
  --
  -- Saltine type classes
  module Crypto.Saltine.Class (
    IsEncoding (..),
    IsNonce (..)
    ) where
  
  import Data.Profunctor
  import Data.ByteString (ByteString)
  
  -- | Class for all keys and nonces in Saltine which have a
  -- representation as ByteString. 'encoded' is a 'Prism' of
  -- type @Prism' ByteString a@ compatible with "Control.Lens" and
  -- is automatically deduced.
  class IsEncoding a where
    encode  :: a -> ByteString
    decode  :: ByteString -> Maybe a
    encoded :: (Choice p, Applicative f)
               => p a (f a) -> p ByteString (f ByteString)
    encoded = prism' encode decode
    {-# INLINE encoded #-}
  
  -- | A generic class for interacting with nonces.
  class IsNonce n where
    zero  :: n
    -- ^ Some privileged nonce value.
    nudge :: n -> n
    -- ^ Some perturbation on nonces such that @n /= nudge n@ with high
    -- probability. Since nonces are finite, repeats may happen in
    -- particularly small cases, but no nonces in Saltine are so
    -- small. This is not guaranteed to be difficult to predict---if a
    -- nonce had an `Enum` instance `succ` would be a good
    -- implementation excepting that `succ` is partial.
  
  -- Copied over from Control.Lens
  
  prism' :: (Applicative f, Choice p) =>
            (a1 -> a) -> (a -> Maybe a2) -> p a2 (f a1) -> p a (f a)
  prism' bs sma = prism bs (\s -> maybe (Left s) Right (sma s))
  {-# INLINE prism' #-}
  
  prism :: (Applicative f, Choice p) =>
           (a2 -> a1) -> (a -> Either a1 a3) -> p a3 (f a2) -> p a (f a1)
  prism bt seta = dimap seta (either pure (fmap bt)) . right'
  {-# INLINE prism #-}
  