{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RecordWildCards #-}
module PRGenerator
(
RandomState, reseed, fillRandomBytes
, entropySource, csprgName, csprgDescription
) where
import Foreign.Ptr ( castPtr )
import Entropy
import Prelude
import Raaz.Core
import Raaz.Core.Memory
import Implementation
import Context
csprgName :: String
csprgName :: String
csprgName = String
name
csprgDescription :: String
csprgDescription :: String
csprgDescription = String
description
data RandomState = RandomState { RandomState -> Cxt RandomBufferSize
randomCxt :: Cxt RandomBufferSize
, RandomState -> MemoryCell (BlockCount Prim)
randomGenBlocks :: MemoryCell (BlockCount Prim)
}
instance Memory RandomState where
memoryAlloc :: Alloc RandomState
memoryAlloc = Cxt RandomBufferSize -> MemoryCell (BlockCount Prim) -> RandomState
RandomState (Cxt RandomBufferSize
-> MemoryCell (BlockCount Prim) -> RandomState)
-> TwistRF AllocField (BYTES Int) (Cxt RandomBufferSize)
-> TwistRF
AllocField
(BYTES Int)
(MemoryCell (BlockCount Prim) -> RandomState)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TwistRF AllocField (BYTES Int) (Cxt RandomBufferSize)
forall m. Memory m => Alloc m
memoryAlloc TwistRF
AllocField
(BYTES Int)
(MemoryCell (BlockCount Prim) -> RandomState)
-> TwistRF AllocField (BYTES Int) (MemoryCell (BlockCount Prim))
-> Alloc RandomState
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TwistRF AllocField (BYTES Int) (MemoryCell (BlockCount Prim))
forall m. Memory m => Alloc m
memoryAlloc
unsafeToPointer :: RandomState -> Ptr Word8
unsafeToPointer = Cxt RandomBufferSize -> Ptr Word8
forall m. Memory m => m -> Ptr Word8
unsafeToPointer (Cxt RandomBufferSize -> Ptr Word8)
-> (RandomState -> Cxt RandomBufferSize)
-> RandomState
-> Ptr Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandomState -> Cxt RandomBufferSize
randomCxt
instance WriteAccessible RandomState where
writeAccess :: RandomState -> [Access]
writeAccess = Internals -> [Access]
forall mem. WriteAccessible mem => mem -> [Access]
writeAccess (Internals -> [Access])
-> (RandomState -> Internals) -> RandomState -> [Access]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cxt RandomBufferSize -> Internals
forall (n :: Nat). Cxt n -> Internals
cxtInternals (Cxt RandomBufferSize -> Internals)
-> (RandomState -> Cxt RandomBufferSize)
-> RandomState
-> Internals
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandomState -> Cxt RandomBufferSize
randomCxt
afterWriteAdjustment :: RandomState -> IO ()
afterWriteAdjustment = Internals -> IO ()
forall mem. WriteAccessible mem => mem -> IO ()
afterWriteAdjustment (Internals -> IO ())
-> (RandomState -> Internals) -> RandomState -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cxt RandomBufferSize -> Internals
forall (n :: Nat). Cxt n -> Internals
cxtInternals (Cxt RandomBufferSize -> Internals)
-> (RandomState -> Cxt RandomBufferSize)
-> RandomState
-> Internals
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandomState -> Cxt RandomBufferSize
randomCxt
sample :: RandomState -> IO ()
sample :: RandomState -> IO ()
sample rstate :: RandomState
rstate@RandomState{MemoryCell (BlockCount Prim)
Cxt RandomBufferSize
randomGenBlocks :: MemoryCell (BlockCount Prim)
randomCxt :: Cxt RandomBufferSize
randomGenBlocks :: RandomState -> MemoryCell (BlockCount Prim)
randomCxt :: RandomState -> Cxt RandomBufferSize
..} = do
BlockCount Prim
genBlocks <- MemoryCell (BlockCount Prim) -> IO (BlockCount Prim)
forall m v. Extractable m v => m -> IO v
extract MemoryCell (BlockCount Prim)
randomGenBlocks
if BlockCount Prim
genBlocks BlockCount Prim -> BlockCount Prim -> Bool
forall a. Ord a => a -> a -> Bool
>= BlockCount Prim
reseedAfter then RandomState -> IO ()
reseed RandomState
rstate
else RandomState -> IO ()
generateRandom RandomState
rstate
reseed :: RandomState -> IO ()
reseed :: RandomState -> IO ()
reseed rstate :: RandomState
rstate@RandomState{MemoryCell (BlockCount Prim)
Cxt RandomBufferSize
randomGenBlocks :: MemoryCell (BlockCount Prim)
randomCxt :: Cxt RandomBufferSize
randomGenBlocks :: RandomState -> MemoryCell (BlockCount Prim)
randomCxt :: RandomState -> Cxt RandomBufferSize
..} = do
RandomState -> IO ()
unsafeInitWithEntropy RandomState
rstate
BlockCount Prim -> MemoryCell (BlockCount Prim) -> IO ()
forall m v. Initialisable m v => v -> m -> IO ()
initialise BlockCount Prim
zeroBlocks MemoryCell (BlockCount Prim)
randomGenBlocks
RandomState -> IO ()
generateRandom RandomState
rstate
generateRandom :: RandomState -> IO ()
generateRandom :: RandomState -> IO ()
generateRandom rstate :: RandomState
rstate@RandomState{MemoryCell (BlockCount Prim)
Cxt RandomBufferSize
randomGenBlocks :: MemoryCell (BlockCount Prim)
randomCxt :: Cxt RandomBufferSize
randomGenBlocks :: RandomState -> MemoryCell (BlockCount Prim)
randomCxt :: RandomState -> Cxt RandomBufferSize
..} = do
(BufferPtr -> BlockCount Prim -> Internals -> IO ())
-> Cxt RandomBufferSize -> IO ()
forall (n :: Nat).
KnownNat n =>
(BufferPtr -> BlockCount Prim -> Internals -> IO ())
-> Cxt n -> IO ()
unsafeGenerateBlocks BufferPtr -> BlockCount Prim -> Internals -> IO ()
randomBlocks Cxt RandomBufferSize
randomCxt
(BlockCount Prim -> BlockCount Prim)
-> MemoryCell (BlockCount Prim) -> IO ()
forall mem a b.
(Initialisable mem a, Extractable mem b) =>
(b -> a) -> mem -> IO ()
modifyMem (BlockCount Prim -> BlockCount Prim -> BlockCount Prim
forall a. Monoid a => a -> a -> a
mappend (BlockCount Prim -> BlockCount Prim -> BlockCount Prim)
-> BlockCount Prim -> BlockCount Prim -> BlockCount Prim
forall a b. (a -> b) -> a -> b
$ Proxy (Cxt RandomBufferSize) -> BlockCount Prim
forall (n :: Nat). KnownNat n => Proxy (Cxt n) -> BlockCount Prim
cxtBlockCount (Proxy (Cxt RandomBufferSize) -> BlockCount Prim)
-> Proxy (Cxt RandomBufferSize) -> BlockCount Prim
forall a b. (a -> b) -> a -> b
$ Cxt RandomBufferSize -> Proxy (Cxt RandomBufferSize)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Cxt RandomBufferSize
randomCxt) MemoryCell (BlockCount Prim)
randomGenBlocks
RandomState -> IO ()
unsafeInitFromBuffer RandomState
rstate
unsafeInitWithEntropy :: RandomState -> IO ()
unsafeInitWithEntropy :: RandomState -> IO ()
unsafeInitWithEntropy = (Access -> IO (BYTES Int)) -> [Access] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Access -> IO (BYTES Int)
initWithEntropy ([Access] -> IO ())
-> (RandomState -> [Access]) -> RandomState -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandomState -> [Access]
forall mem. WriteAccessible mem => mem -> [Access]
writeAccess
where initWithEntropy :: Access -> IO (BYTES Int)
initWithEntropy Access{Ptr Word8
BYTES Int
accessSize :: Access -> BYTES Int
accessPtr :: Access -> Ptr Word8
accessSize :: BYTES Int
accessPtr :: Ptr Word8
..} = BYTES Int -> Ptr Word8 -> IO (BYTES Int)
getEntropy BYTES Int
accessSize Ptr Word8
accessPtr
unsafeInitFromBuffer :: RandomState -> IO ()
unsafeInitFromBuffer :: RandomState -> IO ()
unsafeInitFromBuffer rstate :: RandomState
rstate@RandomState{MemoryCell (BlockCount Prim)
Cxt RandomBufferSize
randomGenBlocks :: MemoryCell (BlockCount Prim)
randomCxt :: Cxt RandomBufferSize
randomGenBlocks :: RandomState -> MemoryCell (BlockCount Prim)
randomCxt :: RandomState -> Cxt RandomBufferSize
..} = (Access -> IO (BYTES Int)) -> [Access] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Access -> IO (BYTES Int)
initFromBuffer ([Access] -> IO ()) -> [Access] -> IO ()
forall a b. (a -> b) -> a -> b
$ RandomState -> [Access]
forall mem. WriteAccessible mem => mem -> [Access]
writeAccess RandomState
rstate
where initFromBuffer :: Access -> IO (BYTES Int)
initFromBuffer Access{Ptr Word8
BYTES Int
accessSize :: BYTES Int
accessPtr :: Ptr Word8
accessSize :: Access -> BYTES Int
accessPtr :: Access -> Ptr Word8
..}
= BYTES Int
-> Dest (Ptr Word8) -> Cxt RandomBufferSize -> IO (BYTES Int)
forall (n :: Nat).
KnownNat n =>
BYTES Int -> Dest (Ptr Word8) -> Cxt n -> IO (BYTES Int)
unsafeWriteTo BYTES Int
accessSize (Ptr Word8 -> Dest (Ptr Word8)
forall a. a -> Dest a
destination Ptr Word8
accessPtr) Cxt RandomBufferSize
randomCxt
zeroBlocks :: BlockCount Prim
zeroBlocks :: BlockCount Prim
zeroBlocks = Int
0 Int -> Proxy Prim -> BlockCount Prim
forall p. Int -> Proxy p -> BlockCount p
`blocksOf` Proxy Prim
forall k (t :: k). Proxy t
Proxy
unsafeRandomBytes :: BYTES Int
-> Dest (Ptr Word8)
-> RandomState -> IO ()
unsafeRandomBytes :: BYTES Int -> Dest (Ptr Word8) -> RandomState -> IO ()
unsafeRandomBytes BYTES Int
sz Dest (Ptr Word8)
destPtr rstate :: RandomState
rstate@RandomState{MemoryCell (BlockCount Prim)
Cxt RandomBufferSize
randomGenBlocks :: MemoryCell (BlockCount Prim)
randomCxt :: Cxt RandomBufferSize
randomGenBlocks :: RandomState -> MemoryCell (BlockCount Prim)
randomCxt :: RandomState -> Cxt RandomBufferSize
..}
= BYTES Int -> Dest (Ptr Word8) -> IO ()
go BYTES Int
sz Dest (Ptr Word8)
destPtr
where go :: BYTES Int -> Dest (Ptr Word8) -> IO ()
go BYTES Int
n Dest (Ptr Word8)
ptr
| BYTES Int
n BYTES Int -> BYTES Int -> Bool
forall a. Ord a => a -> a -> Bool
<= BYTES Int
0 = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = do BYTES Int
trfed <- BYTES Int
-> Dest (Ptr Word8) -> Cxt RandomBufferSize -> IO (BYTES Int)
forall (n :: Nat).
KnownNat n =>
BYTES Int -> Dest (Ptr Word8) -> Cxt n -> IO (BYTES Int)
unsafeWriteTo BYTES Int
n Dest (Ptr Word8)
ptr Cxt RandomBufferSize
randomCxt
let more :: BYTES Int
more = BYTES Int
n BYTES Int -> BYTES Int -> BYTES Int
forall a. Num a => a -> a -> a
- BYTES Int
trfed
nextPtr :: Dest (Ptr Word8)
nextPtr = (Ptr Word8 -> BYTES Int -> Ptr Word8
forall l a. LengthUnit l => Ptr a -> l -> Ptr a
`movePtr` BYTES Int
trfed) (Ptr Word8 -> Ptr Word8) -> Dest (Ptr Word8) -> Dest (Ptr Word8)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Dest (Ptr Word8)
ptr
in Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (BYTES Int
more BYTES Int -> BYTES Int -> Bool
forall a. Ord a => a -> a -> Bool
> BYTES Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ RandomState -> IO ()
sample RandomState
rstate IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BYTES Int -> Dest (Ptr Word8) -> IO ()
go BYTES Int
more Dest (Ptr Word8)
nextPtr
fillRandomBytes :: (LengthUnit l, Pointer ptr)
=> l
-> Dest (ptr a)
-> RandomState
-> IO ()
fillRandomBytes :: l -> Dest (ptr a) -> RandomState -> IO ()
fillRandomBytes l
l Dest (ptr a)
ptr = BYTES Int -> Dest (Ptr Word8) -> RandomState -> IO ()
unsafeRandomBytes (l -> BYTES Int
forall u. LengthUnit u => u -> BYTES Int
inBytes l
l) Dest (Ptr Word8)
forall b. Dest (Ptr b)
wptr
where wptr :: Dest (Ptr b)
wptr = (ptr a -> Ptr b) -> Dest (ptr a) -> Dest (Ptr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Ptr a -> Ptr b
forall a b. Ptr a -> Ptr b
castPtr (Ptr a -> Ptr b) -> (ptr a -> Ptr a) -> ptr a -> Ptr b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ptr a -> Ptr a
forall (ptr :: * -> *) a. Pointer ptr => ptr a -> Ptr a
unsafeRawPtr) Dest (ptr a)
ptr
instance ByteSource RandomState where
fillBytes :: BYTES Int -> RandomState -> Ptr a -> IO (FillResult RandomState)
fillBytes BYTES Int
n RandomState
rstate Ptr a
ptr
= BYTES Int -> Dest (Ptr Word8) -> RandomState -> IO ()
unsafeRandomBytes BYTES Int
n (Ptr Word8 -> Dest (Ptr Word8)
forall a. a -> Dest a
destination (Ptr a -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr a
ptr)) RandomState
rstate IO () -> IO (FillResult RandomState) -> IO (FillResult RandomState)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> FillResult RandomState -> IO (FillResult RandomState)
forall (m :: * -> *) a. Monad m => a -> m a
return (RandomState -> FillResult RandomState
forall a. a -> FillResult a
Remaining RandomState
rstate)