module Database.VCache.Refct
( readRefctBytes
, toRefctBytes
, writeRefctBytes
, Refct
) where
import Control.Exception
import Data.Word
import Data.Bits
import Foreign.Ptr
import Foreign.Storable
import Database.LMDB.Raw
type Refct = Int
readRefctBytes :: MDB_val -> IO Refct
readRefctBytes v = rd (mv_data v) (mv_size v) 0 where
rd _ 0 rc = return (rc + 1)
rd p n rc = do
w8 <- peek p
let rc' = (rc `shiftL` 8) .|. (fromIntegral w8)
rd (p `plusPtr` 1) (n 1) rc'
toRefctBytes :: Refct -> [Word8]
toRefctBytes = rcb [] . subtract 1 . assertPositive where
rcb l 0 = l
rcb l rc = rcb (fromIntegral rc : l) (rc `shiftR` 8)
assertPositive n = assert (n > 0) n
writeRefctBytes :: Ptr Word8 -> Refct -> IO MDB_val
writeRefctBytes p0 = wrcb p0 0 . toRefctBytes where
wrcb _ n [] = return $! MDB_val { mv_data = p0, mv_size = n }
wrcb p n (b:bs) = do { poke p b ; wrcb (p `plusPtr` 1) (n + 1) bs }