{-# LANGUAGE BangPatterns #-}
module Lightning.Protocol.BOLT7.CRC32C (
crc32c
) where
import Data.Bits (shiftR, xor, (.&.))
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Word (Word8, Word32)
crc32cPoly :: Word32
crc32cPoly :: Word32
crc32cPoly = Word32
0x82F63B78
{-# INLINE crc32cPoly #-}
crc32c :: ByteString -> Word32
crc32c :: ByteString -> Word32
crc32c = Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
xor Word32
0xFFFFFFFF (Word32 -> Word32)
-> (ByteString -> Word32) -> ByteString -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32 -> Word8 -> Word32) -> Word32 -> ByteString -> Word32
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
BS.foldl' Word32 -> Word8 -> Word32
updateByte Word32
0xFFFFFFFF
{-# INLINE crc32c #-}
updateByte :: Word32 -> Word8 -> Word32
updateByte :: Word32 -> Word8 -> Word32
updateByte !Word32
crc !Word8
byte =
let crc' :: Word32
crc' = Word32
crc Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
byte
in Int -> Word32 -> Word32
go Int
8 Word32
crc'
where
go :: Int -> Word32 -> Word32
go :: Int -> Word32 -> Word32
go Int
0 !Word32
c = Word32
c
go !Int
n !Word32
c =
let c' :: Word32
c' = if Word32
c Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
1 Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32
0
then (Word32
c Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
1) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
crc32cPoly
else Word32
c Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
1
in Int -> Word32 -> Word32
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Word32
c'
{-# INLINE updateByte #-}