    {-# LANGUAGE CPP #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Crypto.Nettle.Hash.Types
    -- Copyright   :  (c) 2013 Stefan Bühler
    -- License     :  MIT-style (see the file COPYING)
    --
    -- Maintainer  :  stbuehler@web.de
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- Collection of internal utility functions and exports of common imports
    --
    -----------------------------------------------------------------------------

    module Nettle.Utils
    	( Ptr
    	, plusPtr
    	, FunPtr
    	, Word8
    	, Word
    	, forM_
    	, unsafeDupablePerformIO
    	, withByteStringPtr
    	, netEncode
    	) where

    import qualified Data.ByteString as B
    import qualified Data.ByteString.Internal as B

    import Foreign.Ptr (Ptr, plusPtr, FunPtr)
    import Foreign.ForeignPtr (withForeignPtr)
    import Data.Word (Word8, Word)
    import Control.Monad (forM_)

    import System.IO.Unsafe (unsafeDupablePerformIO)

    {-|
    Run action in IO monad with length and pointer to first byte of a 'B.ByteString'
    -}
    withByteStringPtr :: B.ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr :: forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    b Word -> Ptr Word8 -> IO a
    f = ForeignPtr Word8 -> (Ptr Word8 -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    fptr ((Ptr Word8 -> IO a) -> IO a) -> (Ptr Word8 -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ptr -> Word -> Ptr Word8 -> IO a
    f (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len) (Ptr Word8
    ptr Ptr Word8 -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    off)
    	where (ForeignPtr Word8
    fptr, Int
    off, Int
    len) = ByteString -> (ForeignPtr Word8, Int, Int)
    B.toForeignPtr ByteString
    b

    {-|
    Encode any 'Integral' @value@ in @bytes@ 'Word8' as big endian value.
    -}
    netEncode :: (Integral n) => Int {- ^ @bytes@ argument -} -> n {- ^ @value@ argument -} -> [Word8]
    netEncode :: forall n. Integral n => Int -> n -> [Word8]
    netEncode Int
    bytes = Int -> [Word8] -> n -> [Word8]
    forall {t} {t} {a}.
    (Integral t, Num t, Num a, Eq t) =>
    t -> [a] -> t -> [a]
    _work Int
    bytes [] where
    	_work :: t -> [a] -> t -> [a]
    _work t
    0 [a]
    r t
    _ = [a]
    r
    	_work t
    n [a]
    r t
    v = let (t
    d, t
    m) = t -> t -> (t, t)
    forall a. Integral a => a -> a -> (a, a)
    divMod t
    v t
    256 in t -> [a] -> t -> [a]
    _work (t
    nt -> t -> t
    forall a. Num a => a -> a -> a
    -t
    1) (t -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral t
    ma -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    r) t
    d