Arm.hs (2277B)
1 {-# OPTIONS_HADDOCK hide #-} 2 {-# LANGUAGE BangPatterns #-} 3 4 -- | 5 -- Module: Data.ByteString.Base16.Arm 6 -- Copyright: (c) 2025 Jared Tobin 7 -- License: MIT 8 -- Maintainer: Jared Tobin <jared@ppad.tech> 9 -- 10 -- ARM NEON support for base16 encoding and decoding. 11 12 module Data.ByteString.Base16.Arm ( 13 base16_arm_available 14 , encode 15 , decode 16 ) where 17 18 import qualified Data.Bits as B 19 import qualified Data.ByteString as BS 20 import qualified Data.ByteString.Internal as BI 21 import Data.Word (Word8) 22 import Foreign.C.Types (CInt(..), CSize(..)) 23 import Foreign.ForeignPtr (withForeignPtr) 24 import Foreign.Ptr (Ptr, plusPtr) 25 import System.IO.Unsafe (unsafeDupablePerformIO) 26 27 -- ffi ------------------------------------------------------------------------ 28 29 foreign import ccall unsafe "base16_encode_arm" 30 c_base16_encode :: Ptr Word8 -> Ptr Word8 -> CSize -> IO () 31 32 foreign import ccall unsafe "base16_decode_arm" 33 c_base16_decode :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt 34 35 foreign import ccall unsafe "base16_arm_available" 36 c_base16_arm_available :: IO CInt 37 38 -- utilities ------------------------------------------------------------------ 39 40 fi :: (Integral a, Num b) => a -> b 41 fi = fromIntegral 42 {-# INLINE fi #-} 43 44 -- api ------------------------------------------------------------------------ 45 46 -- | Are ARM NEON extensions available? 47 base16_arm_available :: Bool 48 base16_arm_available = 49 unsafeDupablePerformIO c_base16_arm_available /= 0 50 {-# NOINLINE base16_arm_available #-} 51 52 -- | Encode a base256 'ByteString' as base16 using NEON. 53 encode :: BS.ByteString -> BS.ByteString 54 encode (BI.PS sfp soff l) = 55 BI.unsafeCreate (l `B.shiftL` 1) $ \dst -> 56 withForeignPtr sfp $ \sp0 -> 57 c_base16_encode (sp0 `plusPtr` soff) dst (fi l) 58 59 -- | Decode a base16 'ByteString' to base256 using NEON. Returns 60 -- 'Nothing' on odd-length or otherwise invalid input. 61 decode :: BS.ByteString -> Maybe BS.ByteString 62 decode (BI.PS sfp soff l) 63 | B.testBit l 0 = Nothing 64 | otherwise = unsafeDupablePerformIO $ do 65 let !n = l `B.shiftR` 1 66 fp <- BI.mallocByteString n 67 ok <- withForeignPtr fp $ \dst -> 68 withForeignPtr sfp $ \sp0 -> 69 c_base16_decode (sp0 `plusPtr` soff) dst (fi n) 70 pure $! if ok /= 0 then Just (BI.PS fp 0 n) else Nothing