raaz-0.0.1: Raaz/Core/Util/ByteString.hs
{-|
Some utility function for byte strings.
-}
{-# LANGUAGE FlexibleContexts #-}
module Raaz.Core.Util.ByteString
( length, replicate
, fromByteStringStorable
, createFrom
, withByteString
, unsafeCopyToPointer
, unsafeNCopyToPointer
) where
import Prelude hiding (length, replicate)
import qualified Data.ByteString as B
import Data.ByteString (ByteString)
import Data.ByteString.Internal( toForeignPtr
, create
)
import Data.Word
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (castPtr, plusPtr)
import Foreign.Storable (peek, Storable)
import System.IO.Unsafe (unsafePerformIO)
import Raaz.Core.Types.Pointer
-- | A typesafe length for Bytestring
length :: ByteString -> BYTES Int
length = BYTES . B.length
-- | A type safe version of replicate
replicate :: LengthUnit l => l -> Word8 -> ByteString
replicate l = B.replicate sz
where BYTES sz = inBytes l
-- | Copy the bytestring to the crypto buffer. This operation leads to
-- undefined behaviour if the crypto pointer points to an area smaller
-- than the size of the byte string.
unsafeCopyToPointer :: ByteString -- ^ The source.
-> Pointer -- ^ The destination.
-> IO ()
unsafeCopyToPointer bs cptr = withForeignPtr fptr $
\ p -> memcpy dest (p `plusPtr` offset) (BYTES n)
where (fptr, offset,n) = toForeignPtr bs
dest = castPtr cptr
-- | Similar to `unsafeCopyToPointer` but takes an additional input
-- @n@ which is the number of bytes (expressed in type safe length
-- units) to transfer. This operation leads to undefined behaviour if
-- either the bytestring is shorter than @n@ or the crypto pointer
-- points to an area smaller than @n@.
unsafeNCopyToPointer :: LengthUnit n
=> n -- ^ length of data to be copied
-> ByteString -- ^ The source byte string
-> Pointer -- ^ The buffer
-> IO ()
unsafeNCopyToPointer n bs cptr = withForeignPtr fptr $
\ p -> memcpy dest (p `plusPtr` offset) n
where (fptr, offset,_) = toForeignPtr bs
dest = castPtr cptr
-- | Works directly on the pointer associated with the
-- `ByteString`. This function should only read and not modify the
-- contents of the pointer.
withByteString :: ByteString -> (Pointer -> IO a) -> IO a
withByteString bs f = withForeignPtr fptr (f . flip plusPtr off . castPtr)
where (fptr, off, _) = toForeignPtr bs
-- | Get the value from the bytestring using `peek`.
fromByteStringStorable :: Storable k => ByteString -> k
fromByteStringStorable src = unsafePerformIO $ withByteString src (peek . castPtr)
-- | The IO action @createFrom n cptr@ creates a bytestring by copying
-- @n@ bytes from the pointer @cptr@.
createFrom :: LengthUnit l => l -> Pointer -> IO ByteString
createFrom l cptr = create bytes filler
where filler dest = memcpy (castPtr dest) cptr l
BYTES bytes = inBytes l
---------------------- Hexadecimal encoding. -----------------------------------