{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
module Data.Digest.CRC32C
( CRC32C
, crc32c
, crc32cUpdate
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Short as BSS
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Word
import Foreign.C.Types
import Foreign.Ptr
import GHC.Exts (ByteArray#)
import System.IO.Unsafe (unsafeDupablePerformIO)
#if !MIN_VERSION_bytestring(0, 11, 1)
import qualified Data.ByteString.Short.Internal as BSS
#endif
class CRC32C a where
crc32c :: a -> Word32
crc32c = forall a. CRC32C a => Word32 -> a -> Word32
crc32cUpdate Word32
0
crc32cUpdate :: Word32 -> a -> Word32
instance CRC32C BS.ByteString where
crc32c :: ByteString -> Word32
crc32c ByteString
bs = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
bs forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
ptr, Int
len) ->
Ptr Word8 -> CSize -> IO Word32
crc32c_value (forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
ptr) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
crc32cUpdate :: Word32 -> ByteString -> Word32
crc32cUpdate Word32
cks ByteString
bs = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
bs forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
ptr, Int
len) ->
Word32 -> Ptr Word8 -> CSize -> IO Word32
crc32c_extend Word32
cks (forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
ptr) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
instance CRC32C BL.ByteString where
crc32cUpdate :: Word32 -> ByteString -> Word32
crc32cUpdate = forall a. (a -> ByteString -> a) -> a -> ByteString -> a
BL.foldlChunks forall a. CRC32C a => Word32 -> a -> Word32
crc32cUpdate
instance CRC32C [Word8] where
crc32cUpdate :: Word32 -> [Word8] -> Word32
crc32cUpdate Word32
n = (forall a. CRC32C a => Word32 -> a -> Word32
crc32cUpdate Word32
n) forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BL.pack
instance CRC32C BSS.ShortByteString where
crc32c :: ShortByteString -> Word32
crc32c sbs :: ShortByteString
sbs@(BSS.SBS ByteArray#
ba#) = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$
ByteArray# -> CSize -> IO Word32
crc32c_value' ByteArray#
ba# (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ ShortByteString -> Int
BSS.length ShortByteString
sbs)
crc32cUpdate :: Word32 -> ShortByteString -> Word32
crc32cUpdate Word32
cks sbs :: ShortByteString
sbs@(BSS.SBS ByteArray#
ba#) = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$
Word32 -> ByteArray# -> CSize -> IO Word32
crc32c_extend' Word32
cks ByteArray#
ba# (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ ShortByteString -> Int
BSS.length ShortByteString
sbs)
foreign import ccall unsafe "crc32c/crc32c.h crc32c_value"
crc32c_value :: Ptr Word8 -> CSize -> IO Word32
foreign import ccall unsafe "crc32c/crc32c.h crc32c_extend"
crc32c_extend :: Word32 -> Ptr Word8 -> CSize -> IO Word32
foreign import ccall unsafe "crc32c/crc32c.h crc32c_value"
crc32c_value' :: ByteArray# -> CSize -> IO Word32
foreign import ccall unsafe "crc32c/crc32c.h crc32c_extend"
crc32c_extend' :: Word32 -> ByteArray# -> CSize -> IO Word32