use crate::drbg::csg::{qrc_csg_dispose, qrc_csg_generate, qrc_csg_initialize, QrcCsgState};
use crate::tools::intutils::{qrc_intutils_be8to16, qrc_intutils_be8to16i, qrc_intutils_be8to32, qrc_intutils_be8to32i, qrc_intutils_be8to64, qrc_intutils_be8to64i, qrc_intutils_clear8, qrc_intutils_clear8all, qrc_intutils_copy8};
use core::{mem::size_of, default::Default, u16, u32, u64, i16, i32, i64};
#[cfg(feature = "no_std")]
use alloc::borrow::ToOwned;
const INT16_MAX: i16 = i16::MAX;
const UINT16_MAX: u16 = u16::MAX;
const INT32_MAX: i32 = i32::MAX;
const UINT32_MAX: u32 = u32::MAX;
const INT64_MAX: i64 = i64::MAX;
const UINT64_MAX: u64 = u64::MAX;
pub const QRC_SECRAND_CACHE_SIZE: usize = 0x400;
#[derive(PartialEq)]
pub struct QrcSecrandState {
pub hstate: QrcCsgState,
pub cache: [u8; QRC_SECRAND_CACHE_SIZE],
pub cpos: usize,
pub init: bool
}
impl Default for QrcSecrandState {
fn default() -> Self {
Self {
hstate: QrcCsgState::default(),
cache: [Default::default(); QRC_SECRAND_CACHE_SIZE],
cpos: Default::default(),
init: Default::default(),
}
}
}
pub fn qrc_secrand_next_char(state: &mut QrcSecrandState) -> i8 {
let smp = &mut [0u8; size_of::<i8>()];
qrc_secrand_generate(state, smp, size_of::<i8>());
return smp[0] as i8;
}
pub fn qrc_secrand_next_uchar(state: &mut QrcSecrandState) -> u8 {
let smp = &mut [0u8; size_of::<u8>()];
qrc_secrand_generate(state, smp, size_of::<u8>());
return smp[0];
}
pub fn qrc_secrand_next_double(state: &mut QrcSecrandState) -> f64 {
let smp = &mut [0u8; size_of::<f64>()];
qrc_secrand_generate(state, smp, size_of::<f64>());
return f64::from_ne_bytes(smp.to_owned());
}
pub fn qrc_secrand_next_int16(state: &mut QrcSecrandState) -> i16 {
let smp = &mut [0u8; size_of::<i16>()];
qrc_secrand_generate(state, smp, size_of::<i16>());
return qrc_intutils_be8to16i(smp);
}
pub fn qrc_secrand_next_int16_max(state: &mut QrcSecrandState, maximum: i16) -> i16 {
let smpmax = (INT16_MAX - (INT16_MAX % maximum)) as i16;
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int16(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_int16_maxmin(state: &mut QrcSecrandState, maximum: i16, minimum: i16) -> i16 {
let smpthr = maximum - minimum + 1;
let smpmax = (INT16_MAX - (INT16_MAX % smpthr)) as i16;
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int16(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_next_uint16(state: &mut QrcSecrandState) -> u16 {
let smp = &mut [0u8; size_of::<u16>()];
qrc_secrand_generate(state, smp, size_of::<u16>());
return qrc_intutils_be8to16(smp);
}
pub fn qrc_secrand_next_uint16_max(state: &mut QrcSecrandState, maximum: u16) -> u16 {
let smpmax = (UINT16_MAX - (UINT16_MAX % maximum)) as u16;
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint16(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_uint16_maxmin(state: &mut QrcSecrandState, maximum: u16, minimum: u16) -> u16 {
let smpthr = maximum - minimum + 1;
let smpmax = UINT16_MAX - (UINT16_MAX % smpthr) as u16;
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint16(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_next_int32(state: &mut QrcSecrandState) -> i32 {
let smp = &mut [0u8; size_of::<i32>()];
qrc_secrand_generate(state, smp, size_of::<i32>());
return qrc_intutils_be8to32i(smp);
}
pub fn qrc_secrand_next_int32_max(state: &mut QrcSecrandState, maximum: i32) -> i32 {
let smpmax = INT32_MAX - (INT32_MAX % maximum);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int32(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_int32_maxmin(state: &mut QrcSecrandState, maximum: i32, minimum: i32) -> i32 {
let smpthr = maximum - minimum + 1;
let smpmax = INT32_MAX - (INT32_MAX % smpthr);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int32(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_next_uint32(state: &mut QrcSecrandState) -> u32{
let smp = &mut [0u8; size_of::<u32>()];
qrc_secrand_generate(state, smp, size_of::<u32>());
return qrc_intutils_be8to32(smp);
}
pub fn qrc_secrand_next_uint32_max(state: &mut QrcSecrandState, maximum: u32) -> u32 {
let smpmax = UINT32_MAX - (UINT32_MAX % maximum);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint32(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_uint32_maxmin(state: &mut QrcSecrandState, maximum: u32, minimum: u32) -> u32 {
let smpthr = maximum - minimum + 1;
let smpmax = UINT32_MAX - (UINT32_MAX % smpthr);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint32(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_next_int64(state: &mut QrcSecrandState) -> i64 {
let smp = &mut [0u8; size_of::<i64>()];
qrc_secrand_generate(state, smp, size_of::<i64>());
return qrc_intutils_be8to64i(smp);
}
pub fn qrc_secrand_next_int64_max(state: &mut QrcSecrandState, maximum: i64) -> i64{
let smpmax = INT64_MAX - (INT64_MAX % maximum);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int64(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_int64_maxmin(state: &mut QrcSecrandState, maximum: i64, minimum: i64) -> i64 {
let smpthr = maximum - minimum + 1;
let smpmax = INT64_MAX - (INT64_MAX % smpthr);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret < 0 {
x = qrc_secrand_next_int64(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_next_uint64(state: &mut QrcSecrandState) -> u64 {
let smp = &mut [0u8; size_of::<u64>()];
qrc_secrand_generate(state, smp, size_of::<u64>());
return qrc_intutils_be8to64(smp);
}
pub fn qrc_secrand_next_uint64_max(state: &mut QrcSecrandState, maximum: u64) -> u64 {
let smpmax = UINT64_MAX - (UINT64_MAX % maximum);
let mut x = 04;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint64(state);
ret = x % maximum;
}
return ret;
}
pub fn qrc_secrand_next_uint64_maxmin(state: &mut QrcSecrandState, maximum: u64, minimum: u64) -> u64 {
let smpthr = maximum - minimum + 1;
let smpmax = UINT64_MAX - (UINT64_MAX % smpthr);
let mut x = 0;
let mut ret = 0;
while x >= smpmax || ret == 0 {
x = qrc_secrand_next_uint64(state);
ret = x % smpthr;
}
return minimum + ret;
}
pub fn qrc_secrand_destroy(secrand_state: &mut QrcSecrandState) {
if secrand_state.init {
qrc_intutils_clear8(&mut secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
qrc_csg_dispose(&mut secrand_state.hstate);
secrand_state.cpos = 0;
secrand_state.init = false;
}
}
pub fn qrc_secrand_initialize(secrand_state: &mut QrcSecrandState, seed: &[u8], seedlen: usize, custom: &[u8], custlen: usize) {
qrc_csg_initialize(&mut secrand_state.hstate, seed, seedlen, custom, custlen, true);
qrc_csg_generate(&mut secrand_state.hstate, &mut secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
secrand_state.cpos = 0;
secrand_state.init = true;
}
pub fn qrc_secrand_generate(secrand_state: &mut QrcSecrandState, output: &mut [u8], mut length: usize) -> bool {
let buflen = QRC_SECRAND_CACHE_SIZE - secrand_state.cpos;
let mut res = false;
if !secrand_state.init {
qrc_intutils_clear8all(output);
length = 0;
}
if length != 0 {
if length > buflen {
let mut poft = 0;
if buflen > 0 {
qrc_intutils_copy8(output, &secrand_state.cache[secrand_state.cpos..], buflen);
length -= buflen;
poft += buflen;
secrand_state.cpos = QRC_SECRAND_CACHE_SIZE;
}
while length >= QRC_SECRAND_CACHE_SIZE {
qrc_csg_generate(&mut secrand_state.hstate, &mut secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
qrc_intutils_copy8(&mut output[poft..], &secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
length -= QRC_SECRAND_CACHE_SIZE;
poft += QRC_SECRAND_CACHE_SIZE;
}
if length != 0 {
qrc_csg_generate(&mut secrand_state.hstate, &mut secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
qrc_intutils_copy8(&mut output[poft..], &secrand_state.cache, length);
secrand_state.cpos = length;
}
} else {
qrc_intutils_copy8(output, &secrand_state.cache[secrand_state.cpos..], length);
secrand_state.cpos += length;
}
res = true;
}
if secrand_state.cpos != 0 {
qrc_intutils_clear8(&mut secrand_state.cache, QRC_SECRAND_CACHE_SIZE);
}
return res;
}