#![cfg_attr(not(test), no_std)]
use core::str;
use core::ffi::CStr;
#[doc(hidden)]
pub mod wide;
#[doc(hidden)]
pub mod cfo;
mod murmur3;
pub use self::murmur3::murmur3;
mod pos;
pub use self::pos::position;
#[doc(hidden)]
pub mod xref;
#[macro_export]
macro_rules! random {
($ty:ident $(, $seeds:expr)* $(,)?) => {{
const _RANDOM: $ty = $crate::__random_cast!($ty,
$crate::entropy(concat!(file!(), ":", line!(), ":", column!() $(, ":", $seeds)*)));
_RANDOM
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __random_cast {
(u8, $seed:expr) => { $seed as u8 };
(u16, $seed:expr) => { $seed as u16 };
(u32, $seed:expr) => { $seed as u32 };
(u64, $seed:expr) => { $seed };
(usize, $seed:expr) => { $seed as usize };
(i8, $seed:expr) => { $seed as i8 };
(i16, $seed:expr) => { $seed as i16 };
(i32, $seed:expr) => { $seed as i32 };
(i64, $seed:expr) => { $seed as i64 };
(isize, $seed:expr) => { $seed as isize };
(bool, $seed:expr) => { $seed as i64 >= 0 };
(f32, $seed:expr) => { unsafe { ::core::mem::transmute::<u32, f32>(0b0_01111111 << (f32::MANTISSA_DIGITS - 1) | ($seed as u32 >> 9)) } };
(f64, $seed:expr) => { unsafe { ::core::mem::transmute::<u64, f64>(0b0_01111111111 << (f64::MANTISSA_DIGITS - 1) | ($seed >> 12)) } };
($ty:ident, $seed:expr) => { compile_error!(concat!("unsupported type: ", stringify!($ty))) };
}
#[test]
fn test_random_f32() {
#[track_caller]
fn t(v: f32) {
assert!(v >= 1.0 && v < 2.0, "{}", v);
}
use random as r;
t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));
t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));
t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));
t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));t(r!(f32));
}
#[test]
fn test_random_f64() {
#[track_caller]
fn t(v: f64) {
assert!(v >= 1.0 && v < 2.0, "{}", v);
}
use random as r;
t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));
t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));
t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));
t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));t(r!(f64));
}
#[inline(always)]
pub const fn splitmix(seed: u64) -> u64 {
let next = seed.wrapping_add(0x9e3779b97f4a7c15);
let mut z = next;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
return z ^ (z >> 31);
}
#[inline(always)]
pub const fn hash(s: &str) -> u32 {
let s = s.as_bytes();
let mut result = 3581u32;
let mut i = 0usize;
while i < s.len() {
result = result.wrapping_mul(33) ^ s[i] as u32;
i += 1;
}
return result;
}
#[macro_export]
macro_rules! hash {
($s:expr) => {{ const _DJB2_HASH: u32 = $crate::hash($s); _DJB2_HASH }};
}
#[doc(hidden)]
#[inline(always)]
pub const fn entropy(string: &str) -> u64 {
splitmix(SEED ^ splitmix(hash(string) as u64))
}
pub const SEED: u64 = splitmix(hash(match option_env!("OBFSTR_SEED") { Some(seed) => seed, None => "FIXED" }) as u64);
#[doc(hidden)]
pub mod bytes;
#[doc(hidden)]
pub mod words;
#[doc(hidden)]
#[inline(always)]
pub const fn unsafe_as_str(bytes: &[u8]) -> &str {
#[cfg(debug_assertions)]
return match str::from_utf8(bytes) { Ok(s) => s, Err(_) => panic!("invalid str") };
#[cfg(not(debug_assertions))]
return unsafe { str::from_utf8_unchecked(bytes) };
}
#[doc(hidden)]
#[inline(always)]
pub const fn unsafe_as_cstr(bytes: &[u8]) -> &CStr {
#[cfg(debug_assertions)]
return match CStr::from_bytes_with_nul(bytes) { Ok(cstr) => cstr, Err(_) => panic!("invalid cstr") };
#[cfg(not(debug_assertions))]
return unsafe { CStr::from_bytes_with_nul_unchecked(bytes) };
}