module System.Random.URandom (urandom) where

import Foreign.C.Types (CUChar, CInt)
import Foreign.Ptr (Ptr, castPtr)
import System.IO.Error (ioError, userError)
import qualified Data.ByteString as S
import qualified Data.ByteString.Internal as SI


-- XXX why should we specify unsafe if the function is perfectly safe?
foreign import ccall unsafe "HsUrandom.h hsUrandom"
   c_urandom :: Ptr CUChar -> CInt -> IO CInt

urandom :: Int -> IO S.ByteString
urandom 0 = return S.empty
urandom n = SI.create n pseudoBytes
    where
      pseudoBytes p = do
        ret <- c_urandom (castPtr p) (fromIntegral n)
        if ret == -1
          -- TODO: we should use platform specific error routine, to
          -- supply more informations about the occurred error.
          then ioError $ userError "urandom failed"
          else return ()