yaftee-conduit-bytestring-0.1.0.0: src/Control/Monad/Yaftee/Pipe/ByteString/Crc/Common.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RequiredTypeArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
module Control.Monad.Yaftee.Pipe.ByteString.Crc.Common (
-- * RUN STATE
runCrc32, resetCrc32, compCrc32,
-- * TYPE
Crc32(..), crc32Step, initialCrc32, complementCrc32
) where
import Control.Arrow
import Control.Monad.Yaftee.Eff qualified as Eff
import Control.Monad.Yaftee.State qualified as State
import Control.HigherOpenUnion qualified as U
import Data.HigherFunctor qualified as HFunctor
import Data.Bits
import Data.Bits.ToolsYj
import Data.Array
import Data.Bool
import Data.Word
runCrc32 :: forall nm es i o r . HFunctor.Loose (U.U es) =>
Eff.E (State.Named nm Crc32 ': es) i o r -> Eff.E es i o (r, Crc32)
runCrc32 = (`State.runN` Crc32 0)
resetCrc32 :: forall nm -> U.Member (State.Named nm Crc32) es =>
Eff.E es i o ()
resetCrc32 nm = State.putN nm $ Crc32 0xffffffff
compCrc32 :: forall nm -> U.Member (State.Named nm Crc32) es => Eff.E es i o ()
compCrc32 nm = State.modifyN nm \(Crc32 c) -> Crc32 $ complement c
newtype Crc32 = Crc32 { unCrc32 :: Word32 } deriving (Show, Eq)
crc1 :: Word32 -> Word32
crc1 = uncurry (bool id (`xor` 0xedb88320)) . popBit
crc8 :: Word8 -> Word32
crc8 n = iterate crc1 (fromIntegral n) !! 8
table :: Array Word8 Word32
table = listArray (0, 255) $ map crc8 [0 .. 255]
popByte :: (Integral a, Bits a) => a -> (Word8, a)
popByte n = (fromIntegral n, n `shiftR` 8)
crc32Step :: Word32 -> Word8 -> Word32
crc32Step n b = uncurry xor . (first $ (table !) . (`xor` b)) $ popByte n
initialCrc32 :: Crc32
initialCrc32 = Crc32 0xffffffff
complementCrc32 :: Crc32 -> Crc32
complementCrc32 = Crc32 . complement . unCrc32