module Rattletrap.Utility.Crc where

import qualified Data.Array.Unboxed as Array
import qualified Data.Bits as Bits
import qualified Data.ByteString as ByteString
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.
--
-- @
-- compute ('Data.ByteString.Lazy.pack' [0x00])
-- @
--
-- This CRC uses an initial value of @0xefcbf201@ and a polynomial of
-- @0x04c11db7@.
compute :: ByteString.ByteString -> Word.Word32
compute :: ByteString -> Word32
compute = forall a. Bits a => a -> a
Bits.complement forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Word8 -> a) -> a -> ByteString -> a
ByteString.foldl' Word32 -> Word8 -> Word32
update Word32
initial

update :: Word.Word32 -> Word.Word8 -> Word.Word32
update :: Word32 -> Word8 -> Word32
update Word32
crc Word8
byte =
  let index :: Word8
index = forall a. Bits a => a -> a -> a
Bits.xor Word8
byte forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Word8
unsafeWord32ToWord8 forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
Bits.shiftR Word32
crc Int
24
      left :: Word32
left = Array Word8 Word32
table forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
Array.! Word8
index
      right :: Word32
right = forall a. Bits a => a -> Int -> a
Bits.shiftL Word32
crc Int
8
   in forall a. Bits a => a -> a -> a
Bits.xor Word32
left Word32
right

unsafeWord32ToWord8 :: Word.Word32 -> Word.Word8
unsafeWord32ToWord8 :: Word32 -> Word8
unsafeWord32ToWord8 = forall a b. (Integral a, Num b) => a -> b
fromIntegral

initial :: Word.Word32
initial :: Word32
initial = forall a. Bits a => a -> a
Bits.complement Word32
0xefcbf201

table :: Array.Array Word.Word8 Word.Word32
table :: Array Word8 Word32
table =
  forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [e] -> a i e
