{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.ByteString.Base32.Internal.Head
( encodeBase32_
, encodeBase32NoPad_
, decodeBase32_
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
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
encodeBase32_ :: Addr# -> ByteString -> ByteString
encodeBase32_ !lut (PS !sfp !soff !slen) =
unsafeCreate dlen $ \dptr ->
withForeignPtr sfp $ \sptr -> do
let !end = plusPtr sptr (soff + slen)
innerLoop
lut
(castPtr dptr)
(plusPtr sptr soff)
end
(loopTail lut end)
where
!dlen = 8 * ((slen + 4) `div` 5)
encodeBase32NoPad_ :: Addr# -> ByteString -> ByteString
encodeBase32NoPad_ !lut (PS !sfp !soff !slen)
= unsafeDupablePerformIO $ do
!dfp <- mallocPlainForeignPtrBytes dlen
withForeignPtr dfp $ \dptr ->
withForeignPtr sfp $ \sptr -> do
let !end = plusPtr sptr (soff + slen)
innerLoopNoPad
lut
(castPtr dptr)
(plusPtr sptr soff)
end
(loopTailNoPad lut dfp end)
where
!dlen = 8 * ((slen + 4) `div` 5)
decodeBase32_ :: Bool -> ForeignPtr Word8 -> ByteString -> Either Text ByteString
decodeBase32_ !pad !alphabet bs@(PS _ _ !l)
| l == 0 = Right ""
| r /= 0, pad =
if
| r == 2 -> go (BS.append bs (BS.replicate 6 0x3d))
| r == 4 -> go (BS.append bs (BS.replicate 4 0x3d))
| r == 5 -> go (BS.append bs (BS.replicate 3 0x3d))
| r == 7 -> go (BS.append bs (BS.replicate 1 0x3d))
| otherwise -> Left "invalid bytestring size"
| r /= 0, not pad = Left "invalid padding"
| otherwise = go bs
where
(!q, !r) = l `divMod` 8
!dlen = q * 8
go (PS !sfp !soff !slen) = unsafeDupablePerformIO $ do
!dfp <- mallocPlainForeignPtrBytes dlen
withForeignPtr dfp $ \dptr ->
withForeignPtr alphabet $ \(Ptr lut) ->
withForeignPtr sfp $ \sptr -> do
let !end = plusPtr sptr (soff + slen)
decodeLoop
lut
(castPtr dptr)
(plusPtr sptr soff)
end
(decodeTail lut dfp end)