module Data.Hash.SL2.Mutable
( valid
, eq, cmp
, unit
, concat
, append, prepend
, foldAppend, foldPrepend
, serialize, unserialize
, withUnit, withCopy
) where
import Prelude hiding (concat)
import Foreign.Safe
import Foreign.C.String
import Data.ByteString (ByteString)
import Data.ByteString.Unsafe
import Data.Foldable (Foldable, foldlM, foldrM)
import Data.Hash.SL2.Internal (Hash, hashLen)
import qualified Data.Hash.SL2.Internal as Internal
import Data.Hash.SL2.Unsafe
valid :: Ptr Hash -> IO Bool
valid h = fmap toBool $ Internal.valid h
eq :: Ptr Hash -> Ptr Hash -> IO Bool
eq a b = fmap toBool $ Internal.eq a b
cmp :: Ptr Hash -> Ptr Hash -> IO Ordering
cmp a b = fmap (compare 0) $ Internal.cmp a b
unit :: Ptr Hash -> IO ()
unit h = Internal.unit h
concat :: Ptr Hash -> Ptr Hash -> Ptr Hash -> IO ()
concat c a b = Internal.concat c a b
append :: ByteString -> Ptr Hash -> IO ()
append s p = unsafeUseAsCStringLen s $ \(s', len) -> Internal.append p s' (fromIntegral len)
prepend :: ByteString -> Ptr Hash -> IO ()
prepend s p = unsafeUseAsCStringLen s $ \(s', len) -> Internal.prepend p s' (fromIntegral len)
foldAppend :: Foldable t => t ByteString -> Ptr Hash -> IO ()
foldAppend ss p = foldlM (const $ flip append p) () ss
foldPrepend :: Foldable t => t ByteString -> Ptr Hash -> IO ()
foldPrepend ss p = foldrM (const . flip prepend p) () ss
serialize :: Ptr Hash -> IO String
serialize h = allocaBytes hashLen $ \p -> Internal.serialize h p >> peekCStringLen (p, hashLen)
unserialize :: String -> Ptr Hash -> IO (Maybe ())
unserialize s p = withCAStringLen s $ \(s', len) ->
if len == hashLen then Just `fmap` Internal.unserialize p s' else return Nothing
withUnit :: (Ptr Hash -> IO a) -> IO (Hash, a)
withUnit f = unsafeWithNew $ \p -> unit p >> f p
withCopy :: Hash -> (Ptr Hash -> IO a) -> IO (Hash, a)
withCopy h f = unsafeWithNew $ \p -> poke p h >> f p