Array.listArray
    (Word8
0, Word8
255)
    [ Word32
0x00000000,
      Word32
0x04c11db7,
      Word32
0x09823b6e,
      Word32
0x0d4326d9,
      Word32
0x130476dc,
      Word32
0x17c56b6b,
      Word32
0x1a864db2,
      Word32
0x1e475005,
      Word32
0x2608edb8,
      Word32
0x22c9f00f,
      Word32
0x2f8ad6d6,
      Word32
0x2b4bcb61,
      Word32
0x350c9b64,
      Word32
0x31cd86d3,
      Word32
0x3c8ea00a,
      Word32
0x384fbdbd,
      Word32
0x4c11db70,
      Word32
0x48d0c6c7,
      Word32
0x4593e01e,
      Word32
0x4152fda9,
      Word32
0x5f15adac,
      Word32
0x5bd4b01b,
      Word32
0x569796c2,
      Word32
0x52568b75,
      Word32
0x6a1936c8,
      Word32
0x6ed82b7f,
      Word32
0x639b0da6,
      Word32
0x675a1011,
      Word32
0x791d4014,
      Word32
0x7ddc5da3,
      Word32
0x709f7b7a,
      Word32
0x745e66cd,
      Word32
0x9823b6e0,
      Word32
0x9ce2ab57,
      Word32
0x91a18d8e,
      Word32
0x95609039,
      Word32
0x8b27c03c,
      Word32
0x8fe6dd8b,
      Word32
0x82a5fb52,
      Word32
0x8664e6e5,
      Word32
0xbe2b5b58,
      Word32
0xbaea46ef,
      Word32
0xb7a96036,
      Word32
0xb3687d81,
      Word32
0xad2f2d84,
      Word32
0xa9ee3033,
      Word32
0xa4ad16ea,
      Word32
0xa06c0b5d,
      Word32
0xd4326d90,
      Word32
0xd0f37027,
      Word32
0xddb056fe,
      Word32
0xd9714b49,
      Word32
0xc7361b4c,
      Word32
0xc3f706fb,
      Word32
0xceb42022,
      Word32
0xca753d95,
      Word32
0xf23a8028,
      Word32
0xf6fb9d9f,
      Word32
0xfbb8bb46,
      Word32
0xff79a6f1,
      Word32
0xe13ef6f4,
      Word32
0xe5ffeb43,
      Word32
0xe8bccd9a,
      Word32
0xec7dd02d,
      Word32
0x34867077,
      Word32
0x30476dc0,
      Word32
0x3d044b19,
      Word32
0x39c556ae,
      Word32
0x278206ab,
      Word32
0x23431b1c,
      Word32
0x2e003dc5,
      Word32
0x2ac12072,
      Word32
0x128e9dcf,
      Word32
0x164f8078,
      Word32
0x1b0ca6a1,
      Word32
0x1fcdbb16,
      Word32
0x018aeb13,
      Word32
0x054bf6a4,
      Word32
0x0808d07d,
      Word32
0x0cc9cdca,
      Word32
0x7897ab07,
      Word32
0x7c56b6b0,
      Word32
0x71159069,
      Word32
0x75d48dde,
      Word32
0x6b93dddb,
      Word32
0x6f52c06c,
      Word32
0x6211e6b5,
      Word32
0x66d0fb02,
      Word32
0x5e9f46bf,
      Word32
0x5a5e5b08,
      Word32
0x571d7dd1,
      Word32
0x53dc6066,
      Word32
0x4d9b3063,
      Word32
0x495a2dd4,
      Word32
0x44190b0d,
      Word32
0x40d816ba,
      Word32
0xaca5c697,
      Word32
0xa864db20,
      Word32
0xa527fdf9,
      Word32
0xa1e6e04e,
      Word32
0xbfa1b04b,
      Word32
0xbb60adfc,
      Word32
0xb6238b25,
      Word32
0xb2e29692,
      Word32
0x8aad2b2f,
      Word32
0x8e6c3698,
      Word32
0x832f1041,
      Word32
0x87ee0df6,
      Word32
0x99a95df3,
      Word32
0x9d684044,
      Word32
0x902b669d,
      Word32
0x94ea7b2a,
      Word32
0xe0b41de7,
      Word32
0xe4750050,
      Word32
0xe9362689,
      Word32
0xedf73b3e,
      Word32
0xf3b06b3b,
      Word32
0xf771768c,
      Word32
0xfa325055,
      Word32
0xfef34de2,
      Word32
0xc6bcf05f,
      Word32
0xc27dede8,
      Word32
0xcf3ecb31,
      Word32
0xcbffd686,
      Word32
0xd5b88683,
      Word32
0xd1799b34,
      Word32
0xdc3abded,
      Word32
0xd8fba05a,
      Word32
0x690ce0ee,
      Word32
0x6dcdfd59,
      Word32
0x608edb80,
      Word32
0x644fc637,
      Word32
0x7a089632,
      Word32
0x7ec98b85,
      Word32
0x738aad5c,
      Word32
0x774bb0eb,
      Word32
0x4f040d56,
      Word32
0x4bc510e1,
      Word32
0x46863638,
      Word32
0x42472b8f,
      Word32
0x5c007b8a,
      Word32
0x58c1663d,
      Word32
0x558240e4,
      Word32
0x51435d53,
      Word32
0x251d3b9e,
      Word32
0x21dc2629,
      Word32
0x2c9f00f0,
      Word32
0x285e1d47,
      Word32
0x36194d42,
      Word32
0x32d850f5,
      Word32
0x3f9b762c,
      Word32
0x3b5a6b9b,
      Word32
0x0315d626,
      Word32
0x07d4cb91,
      Word32
0x0a97ed48,
      Word32
0x0e56f0ff,
      Word32
0x1011a0fa,
      Word32
0x14d0bd4d,
      Word32
0x19939b94,
      Word32
0x1d528623,
      Word32
0xf12f560e,
      Word32
0xf5ee4bb9,
      Word32
0xf8ad6d60,
      Word32
0xfc6c70d7,
      Word32
0xe22b20d2,
      Word32
0xe6ea3d65,
      Word32
0xeba91bbc,
      Word32
0xef68060b,
      Word32
0xd727bbb6,
      Word32
0xd3e6a601,
      Word32
0xdea580d8,
      Word32
0xda649d6f,
      Word32
0xc423cd6a,
      Word32
0xc0e2d0dd,
      Word32
0xcda1f604,
      Word32
0xc960ebb3,
      Word32
0xbd3e8d7e,
      Word32
0xb9ff90c9,
      Word32
0xb4bcb610,
      Word32
0xb07daba7,
      Word32
0xae3afba2,
      Word32
0xaafbe615,
      Word32
0xa7b8c0cc,
      Word32
0xa379dd7b,
      Word32
0x9b3660c6,
      Word32
0x9ff77d71,
      Word32
0x92b45ba8,
      Word32
0x9675461f,
      Word32
0x8832161a,
      Word32
0x8cf30bad,
      Word32
0x81b02d74,
      Word32
0x857130c3,
      Word32
0x5d8a9099,
      Word32
0x594b8d2e,
      Word32
0x5408abf7,
      Word32
0x50c9b640,
      Word32
0x4e8ee645,
      Word32
0x4a4ffbf2,
      Word32
0x470cdd2b,
      Word32
0x43cdc09c,
      Word32
0x7b827d21,
      Word32
0x7f436096,
      Word32
0x7200464f,
      Word32
0x76c15bf8,
      Word32
0x68860bfd,
      Word32
0x6c47164a,
      Word32
0x61043093,
      Word32
0x65c52d24,
      Word32
0x119b4be9,
      Word32
0x155a565e,
      Word32
0x18197087,
      Word32
0x1cd86d30,
      Word32
0x029f3d35,
      Word32
0x065e2082,
      Word32
0x0b1d065b,
      Word32
0x0fdc1bec,
      Word32
0x3793a651,
      Word32
0x3352bbe6,
      Word32
0x3e119d3f,
      Word32
0x3ad08088,
      Word32
0x2497d08d,
      Word32
0x2056cd3a,
      Word32
0x2d15ebe3,
      Word32
0x29d4f654,
      Word32
0xc5a92679,
      Word32
0xc1683bce,
      Word32
0xcc2b1d17,
      Word32
0xc8ea00a0,
      Word32
0xd6ad50a5,
      Word32
0xd26c4d12,
      Word32
0xdf2f6bcb,
      Word32
0xdbee767c,
      Word32
0xe3a1cbc1,
      Word32
0xe760d676,
      Word32
0xea23f0af,
      Word32
0xeee2ed18,
      Word32
0xf0a5bd1d,
      Word32
0xf464a0aa,
      Word32
0xf9278673,
      Word32
0xfde69bc4,
      Word32
0x89b8fd09,
      Word32
0x8d79e0be,
      Word32
0x803ac667,
      Word32
0x84fbdbd0,
      Word32
0x9abc8bd5,
      Word32
0x9e7d9662,
      Word32
0x933eb0bb,
      Word32
0x97ffad0c,
      Word32
0xafb010b1,
      Word32
0xab710d06,
      Word32
0xa6322bdf,
      Word32
0xa2f33668,
      Word32
0xbcb4666d,
      Word32
0xb8757bda,
      Word32
0xb5365d03,
      Word32
0xb1f740b4
    ]