{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
module Data.ByteString.Base32.Internal.Head
( encodeBase32_
, encodeBase32NoPad_
, decodeBase32_
) where


import Data.ByteString.Internal
import Data.ByteString.Base32.Internal.Loop
import Data.ByteString.Base32.Internal.Tail
import Data.Text (Text)

import Foreign.Ptr
import Foreign.ForeignPtr

import GHC.Exts
import GHC.ForeignPtr
import GHC.Word

import System.IO.Unsafe


-- | Head of the padded base32 encoding loop.
--
-- This function takes an alphabet in the form of an unboxed 'Addr#',
-- allocates the correct number of bytes that will be written, and
-- executes the inner encoding loop against that data.
--
encodeBase32_ :: Addr# -> ByteString -> ByteString
encodeBase32_ :: Addr# -> ByteString -> ByteString
encodeBase32_ !Addr#
lut (PS !ForeignPtr Word8
sfp !Int
o !Int
l) = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr Word8
dfp <- forall a. Int -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Int
dlen
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
dfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
dptr ->
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
sfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
sptr -> do
        let !end :: Ptr b
end = forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr (Int
l forall a. Num a => a -> a -> a
+ Int
o)
        Addr#
-> Ptr Word64
-> Ptr Word8
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
-> IO ByteString
innerLoop Addr#
lut
          (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
dptr) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr Int
o)
          forall {b}. Ptr b
end (Addr#
-> ForeignPtr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> IO ByteString
loopTail Addr#
lut ForeignPtr Word8
dfp Ptr Word8
dptr forall {b}. Ptr b
end)
  where
    !dlen :: Int
dlen = forall a b. (RealFrac a, Integral b) => a -> b
ceiling (forall a b. (Integral a, Num b) => a -> b
fromIntegral @_ @Double Int
l forall a. Fractional a => a -> a -> a
/ Double
5) forall a. Num a => a -> a -> a
* Int
8

-- | Head of the unpadded base32 encoding loop.
--
-- This function takes an alphabet in the form of an unboxed 'Addr#',
-- allocates the correct number of bytes that will be written, and
-- executes the inner encoding loop against that data.
--
encodeBase32NoPad_ :: Addr# -> ByteString -> ByteString
encodeBase32NoPad_ :: Addr# -> ByteString -> ByteString
encodeBase32NoPad_ !Addr#
lut (PS !ForeignPtr Word8
sfp !Int
o !Int
l) = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$ do
    !ForeignPtr Word8
dfp <- forall a. Int -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Int
dlen
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
dfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
dptr ->
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
sfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
sptr -> do
        let !end :: Ptr b
end = forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr (Int
l forall a. Num a => a -> a -> a
+ Int
o)
        Addr#
-> Ptr Word64
-> Ptr Word8
-> Ptr Word8
-> (Ptr Word8 -> Ptr Word8 -> IO ByteString)
-> IO ByteString
innerLoop Addr#
lut
          (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
dptr) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr Int
o)
          forall {b}. Ptr b
end (Addr#
-> ForeignPtr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> IO ByteString
loopTailNoPad Addr#
lut ForeignPtr Word8
dfp Ptr Word8
dptr forall {b}. Ptr b
end)
  where
    !dlen :: Int
dlen = forall a b. (RealFrac a, Integral b) => a -> b
ceiling (forall a b. (Integral a, Num b) => a -> b
fromIntegral @_ @Double Int
l forall a. Fractional a => a -> a -> a
/ Double
5) forall a. Num a => a -> a -> a
* Int
8

-- | Head of the base32 decoding loop.
--
-- This function takes a base32-decoding lookup table and base32-encoded
-- bytestring, allocates the correct number of bytes that will be written,
-- and executes the inner decoding loop against that data.
--
decodeBase32_ :: Ptr Word8 -> ByteString -> IO (Either Text ByteString)
decodeBase32_ :: Ptr Word8 -> ByteString -> IO (Either Text ByteString)
decodeBase32_ (Ptr !Addr#
dtable) (PS !ForeignPtr Word8
sfp !Int
soff !Int
slen) =
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
sfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
sptr -> do
      ForeignPtr Word8
dfp <- forall a. Int -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Int
dlen
      forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
dfp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
dptr -> do
        let !end :: Ptr b
end = forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr (Int
soff forall a. Num a => a -> a -> a
+ Int
slen)
        Addr#
-> ForeignPtr Word8
-> Ptr Word8
-> Ptr Word64
-> Ptr Word8
-> IO (Either Text ByteString)
decodeLoop Addr#
dtable ForeignPtr Word8
dfp Ptr Word8
dptr (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
sptr Int
soff) forall {b}. Ptr b
end
  where
    !dlen :: Int
dlen = forall a b. (RealFrac a, Integral b) => a -> b
ceiling (forall a b. (Integral a, Num b) => a -> b
fromIntegral @_ @Double Int
slen forall a. Fractional a => a -> a -> a
/ Double
1.6)