packages feed

hask-redis-mux-0.1.0.0: lib/crc16/Database/Redis/Crc16.hs

-- | CRC16 hash computation for Redis cluster slot assignment.
-- Wraps a C implementation via FFI. The FFI call is safe to treat as pure
-- (deterministic, no side effects), so we use 'unsafeDupablePerformIO' to
-- avoid forcing callers into IO on the hot path.
--
-- @since 0.1.0.0
module Database.Redis.Crc16  ( crc16 ) where

import           Data.Bits             ((.&.))
import           Data.ByteString       (ByteString)
import qualified Data.ByteString.Char8 as BS8
import           Data.Word             (Word16)
import           Foreign.C.String      (CString)
import           Foreign.C.Types       (CInt (..), CUShort (..))
import           System.IO.Unsafe      (unsafeDupablePerformIO)

-- Foreign function interface to the C function (marked unsafe for speed — no callbacks)
foreign import ccall unsafe "crc16" c_crc16 :: CString -> CInt -> CUShort

-- | Compute the CRC16 hash of a key, reduced to the Redis cluster slot range (0–16383).
-- Pure: the underlying C function is deterministic with no side effects.
crc16 :: ByteString -> Word16
crc16 bs = unsafeDupablePerformIO $
  BS8.useAsCStringLen bs $ \(cstr, len) -> do
    let !result = c_crc16 cstr (fromIntegral len)
    return $! fromIntegral result .&. (0x3FFF :: Word16)
{-# INLINE crc16 #-}