module Rattletrap.Utility.Crc ( getCrc32 ) where import Rattletrap.Data import qualified Data.Bits as Bits import qualified Data.ByteString.Lazy as LazyBytes import qualified Data.IntMap as IntMap import qualified Data.Word as Word -- | Computes the CRC32 of some bytes. This is done to ensure that the bytes -- are valid before trying to parse them. -- -- @ -- getCrc32 ('Data.ByteString.Lazy.pack' [0x00]) -- @ -- -- This CRC uses an initial value of @0xefcbf201@ and a polynomial of -- @0x04c11db7@. getCrc32 :: LazyBytes.ByteString -> Word.Word32 getCrc32 bytes = do let update = crc32Update crc32Table initial = Bits.complement crc32Initial crc = LazyBytes.foldl update initial bytes Bits.complement crc crc32Update :: IntMap.IntMap Word.Word32 -> Word.Word32 -> Word.Word8 -> Word.Word32 crc32Update table crc byte = do let toWord8 :: (Integral a) => a -> Word.Word8 toWord8 = fromIntegral toInt :: (Integral a) => a -> Int toInt = fromIntegral index = toInt (Bits.xor byte (toWord8 (Bits.shiftR crc 24))) left = table IntMap.! index right = Bits.shiftL crc 8 Bits.xor left right crc32Initial :: Word.Word32 crc32Initial = 0xefcbf201 crc32Table :: IntMap.IntMap Word.Word32 crc32Table = IntMap.fromDistinctAscList (zip [0 ..] rawCrc32Table)