module Data.Crc32 (
crc32
, Crc32(..)
) where
import Data.Bits
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as BSL
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
import Data.Word
import Text.Printf
table :: Vector Word32
table :: Vector Word32
table = Word32 -> Vector Word32
createCrc32Table Word32
0xedb88320
createCrc32Table :: Word32 -> Vector Word32
createCrc32Table :: Word32 -> Vector Word32
createCrc32Table Word32
poly = Int -> (Int -> Word32) -> Vector Word32
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
256 ((Int -> Word32) -> Vector Word32)
-> (Int -> Word32) -> Vector Word32
forall a b. (a -> b) -> a -> b
$ \Int
n -> (Word32 -> Integer -> Word32) -> Word32 -> Vector Integer -> Word32
forall a b. (a -> b -> a) -> a -> Vector b -> a
V.foldl'
(\Word32
acc Integer
_ -> if Word32 -> Bool
forall a. Integral a => a -> Bool
odd Word32
acc
then Word32
poly Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
acc Int
1
else Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
acc Int
1
)
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
(Integer -> Int -> Vector Integer
forall a. Num a => a -> Int -> Vector a
V.enumFromN Integer
0 Int
8)
newtype Crc32 = Crc32 Word32
deriving (Crc32 -> Crc32 -> Bool
(Crc32 -> Crc32 -> Bool) -> (Crc32 -> Crc32 -> Bool) -> Eq Crc32
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Crc32 -> Crc32 -> Bool
== :: Crc32 -> Crc32 -> Bool
$c/= :: Crc32 -> Crc32 -> Bool
/= :: Crc32 -> Crc32 -> Bool
Eq, Eq Crc32
Eq Crc32
-> (Crc32 -> Crc32 -> Ordering)
-> (Crc32 -> Crc32 -> Bool)
-> (Crc32 -> Crc32 -> Bool)
-> (Crc32 -> Crc32 -> Bool)
-> (Crc32 -> Crc32 -> Bool)
-> (Crc32 -> Crc32 -> Crc32)
-> (Crc32 -> Crc32 -> Crc32)
-> Ord Crc32
Crc32 -> Crc32 -> Bool
Crc32 -> Crc32 -> Ordering
Crc32 -> Crc32 -> Crc32
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Crc32 -> Crc32 -> Ordering
compare :: Crc32 -> Crc32 -> Ordering
$c< :: Crc32 -> Crc32 -> Bool
< :: Crc32 -> Crc32 -> Bool
$c<= :: Crc32 -> Crc32 -> Bool
<= :: Crc32 -> Crc32 -> Bool
$c> :: Crc32 -> Crc32 -> Bool
> :: Crc32 -> Crc32 -> Bool
$c>= :: Crc32 -> Crc32 -> Bool
>= :: Crc32 -> Crc32 -> Bool
$cmax :: Crc32 -> Crc32 -> Crc32
max :: Crc32 -> Crc32 -> Crc32
$cmin :: Crc32 -> Crc32 -> Crc32
min :: Crc32 -> Crc32 -> Crc32
Ord)
instance Show Crc32 where show :: Crc32 -> String
show (Crc32 Word32
crc) = String -> Word32 -> String
forall r. PrintfType r => String -> r
printf String
"%#08x" Word32
crc
crc32 :: ByteString -> Crc32
crc32 :: ByteString -> Crc32
crc32 ByteString
bs =
let Crc32 Word32
crcResult = (Crc32 -> Word8 -> Crc32) -> Crc32 -> ByteString -> Crc32
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
BSL.foldl' (\(Crc32 Word32
crc) Word8
byte -> Word32 -> Crc32
Crc32 (Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
xor (Word32
crc Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
8) (Vector Word32
table Vector Word32 -> Int -> Word32
forall a. Vector a -> Int -> a
! Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
crc Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0xff) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
`xor` Word8
byte)))) (Word32 -> Crc32
Crc32 Word32
0xffffffff) ByteString
bs
in Word32 -> Crc32
Crc32 (Word32 -> Word32
forall a. Bits a => a -> a
complement Word32
crcResult)