Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Created October 15, 2015 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NicolasT/2e109f40ea2e6213a0d0 to your computer and use it in GitHub Desktop.
Save NicolasT/2e109f40ea2e6213a0d0 to your computer and use it in GitHub Desktop.
Combining intermediate CRC32 results
module Main where
import Data.Word (Word8, Word32)
import Foreign.C (CUInt(..), CULong(..))
import Foreign.Ptr (Ptr)
import System.IO.Unsafe (unsafePerformIO)
import qualified Data.ByteString as BS
import Test.QuickCheck
type CRC32 = Word32
foreign import ccall unsafe "zlib.h crc32" c_crc32 ::
CULong -> Ptr a -> CUInt -> CULong
foreign import ccall unsafe "zlib.h crc32_combine" c_crc32_combine ::
CULong -> CULong -> CUInt -> CULong
crc32 :: BS.ByteString -> CRC32 -> CRC32
crc32 bs init = fromIntegral $ unsafePerformIO go
where
go = BS.useAsCStringLen bs $ \(ptr, len) ->
pure $ c_crc32 (fromIntegral init) ptr (fromIntegral len)
combine :: CRC32 -> CRC32 -> Int -> CRC32
combine crc1 crc2 len2 = fromIntegral combined
where
combined = c_crc32_combine (fromIntegral crc1)
(fromIntegral crc2)
(fromIntegral len2)
prop_crc32_combine :: [Word8] -> [Word8] -> Bool
prop_crc32_combine l1 l2 =
combine (crc32 s1 0) (crc32 s2 0) (BS.length s2) == crc32 (BS.append s1 s2) 0
where
s1 = BS.pack l1
s2 = BS.pack l2
main :: IO ()
main = quickCheck prop_crc32_combine
$ stack runghc -- -lz crc32_prop.hs 2>/dev/null
+++ OK, passed 100 tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment