{-# 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}.
(Num t, Num a, Eq t, Integral 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