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
import Foreign.C.String
import Data.ByteString (ByteString)
import Data.ByteString.Unsafe
import Data.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