    {-# language DataKinds #-}
    {-# language RankNTypes #-}
    {-# language TypeFamilies #-}
    -- |
    -- Module       : Data.ByteString.Base64.Types.Internal
    -- Copyright    : (c) 2019-2023 Emily Pillmore
    -- License      : BSD-style
    --
    -- Maintainer   : Emily Pillmore <emilypi@cohomolo.gy>,
    --                sofia-m-a <https://github.com/sofia-m-a>
    -- Stability    : stable
    -- Portability  : non-portable
    --
    -- This module contains the 'Base64' newtype, 'Alphabet'
    -- datatype, and associated instances for 'Base64'.
    --
    module Data.Base64.Types.Internal
    ( Alphabet(..)
    , Base64(..)
    ) where

    import Control.DeepSeq (NFData, rnf)

    -- | The different kinds of supported Base64 encodings
    data Alphabet
      = StdPadded
        -- ^ Standard base64 according to [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
        -- Padding is always inserted when encoding, and required when decoding
      | UrlPadded
        -- ^ Standard base64 according to [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
        -- Padding is never inserted when encoding, and optional when decoding per
        -- [RFC 7049](https://datatracker.ietf.org/doc/html/rfc7049#section-2.4.4.2).
      | UrlUnpadded
        -- ^ URL-safe base64 according to [RFC 4648 §5](https://datatracker.ietf.org/doc/html/rfc4648#section-5) aka base64url
        -- Padding is never inserted when encoding, and optional when decoding
      | NonStandard
        -- ^ Any non-standard, non RFC 4648-compliant base64 encoding.
        -- Can only be decoded using lenient decoders.

    -- | Wraps a value, asserting that it is or is intended to be
    -- in a particular kind of Base64 encoding use 'extractBase64'
    -- to extract the value, and 'assertBase64' to tag a value
    -- as base64-encoded
    --
    newtype Base64 (k :: Alphabet) a = Base64 a

    instance forall k. Functor (Base64 k) where
      fmap :: forall a b. (a -> b) -> Base64 k a -> Base64 k b
    fmap a -> b
    f (Base64 a
    a) = b -> Base64 k b
    forall (k :: Alphabet) a. a -> Base64 k a
    Base64 (a -> b
    f a
    a)

    instance forall k a. (Eq a) => Eq (Base64 k a) where
      Base64 a
    a == :: Base64 k a -> Base64 k a -> Bool
    == Base64 a
    b = a
    a a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    b

    instance forall k. Applicative (Base64 k) where
      pure :: forall a. a -> Base64 k a
    pure = a -> Base64 k a
    forall (k :: Alphabet) a. a -> Base64 k a
    Base64
      Base64 a -> b
    f <*> :: forall a b. Base64 k (a -> b) -> Base64 k a -> Base64 k b
    <*> Base64 a
    a = b -> Base64 k b
    forall (k :: Alphabet) a. a -> Base64 k a
    Base64 (a -> b
    f a
    a)

    instance forall k. Monad (Base64 k) where
      return :: forall a. a -> Base64 k a
    return = a -> Base64 k a
    forall a. a -> Base64 k a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      Base64 a
    a >>= :: forall a b. Base64 k a -> (a -> Base64 k b) -> Base64 k b
    >>= a -> Base64 k b
    k = a -> Base64 k b
    k a
    a

    instance forall k a. (Show a) => Show (Base64 k a) where
      show :: Base64 k a -> String
    show (Base64 a
    a) = a -> String
    forall a. Show a => a -> String
    show a
    a

    instance forall k a. NFData a => NFData (Base64 k a) where
      rnf :: Base64 k a -> ()
    rnf (Base64 a
    a) = a -> ()
    forall a. NFData a => a -> ()
    rnf a
    a