use parking_lot::{Once, OnceState};
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
static INITIALIZED: Once = Once::new();
pub fn initialize() {
INITIALIZED.call_once(|| {
crate::os::initialize();
});
}
pub fn initialized() -> bool {
INITIALIZED.state() != OnceState::Done
}
#[cfg(feature = "asm")]
pub fn keep<T>(x: T) -> T {
unsafe { llvm_asm!["" : : "r"(&x)] }
x
}
pub fn assert_send(_: impl Send) {}
pub fn assert_sync(_: impl Sync) {}
pub fn assert_send_sync(_: impl Send + Sync) {}
pub trait Any {}
impl<T> Any for T {}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct BlackHole;
impl<T> Into<Result<T, BlackHole>> for BlackHole {
fn into(self) -> Result<T, BlackHole> {
Err(BlackHole)
}
}
impl Display for BlackHole {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), std::fmt::Error> {
writeln!(formatter, "BlackHole")
}
}
impl<T> From<T> for BlackHole
where
T: Error,
{
fn from(_: T) -> BlackHole {
BlackHole
}
}
pub struct DefaultDebug<T>(pub T);
impl<T> Debug for DefaultDebug<T> {
default fn fmt(&self, formatter: &mut Formatter) -> Result<(), std::fmt::Error> {
match cfg!(verbose) {
true => write!(formatter, "{}", std::any::type_name::<T>()),
false => Ok(()),
}
}
}
impl<T> Debug for DefaultDebug<T>
where
T: Debug,
{
fn fmt(&self, formatter: &mut Formatter) -> Result<(), std::fmt::Error> {
self.0.fmt(formatter)
}
}
impl<T> Deref for DefaultDebug<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> DerefMut for DefaultDebug<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
pub unsafe fn slice_as_array<T, TArray>(data: &[T]) -> Option<&TArray>
where
TArray: AsRef<[T]>,
{
let a = std::mem::size_of::<TArray>();
let b = std::mem::size_of::<T>() * data.len();
match a == b {
true => Some(&*(data.as_ptr() as *const TArray)),
false => None,
}
}
pub fn as_slice<T>(item: &T) -> &[T] {
unsafe { std::slice::from_raw_parts(item, 1) }
}
pub fn as_slice_mut<T>(item: &mut T) -> &mut [T] {
unsafe { std::slice::from_raw_parts_mut(item, 1) }
}
pub fn option_as_slice<T>(value: &Option<T>) -> &[T] {
match value {
Some(x) => as_slice(x),
None => &[],
}
}
pub fn option_as_slice_mut<T>(value: &mut Option<T>) -> &mut [T] {
match value {
Some(x) => as_slice_mut(x),
None => &mut [],
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BitField<TStorage, TAlignment>
where
TStorage: AsRef<[u8]> + AsMut<[u8]>,
{
storage: TStorage,
alignment: [TAlignment; 0],
}
impl<TStorage, TAlignment> BitField<TStorage, TAlignment>
where
TStorage: AsRef<[u8]> + AsMut<[u8]>,
{
#[inline]
pub fn new(storage: TStorage) -> Self {
BitField {
storage,
alignment: [],
}
}
#[inline]
pub fn get(&self, index: usize) -> bool {
let storage = self.storage.as_ref();
debug_assert![storage.len() >= index / 8];
#[rustfmt::skip]
let shift = if cfg!(target_endian = "little") { index % 8 } else { 7 - (index % 8) };
let byte = storage[index / 8];
let mask = 1 << shift;
byte & mask != 0
}
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
let storage = self.storage.as_mut();
debug_assert![storage.len() >= index / 8];
#[rustfmt::skip]
let shift = if cfg!(target_endian = "little") { index % 8 } else { 7 - (index % 8) };
let byte = &mut storage[index / 8];
let mask = 1 << shift;
match value {
true => *byte |= mask,
false => *byte &= !mask,
}
}
#[inline]
pub fn get_value<T>(&self, offset: usize, width: usize) -> T
where
T: From<u64>,
{
let storage = self.storage.as_ref();
debug_assert![width <= 64];
debug_assert![storage.len() > (offset + width) / 8];
let mut value = 0u64;
for i in 0..width {
if self.get(offset + i) {
let shift = if cfg!(target_endian = "big") {
width - i - 1
} else {
i
};
value |= 1 << shift;
}
}
value.into()
}
#[inline]
pub fn set_value<T>(&mut self, offset: usize, width: usize, value: T)
where
T: Into<u64>,
{
let storage = self.storage.as_ref();
let value = Into::<u64>::into(value);
debug_assert![width <= 64];
debug_assert![storage.len() > (offset + width) / 8];
for i in 0..width {
let index = if cfg!(target_endian = "big") {
width - i - 1
} else {
i
};
let mask = 1 << i;
self.set(index + offset, value & mask != 0);
}
}
#[inline]
pub fn value(&self) -> &TStorage {
&self.storage
}
}
pub trait VecExt {
fn clear_vec(&mut self);
}
impl<T> VecExt for Vec<T> {
default fn clear_vec(&mut self) {
self.clear();
}
}
impl<T> VecExt for Vec<T>
where
T: Copy,
{
fn clear_vec(&mut self) {
unsafe {
self.set_len(0);
}
}
}
pub trait BoolExt {
fn as_option(&self) -> Option<()>;
}
impl BoolExt for bool {
fn as_option(&self) -> Option<()> {
match self {
true => Some(()),
false => None,
}
}
}