    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE CPP #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE TypeApplications #-}
    -- |
    -- Module       : Data.ByteString.Base64.Internal.Head
    -- Copyright    : (c) 2019-2020 Emily Pillmore
    -- License      : BSD-style
    --
    -- Maintainer   : Emily Pillmore <emilypi@cohomolo.gy>
    -- Stability    : Experimental
    -- Portability  : portable
    --
    -- Shared internal utils
    --
    module Data.ByteString.Base64.Internal.Head
    ( encodeBase64_
    , encodeBase64Nopad_
    , decodeBase64_
    , decodeBase64Lenient_
    ) where

    #include "MachDeps.h"

    import Data.ByteString.Base64.Internal.Tail
    import Data.ByteString.Base64.Internal.Utils
    #if WORD_SIZE_IN_BITS == 32
    import Data.ByteString.Base64.Internal.W32.Loop
    #elif WORD_SIZE_IN_BITS >= 64
    import Data.ByteString.Base64.Internal.W64.Loop
    #else
    import Data.ByteString.Base64.Internal.W16.Loop
    #endif
    import Data.ByteString.Internal
    import Data.Text (Text)

    import Foreign.ForeignPtr
    import Foreign.Ptr

    import GHC.ForeignPtr
    import GHC.Word

    import System.IO.Unsafe

    encodeBase64_ :: EncodingTable -> ByteString -> ByteString
    encodeBase64_ :: EncodingTable -> ByteString -> ByteString
    encodeBase64_ (EncodingTable !Ptr Word8
    aptr !ForeignPtr Word16
    efp) (PS !ForeignPtr Word8
    sfp !Int
    soff !Int
    slen) =
        IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ do
          ForeignPtr Word8
    dfp <- Int -> IO (ForeignPtr Word8)
    forall a. Int -> IO (ForeignPtr a)
    mallocPlainForeignPtrBytes Int
    dlen
          ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dptr ->
            ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    sfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    sptr ->
            ForeignPtr Word16 -> (Ptr Word16 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word16
    efp ((Ptr Word16 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word16 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word16
    eptr -> do
              let !end :: Ptr b
    end = Ptr Word8 -> Int -> Ptr b
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr (Int
    soff Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    slen)
              Ptr Word16
    -> Ptr Word64
    -> Ptr Word64
    -> Ptr Word64
    -> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
    -> IO ByteString
    innerLoop
                Ptr Word16
    eptr
                (Ptr Any -> Ptr Word64
    forall a b. Ptr a -> Ptr b
    castPtr (Ptr Word8 -> Int -> Ptr Any
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr Int
    soff))
                (Ptr Word8 -> Ptr Word64
    forall a b. Ptr a -> Ptr b
    castPtr Ptr Word8
    dptr)
                Ptr Word64
    forall {b}. Ptr b
    end
                (ForeignPtr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> IO ByteString
    loopTail ForeignPtr Word8
    dfp Ptr Word8
    aptr Ptr Word8
    dptr (Ptr Any -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr Any
    forall {b}. Ptr b
    end))
      where
        !dlen :: Int
    dlen = Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * ((Int
    slen Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    3)

    encodeBase64Nopad_ :: EncodingTable -> ByteString -> ByteString
    encodeBase64Nopad_ :: EncodingTable -> ByteString -> ByteString
    encodeBase64Nopad_ (EncodingTable !Ptr Word8
    aptr !ForeignPtr Word16
    efp) (PS !ForeignPtr Word8
    sfp !Int
    soff !Int
    slen) =
        IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ do
          ForeignPtr Word8
    dfp <- Int -> IO (ForeignPtr Word8)
    forall a. Int -> IO (ForeignPtr a)
    mallocPlainForeignPtrBytes Int
    dlen
          ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dptr ->
            ForeignPtr Word16 -> (Ptr Word16 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word16
    efp ((Ptr Word16 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word16 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word16
    etable ->
            ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    sfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    sptr -> do
              let !end :: Ptr b
    end = Ptr Word8 -> Int -> Ptr b
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr (Int
    soff Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    slen)
              Ptr Word16
    -> Ptr Word64
    -> Ptr Word64
    -> Ptr Word64
    -> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
    -> IO ByteString
    innerLoop
                Ptr Word16
    etable
                (Ptr Any -> Ptr Word64
    forall a b. Ptr a -> Ptr b
    castPtr (Ptr Word8 -> Int -> Ptr Any
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr Int
    soff))
                (Ptr Word8 -> Ptr Word64
    forall a b. Ptr a -> Ptr b
    castPtr Ptr Word8
    dptr)
                Ptr Word64
    forall {b}. Ptr b
    end
                (ForeignPtr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> IO ByteString
    loopTailNoPad ForeignPtr Word8
    dfp Ptr Word8
    aptr Ptr Word8
    dptr (Ptr Any -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr Any
    forall {b}. Ptr b
    end))
      where
        !dlen :: Int
    dlen = Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * ((Int
    slen Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    3)

    -- | The main decode function. Takes a padding flag, a decoding table, and
    -- the input value, producing either an error string on the left, or a
    -- decoded value.
    --
    -- Note: If 'Padding' ~ 'Don\'tCare', then we pad out the input to a multiple of 4.
    -- If 'Padding' ~ 'Padded', then we do not, and fail if the input is not
    -- a multiple of 4 in length. If 'Padding' ~ 'Unpadded', then we validate
    -- correctness of length and the absence of padding and then treat as a std
    -- padded string.
    --
    decodeBase64_
        :: ForeignPtr Word8
        -> ByteString
        -> IO (Either Text ByteString)
    decodeBase64_ :: ForeignPtr Word8 -> ByteString -> IO (Either Text ByteString)
    decodeBase64_ !ForeignPtr Word8
    dtfp (PS !ForeignPtr Word8
    sfp !Int
    soff !Int
    slen) =
        ForeignPtr Word8
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dtfp ((Ptr Word8 -> IO (Either Text ByteString))
     -> IO (Either Text ByteString))
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dtable ->
        ForeignPtr Word8
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    sfp ((Ptr Word8 -> IO (Either Text ByteString))
     -> IO (Either Text ByteString))
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    sptr -> do
          ForeignPtr Word8
    dfp <- Int -> IO (ForeignPtr Word8)
    forall a. Int -> IO (ForeignPtr a)
    mallocPlainForeignPtrBytes Int
    dlen
          ForeignPtr Word8
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dfp ((Ptr Word8 -> IO (Either Text ByteString))
     -> IO (Either Text ByteString))
    -> (Ptr Word8 -> IO (Either Text ByteString))
    -> IO (Either Text ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dptr -> do
            let !end :: Ptr b
    end = Ptr Word8 -> Int -> Ptr b
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr (Int
    soff Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    slen)
            Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> ForeignPtr Word8
    -> IO (Either Text ByteString)
    decodeLoop Ptr Word8
    dtable
              (Ptr Word8 -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr Int
    soff)
              Ptr Word8
    dptr Ptr Word8
    forall {b}. Ptr b
    end ForeignPtr Word8
    dfp
      where
        !dlen :: Int
    dlen = (Int
    slen Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `quot` Int
    4) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    3
    {-# inline decodeBase64_ #-}

    decodeBase64Lenient_ :: ForeignPtr Word8 -> ByteString -> ByteString
    decodeBase64Lenient_ :: ForeignPtr Word8 -> ByteString -> ByteString
    decodeBase64Lenient_ !ForeignPtr Word8
    dtfp (PS !ForeignPtr Word8
    sfp !Int
    soff !Int
    slen) = IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $
        ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dtfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dtable ->
        ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    sfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    sptr -> do
          ForeignPtr Word8
    dfp <- Int -> IO (ForeignPtr Word8)
    forall a. Int -> IO (ForeignPtr a)
    mallocPlainForeignPtrBytes Int
    dlen
          ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    dfp ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    dptr ->
            Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> ForeignPtr Word8
    -> IO ByteString
    lenientLoop
              Ptr Word8
    dtable
              (Ptr Word8 -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr Int
    soff)
              Ptr Word8
    dptr
              (Ptr Word8 -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    plusPtr Ptr Word8
    sptr (Int
    soff Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    slen))
              ForeignPtr Word8
    dfp
      where
        !dlen :: Int
    dlen = ((Int
    slen Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    4) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    3