{-# LANGUAGE BangPatterns #-}
module Crypto.Internal.Builder
( Builder
, buildAndFreeze
, builderLength
, byte
, bytes
, zero
) where
import Data.ByteArray (ByteArray, ByteArrayAccess)
import qualified Data.ByteArray as B
import Data.Memory.PtrMethods (memSet)
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (poke)
import Crypto.Internal.Imports hiding (empty)
data Builder = Builder !Int (Ptr Word8 -> IO ())
instance Semigroup Builder where
(Builder Int
s1 Ptr Word8 -> IO ()
f1) <> :: Builder -> Builder -> Builder
<> (Builder Int
s2 Ptr Word8 -> IO ()
f2) = Int -> (Ptr Word8 -> IO ()) -> Builder
Builder (Int
s1 forall a. Num a => a -> a -> a
+ Int
s2) Ptr Word8 -> IO ()
f
where f :: Ptr Word8 -> IO ()
f Ptr Word8
p = Ptr Word8 -> IO ()
f1 Ptr Word8
p forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr Word8 -> IO ()
f2 (Ptr Word8
p forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
s1)
builderLength :: Builder -> Int
builderLength :: Builder -> Int
builderLength (Builder Int
s Ptr Word8 -> IO ()
_) = Int
s
buildAndFreeze :: ByteArray ba => Builder -> ba
buildAndFreeze :: forall ba. ByteArray ba => Builder -> ba
buildAndFreeze (Builder Int
s Ptr Word8 -> IO ()
f) = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
s Ptr Word8 -> IO ()
f
byte :: Word8 -> Builder
byte :: Word8 -> Builder
byte !Word8
b = Int -> (Ptr Word8 -> IO ()) -> Builder
Builder Int
1 (forall a. Storable a => Ptr a -> a -> IO ()
`poke` Word8
b)
bytes :: ByteArrayAccess ba => ba -> Builder
bytes :: forall ba. ByteArrayAccess ba => ba -> Builder
bytes ba
bs = Int -> (Ptr Word8 -> IO ()) -> Builder
Builder (forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs) (forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
B.copyByteArrayToPtr ba
bs)
zero :: Int -> Builder
zero :: Int -> Builder
zero Int
s = if Int
s forall a. Ord a => a -> a -> Bool
> Int
0 then Int -> (Ptr Word8 -> IO ()) -> Builder
Builder Int
s (\Ptr Word8
p -> Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
p Word8
0 Int
s) else Builder
empty
empty :: Builder
empty :: Builder
empty = Int -> (Ptr Word8 -> IO ()) -> Builder
Builder Int
0 (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ())