    -- | Base 64 encoding of objects.
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE CPP                        #-}
    module Raaz.Core.Encode.Base64( Base64 ) where

    import Data.Char
    import Data.Bits
    import Data.String

    import Data.ByteString as B
    import Data.ByteString.Char8 as C8
    import Data.ByteString.Internal (c2w, w2c)

    import Data.ByteString.Unsafe(unsafeIndex)
    import Data.Monoid
    import Data.Word
    import Raaz.Core.Encode.Internal

    -- | The type corresponding to the standard padded base-64 binary
    -- encoding.
    newtype Base64 = Base64 {Base64 -> ByteString
    unBase64 :: ByteString}
    #if MIN_VERSION_base(4,11,0)
                     deriving (Base64 -> Base64 -> Bool
    (Base64 -> Base64 -> Bool)
    -> (Base64 -> Base64 -> Bool) -> Eq Base64
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Base64 -> Base64 -> Bool
    $c/= :: Base64 -> Base64 -> Bool
    == :: Base64 -> Base64 -> Bool
    $c== :: Base64 -> Base64 -> Bool
    Eq, b -> Base64 -> Base64
    NonEmpty Base64 -> Base64
    Base64 -> Base64 -> Base64
    (Base64 -> Base64 -> Base64)
    -> (NonEmpty Base64 -> Base64)
    -> (forall b. Integral b => b -> Base64 -> Base64)
    -> Semigroup Base64
    forall b. Integral b => b -> Base64 -> Base64
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    stimes :: b -> Base64 -> Base64
    $cstimes :: forall b. Integral b => b -> Base64 -> Base64
    sconcat :: NonEmpty Base64 -> Base64
    $csconcat :: NonEmpty Base64 -> Base64
    <> :: Base64 -> Base64 -> Base64
    $c<> :: Base64 -> Base64 -> Base64
    Semigroup, Semigroup Base64
    Base64
    Semigroup Base64 =>
    Base64
    -> (Base64 -> Base64 -> Base64)
    -> ([Base64] -> Base64)
    -> Monoid Base64
    [Base64] -> Base64
    Base64 -> Base64 -> Base64
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    mconcat :: [Base64] -> Base64
    $cmconcat :: [Base64] -> Base64
    mappend :: Base64 -> Base64 -> Base64
    $cmappend :: Base64 -> Base64 -> Base64
    mempty :: Base64
    $cmempty :: Base64
    $cp1Monoid :: Semigroup Base64
    Monoid)
    #else
                     deriving (Eq, Monoid)
    #endif

    -- Developers note: Internally base16 just stores the bytestring as
    -- is. The conversion happens when we do an encode and decode of
    -- actual base16.

    instance Encodable Base64 where
      toByteString :: Base64 -> ByteString
    toByteString          = ByteString -> ByteString
    toB64 (ByteString -> ByteString)
    -> (Base64 -> ByteString) -> Base64 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Base64 -> ByteString
    unBase64

      fromByteString :: ByteString -> Maybe Base64
    fromByteString bs :: ByteString
    bs
        | ByteString -> Bool
    B.null ByteString
    bs                = Base64 -> Maybe Base64
    forall a. a -> Maybe a
    Just (Base64 -> Maybe Base64) -> Base64 -> Maybe Base64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Base64
    Base64 ByteString
    B.empty
        | ByteString -> Int
    B.length ByteString
    bs Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `rem` 4 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= 0 = Maybe Base64
    forall a. Maybe a
    Nothing
        | Bool
    okeyPad                  = Base64 -> Maybe Base64
    forall a. a -> Maybe a
    Just (Base64 -> Maybe Base64) -> Base64 -> Maybe Base64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Base64
    Base64 (ByteString -> Base64) -> ByteString -> Base64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString
    unsafeFromB64 ByteString
    bs
        | Bool
    otherwise                = Maybe Base64
    forall a. Maybe a
    Nothing
        where padPart :: ByteString
    padPart     = (Char -> Bool) -> ByteString -> ByteString
    C8.dropWhile Char -> Bool
    isB64Char ByteString
    bs
              okeyPad :: Bool
    okeyPad     = ByteString
    padPart ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    C8.empty Bool -> Bool -> Bool
    || ByteString
    padPart ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char -> ByteString
    C8.singleton '=' Bool -> Bool -> Bool
    || ByteString
    padPart ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == String -> ByteString
    C8.pack "=="
              isB64Char :: Char -> Bool
    isB64Char c :: Char
    c = Char -> Bool
    isAlpha Char
    c Bool -> Bool -> Bool
    || Char -> Bool
    isDigit Char
    c Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '+' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '/'

      unsafeFromByteString :: ByteString -> Base64
    unsafeFromByteString bs :: ByteString
    bs | ByteString -> Bool
    B.null ByteString
    bs = ByteString -> Base64
    Base64 ByteString
    B.empty
                              | Bool
    otherwise = ByteString -> Base64
    Base64 (ByteString -> Base64) -> ByteString -> Base64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString
    unsafeFromB64 ByteString
    bs

    instance Show Base64 where
      show :: Base64 -> String
    show = ByteString -> String
    C8.unpack (ByteString -> String)
    -> (Base64 -> ByteString) -> Base64 -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Base64 -> ByteString
    forall a. Encodable a => a -> ByteString
    toByteString

    -- | Ignores spaces and newlines.
    instance IsString Base64 where
      fromString :: String -> Base64
    fromString = ByteString -> Base64
    forall a. Encodable a => ByteString -> a
    unsafeFromByteString (ByteString -> Base64)
    -> (String -> ByteString) -> String -> Base64
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> ByteString -> ByteString
    C8.filter (Bool -> Bool
    not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Bool
    isSpace) (ByteString -> ByteString)
    -> (String -> ByteString) -> String -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ByteString
    forall a. IsString a => String -> a
    fromString

    instance Format Base64 where
      encodeByteString :: ByteString -> Base64
    encodeByteString = ByteString -> Base64
    Base64
      {-# INLINE encodeByteString #-}

      decodeFormat :: Base64 -> ByteString
    decodeFormat     = Base64 -> ByteString
    unBase64
      {-# INLINE decodeFormat #-}

    ------------- Base 64 encoding -------------------------

    -- NOTE: The topN functions ensure that the top N bits of a word are present
    -- in the least N significant bits. The botN ensures that there

    top6 :: Word8 -> Word8; bot2 :: Word8 -> Word8
    top4 :: Word8 -> Word8; bot4 :: Word8 -> Word8
    top2 :: Word8 -> Word8; bot6 :: Word8 -> Word8

    top6 :: Word8 -> Word8
    top6 w :: Word8
    w = Word8
    w Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftR` 2; bot2 :: Word8 -> Word8
    bot2 w :: Word8
    w = Word8
    w Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .&. 0x03
    top4 :: Word8 -> Word8
    top4 w :: Word8
    w = Word8
    w Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftR` 4; bot4 :: Word8 -> Word8
    bot4 w :: Word8
    w = Word8
    w Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .&. 0x0F
    top2 :: Word8 -> Word8
    top2 w :: Word8
    w = Word8
    w Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftR` 6; bot6 :: Word8 -> Word8
    bot6 w :: Word8
    w = Word8
    w Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .&. 0x3F

    --------------- Combining bytes -----------------------------------

    byte0 :: Word8 -> Word8
    byte1 :: Word8 -> Word8 -> Word8
    byte2 :: Word8 -> Word8 -> Word8
    byte3 :: Word8 -> Word8
    pad   :: Word8

    byte0 :: Word8 -> Word8
    byte0     = Word8 -> Word8
    b64 (Word8 -> Word8) -> (Word8 -> Word8) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Word8
    top6
    byte1 :: Word8 -> Word8 -> Word8
    byte1 t :: Word8
    t p :: Word8
    p = Word8 -> Word8
    b64 (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    shiftL (Word8 -> Word8
    bot2 Word8
    p) 4 Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Word8
    top4 Word8
    t
    byte2 :: Word8 -> Word8 -> Word8
    byte2 t :: Word8
    t p :: Word8
    p = Word8 -> Word8
    b64 (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    shiftL (Word8 -> Word8
    bot4 Word8
    p) 2 Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Word8
    top2 Word8
    t
    byte3 :: Word8 -> Word8
    byte3     = Word8 -> Word8
    b64 (Word8 -> Word8) -> (Word8 -> Word8) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Word8
    bot6
    pad :: Word8
    pad       = Char -> Word8
    c2w '='

    -- | Encoding word.
    b64 :: Word8 -> Word8
    b64 :: Word8 -> Word8
    b64 w :: Word8
    w | 0  Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w  Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 25 = Char -> Word8
    c2w 'A' Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    w
          | 26 Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w  Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 51 = Char -> Word8
    c2w 'a' Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - 26
          | 52 Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w  Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 61 = Char -> Word8
    c2w '0' Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - 52
          | Word8
    w Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == 62             = Char -> Word8
    c2w '+'
          | Word8
    w Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == 63             = Char -> Word8
    c2w '/'
          | Bool
    otherwise           = String -> Word8
    forall a. HasCallStack => String -> a
    error "oops: b64"

    unB64 :: Word8 -> Word8
    unB64 :: Word8 -> Word8
    unB64 w :: Word8
    w | Char -> Word8
    c2w 'A' Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Char -> Word8
    c2w 'Z' = Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Char -> Word8
    c2w 'A'
            | Char -> Word8
    c2w 'a' Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Char -> Word8
    c2w 'z' = Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Char -> Word8
    c2w 'a' Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + 26
            | Char -> Word8
    c2w '0' Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word8
    w Bool -> Bool -> Bool
    && Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Char -> Word8
    c2w '9' = Word8
    w Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Char -> Word8
    c2w '0' Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + 52
            | Word8
    w Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char -> Word8
    c2w '+'                 = 62
            | Word8
    w Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char -> Word8
    c2w '/'                 = 63
            | Bool
    otherwise                    = String -> Word8
    forall a. HasCallStack => String -> a
    error (String -> Word8) -> String -> Word8
    forall a b. (a -> b) -> a -> b
    $ "oops unB64:" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ [Word8 -> Char
    w2c Word8
    w]

    -- Since the encoding to base16 is usually used for user interaction
    -- we can afford to be slower here.

    -- TODO (Liquid Haskell)
    --
    {--@ toB64 :: ByteString -> { bs : ByteString | (bslen bs) mod 4 == 0 @-}
    --
    toB64 :: ByteString -> ByteString
    toB64 :: ByteString -> ByteString
    toB64 bs :: ByteString
    bs = (ByteString, Maybe Int) -> ByteString
    forall a b. (a, b) -> a
    fst (Int
    -> (Int -> Maybe (Word8, Int)) -> Int -> (ByteString, Maybe Int)
    forall a.
    Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
    B.unfoldrN (4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    n) Int -> Maybe (Word8, Int)
    gen 0) ByteString -> ByteString -> ByteString
    forall a. Semigroup a => a -> a -> a
    <> ByteString
    padding
        where gen :: Int -> Maybe (Word8, Int)
    gen i :: Int
    i    = (Word8, Int) -> Maybe (Word8, Int)
    forall a. a -> Maybe a
    Just (Int -> Word8
    byte Int
    i, Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 1)
              at :: Int -> Int -> Word8
    at blk :: Int
    blk i :: Int
    i = ByteString -> Int -> Word8
    unsafeIndex ByteString
    bs (Int -> Word8) -> Int -> Word8
    forall a b. (a -> b) -> a -> b
    $ 3 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    blk Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    i

              byte :: Int -> Word8
    byte i :: Int
    i = case Int
    r of
                0 -> Word8 -> Word8
    byte0          (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 0
                1 -> Word8 -> Word8 -> Word8
    byte1 (Int -> Int -> Word8
    at Int
    q 1) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 0
                2 -> Word8 -> Word8 -> Word8
    byte2 (Int -> Int -> Word8
    at Int
    q 2) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 1
                3 -> Word8 -> Word8
    byte3          (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 2
                _ -> String -> Word8
    forall a. HasCallStack => String -> a
    error "base64 bad index"
                where (q :: Int
    q, r :: Int
    r) = Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    quotRem Int
    i 4

              (n :: Int
    n,p :: Int
    p) = ByteString -> Int
    B.length ByteString
    bs Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` 3

              padding :: ByteString
    padding = case Int
    p of
                0 -> ByteString
    forall a. Monoid a => a
    mempty
                1 -> [Word8] -> ByteString
    B.pack [ Word8 -> Word8
    byte0   (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 0
                            , Word8 -> Word8 -> Word8
    byte1 0 (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 0
                            , Word8
    pad, Word8
    pad
                            ]
                2 -> [Word8] -> ByteString
    B.pack [ Word8 -> Word8
    byte0          (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 0
                            , Word8 -> Word8 -> Word8
    byte1 (Int -> Int -> Word8
    at Int
    n 1) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 0
                            , Word8 -> Word8 -> Word8
    byte2 0        (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 1
                            , Word8
    pad
                            ]
                _ -> String -> ByteString
    forall a. HasCallStack => String -> a
    error "base64 pad bad index"

    -- Notes: Merge is used to convert from base64 digits, which are
    -- words of 6-bits.
    merg0 :: Word8 -> Word8 -> Word8
    merg1 :: Word8 -> Word8 -> Word8
    merg2 :: Word8 -> Word8 -> Word8
    merg0 :: Word8 -> Word8 -> Word8
    merg0 a :: Word8
    a b :: Word8
    b = (Word8 -> Word8
    unB64 Word8
    a Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftL` 2) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Word8
    top4 (Word8 -> Word8
    unB64 Word8
    b)
    merg1 :: Word8 -> Word8 -> Word8
    merg1 a :: Word8
    a b :: Word8
    b = (Word8 -> Word8
    unB64 Word8
    a Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftL` 4) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Word8
    top6 (Word8 -> Word8
    unB64 Word8
    b)
    merg2 :: Word8 -> Word8 -> Word8
    merg2 a :: Word8
    a b :: Word8
    b = (Word8 -> Word8
    unB64 Word8
    a Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftL` 6) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Word8
    unB64 Word8
    b

    unsafeFromB64 :: ByteString -> ByteString
    unsafeFromB64 :: ByteString -> ByteString
    unsafeFromB64 bs :: ByteString
    bs = (ByteString, Maybe Int) -> ByteString
    forall a b. (a, b) -> a
    fst (Int
    -> (Int -> Maybe (Word8, Int)) -> Int -> (ByteString, Maybe Int)
    forall a.
    Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
    B.unfoldrN (3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    n) Int -> Maybe (Word8, Int)
    gen 0) ByteString -> ByteString -> ByteString
    forall a. Semigroup a => a -> a -> a
    <> ByteString
    unPad
      where n :: Int
    n         = ByteString -> Int
    B.length ByteString
    bs Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `quot` 4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1
            gen :: Int -> Maybe (Word8, Int)
    gen i :: Int
    i     = (Word8, Int) -> Maybe (Word8, Int)
    forall a. a -> Maybe a
    Just (Int -> Word8
    byte Int
    i, Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 1)
            at :: Int -> Int -> Word8
    at blk :: Int
    blk i :: Int
    i  = ByteString -> Int -> Word8
    unsafeIndex ByteString
    bs (Int -> Word8) -> Int -> Word8
    forall a b. (a -> b) -> a -> b
    $ 4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    blk Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    i

            byte :: Int -> Word8
    byte i :: Int
    i    = case Int
    r of
              0 -> Word8 -> Word8 -> Word8
    merg0 (Int -> Int -> Word8
    at Int
    q 0) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 1
              1 -> Word8 -> Word8 -> Word8
    merg1 (Int -> Int -> Word8
    at Int
    q 1) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 2
              2 -> Word8 -> Word8 -> Word8
    merg2 (Int -> Int -> Word8
    at Int
    q 2) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    q 3
              _ -> String -> Word8
    forall a. HasCallStack => String -> a
    error "base64 bad index"
              where (q :: Int
    q, r :: Int
    r) = Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    quotRem Int
    i 3

            unPad :: ByteString
    unPad
              | Int -> Int -> Word8
    at Int
    n 2 Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char -> Word8
    c2w '=' = Word8 -> ByteString
    B.singleton (Word8 -> ByteString) -> Word8 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Word8 -> Word8
    merg0 (Int -> Int -> Word8
    at Int
    n 0) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 1
              | Int -> Int -> Word8
    at Int
    n 3 Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char -> Word8
    c2w '=' = [Word8] -> ByteString
    B.pack [ Word8 -> Word8 -> Word8
    merg0 (Int -> Int -> Word8
    at Int
    n 0) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 1
                                           , Word8 -> Word8 -> Word8
    merg1 (Int -> Int -> Word8
    at Int
    n 1) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 2
                                           ]
              | Bool
    otherwise         = [Word8] -> ByteString
    B.pack [ Word8 -> Word8 -> Word8
    merg0 (Int -> Int -> Word8
    at Int
    n 0) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 1
                                           , Word8 -> Word8 -> Word8
    merg1 (Int -> Int -> Word8
    at Int
    n 1) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 2
                                           , Word8 -> Word8 -> Word8
    merg2 (Int -> Int -> Word8
    at Int
    n 2) (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Word8
    at Int
    n 3
                                           ]