{-# 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 :: ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
withByteStringPtr b :: ByteString
b f :: 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 :: 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 (fptr :: ForeignPtr Word8
fptr, off :: Int
off, len :: 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 :: Int -> n -> [Word8]
netEncode bytes :: 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 0 r :: [a]
r _ = [a]
r
	_work n :: t
n r :: [a]
r v :: t
v = let (d :: t
d, m :: t
m) = t -> t -> (t, t)
forall a. Integral a => a -> a -> (a, a)
divMod t
v 256 in t -> [a] -> t -> [a]
_work (t
nt -> t -> t
forall a. Num a => a -> a -> a
-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