#![doc(html_root_url = "https://docs.rs/high_mem_utils/0.2.7/")]
#![feature(vec_leak, untagged_unions, const_fn, const_fn_union)]
#![allow(unused_unsafe, clippy::wrong_self_convention, clippy::map_entry)]
use core::mem::{take, ManuallyDrop, MaybeUninit, forget, align_of};
use core::ops::{Deref, DerefMut};
use core::fmt::{Debug, Pointer};
use core::hash::Hash;
use core::ptr::NonNull;
use std::collections::BTreeMap;
use fast_new_type::new_type;
pub unsafe trait RawPointer<T: ?Sized>: Copy + Clone + Pointer + Debug + PartialEq + Eq + Hash + PartialOrd + Ord + Unpin {}
unsafe impl<T: ?Sized> RawPointer<T> for *const T {}
unsafe impl<T: ?Sized> RawPointer<T> for *mut T {}
unsafe impl<T: ?Sized> RawPointer<T> for NonNull<T> {}
#[repr(packed)]
union Ptr<T, U: RawPointer<T>> {
address: usize,
ptr: U,
p: core::marker::PhantomData<T>
}
#[inline]
pub const fn dangling<T, U: RawPointer<T>>() -> U {
unsafe { Ptr { address: align_of::<T>() }.ptr }
}
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};
#[macro_export]
macro_rules! unreachable_debug {
() => { unreachable!("entered unreachable code") };
($e:expr) => {
if cfg!(not(debug_assertions)) {
unsafe { std::hint::unreachable_unchecked() };
} else {
panic!($e);
}
}
}
pub union Catch<'a, T: ?Sized> {
leaked: &'a mut T,
sealed: ManuallyDrop<Box<T>>,
}
impl<'a, U> Catch<'a, [U]> {
pub fn new_seq(a: Vec<U>) -> Self {
Catch {
leaked: Vec::leak(a),
}
}
pub fn leaked(&self) -> &&'a mut [U] {
unsafe { &self.leaked }
}
pub fn seal(self) -> Vec<U> {
unsafe { ManuallyDrop::into_inner(self.sealed).into_vec() }
}
pub fn leak(self) -> &'a mut [U] {
unsafe { self.leaked }
}
pub unsafe fn from_leaked(leaked: &'a mut [U]) -> Self {
Catch { leaked }
}
}
impl<'a> Catch<'a, str> {
pub fn new_str(a: String) -> Self {
Catch {
leaked: Box::leak(a.into_boxed_str()),
}
}
pub fn leaked(&self) -> &&'a mut str {
unsafe { &self.leaked }
}
pub fn seal(self) -> String {
unsafe { ManuallyDrop::into_inner(self.sealed).into_string() }
}
pub fn leak(self) -> &'a mut str {
unsafe { self.leaked }
}
pub unsafe fn from_leaked(leaked: &'a mut str) -> Self {
Catch { leaked }
}
}
impl<'a, T> Catch<'a, T> {
pub fn new(a: Box<T>) -> Self {
Catch {
leaked: Box::leak(a),
}
}
pub fn leaked(&self) -> &&'a mut T {
unsafe { &self.leaked }
}
pub fn sealed(&mut self) -> &mut ManuallyDrop<Box<T>> {
unsafe { &mut self.sealed }
}
pub fn seal(self) -> Box<T> {
unsafe { ManuallyDrop::into_inner(self.sealed) }
}
pub fn leak(self) -> &'a mut T {
unsafe { self.leaked }
}
pub unsafe fn from_leaked(leaked: &'a mut T) -> Self {
Catch { leaked }
}
}
impl<'a, T: Default> Catch<'a, T> {
pub fn take(&mut self) -> Box<T> {
let tmp = unsafe { ManuallyDrop::take(&mut self.sealed) };
let ptr = self as *mut Self;
unsafe { ptr.write( Self::new(Box::new(T::default())) ); }
tmp
}
}
#[deprecated(since = "0.2.5", note = "Catch has implementations for serve the same functionality")]
pub union CatchSeq<'a, T> {
leaked: &'a mut [T],
sealed: ManuallyDrop<Box<[T]>>,
}
#[allow(deprecated)]
impl<'a, T> CatchSeq<'a, T> {
pub fn new(a: Vec<T>) -> Self {
CatchSeq {
leaked: Vec::leak(a),
}
}
pub fn leaked(&self) -> &&'a mut [T] {
unsafe { &self.leaked }
}
pub fn seal(self) -> Vec<T> {
unsafe { ManuallyDrop::into_inner(self.sealed).into_vec() }
}
pub fn leak(self) -> &'a mut [T] {
unsafe { self.leaked }
}
pub unsafe fn from_leaked(leaked: &'a mut [T]) -> Self {
CatchSeq { leaked }
}
}
#[deprecated(since = "0.2.5", note = "Catch has implementations for serve the same functionality")]
pub union CatchStr<'a> {
leaked: &'a mut str,
sealed: ManuallyDrop<Box<str>>,
}
#[allow(deprecated)]
impl<'a> CatchStr<'a> {
pub fn new(a: String) -> Self {
CatchStr {
leaked: Box::leak(a.into_boxed_str()),
}
}
pub fn leaked(&self) -> &&'a mut str {
unsafe { &self.leaked }
}
pub fn seal(self) -> String {
unsafe { ManuallyDrop::into_inner(self.sealed).into_string() }
}
pub fn leak(self) -> &'a mut str {
unsafe { self.leaked }
}
pub unsafe fn from_leaked(leaked: &'a mut str) -> Self {
CatchStr { leaked }
}
}
#[deprecated(since = "0.2.4", note = "Use ManuallyDrop or DontDropOpt if you want to take the value and reuse the container,instead.")]
#[repr(transparent)]
pub struct DontDrop<T: Default>(pub T);
#[allow(deprecated)]
impl<T: Default> DontDrop<T> {
pub fn into_inner(&mut self) -> T {
take(&mut self.0)
}
}
#[allow(deprecated)]
impl<T: Default> Deref for DontDrop<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[allow(deprecated)]
impl<T: Default> DerefMut for DontDrop<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[allow(deprecated)]
impl<T: Default> Drop for DontDrop<T> {
fn drop(&mut self) {
forget(take(&mut self.0));
}
}
#[repr(transparent)]
#[new_type]
pub struct DontDropOpt<T>(Option<T>);
impl<T> DontDropOpt<T> {
pub fn new(a: T) -> Self {
DontDropOpt(Some(a))
}
pub fn into_inner(&mut self) -> Option<T> {
self.0.take()
}
pub fn forget(&mut self) {
forget((&mut self.0).take())
}
pub fn set(&mut self, value: T) {
self.0 = Some(value)
}
pub unsafe fn into_inner_unchecked(&mut self) -> T {
self.0.take().unwrap_or_else(|| unreachable_debug!("Called into_inner_unchecked with None value on DontDropOpt in debug."))
}
}
impl<T> Drop for DontDropOpt<T> {
fn drop(&mut self) {
self.forget()
}
}
#[new_type]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct DropBy<T, F: FnMut(T)> {
pub value: Option<T>,
pub clos: F
}
impl<T, F: FnMut(T)> DropBy<T, F> {
pub const fn new(value: T, clos: F) -> Self {
let value = Some(value);
DropBy { value, clos }
}
pub fn into_inner(&mut self) -> Option<T> {
self.value.take()
}
pub fn drop_by(&mut self) {
let value = match self.value.take() {
Some(a) => a,
None => return,
};
(self.clos)(value)
}
pub fn set(&mut self, value: T) {
self.value = Some(value)
}
pub unsafe fn into_inner_unchecked(&mut self) -> T {
self.value.take().unwrap_or_else(|| unreachable_debug!("Called into_inner_unchecked with None value on DropBy in debug."))
}
}
impl<T, F: FnMut(T)> Drop for DropBy<T, F> {
fn drop(&mut self) {
self.drop_by()
}
}
#[deprecated(since = "0.2.5", note = "Catch has implementations for serve the same functionality of the other variants")]
pub enum CatchT<'a, T> {
Catch(Catch<'a, T>),
#[allow(deprecated)]
CatchSeq(CatchSeq<'a, T>),
#[allow(deprecated)]
CatchStr(CatchStr<'a>),
}
pub struct LazyCache<P: Ord, V: Clone, C: Fn(P) -> V> {
cache: MaybeUninit<BTreeMap<P, V>>,
pub closure: C,
init: bool
}
impl<P: Ord + Clone, V: Clone, C: Fn(P) -> V> LazyCache<P, V, C> {
pub const fn new(closure: C) -> Self {
Self {cache: MaybeUninit::uninit(), closure, init: false}
}
pub const fn with_cache(cache: BTreeMap<P, V>, closure: C) -> Self {
Self {cache: MaybeUninit::new(cache), closure, init: true }
}
pub const unsafe fn with_cache_unchecked(cache: MaybeUninit<BTreeMap<P, V>>, closure: C, init: bool) -> Self {
Self {cache, closure, init}
}
fn init(&mut self) {
unsafe {
self.cache.as_mut_ptr().write(BTreeMap::new());
self.init = true;
}
}
pub fn call_cache(&mut self, arg: P) -> V {
if !self.init {
self.init();
}
let mut_ref = unsafe { &mut *self.cache.as_mut_ptr() };
if mut_ref.contains_key(&arg) {
(mut_ref.get(&arg).unwrap()).clone()
} else {
let temp = (self.closure)(arg.clone());
mut_ref.insert(arg, temp.clone());
temp
}
}
pub fn pop(&mut self, arg: &P) -> Option<V> {
if !self.init {
return None;
}
(unsafe { &mut *self.cache.as_mut_ptr() }).remove(arg)
}
pub fn clear(&mut self) {
if !self.init {
return;
}
(unsafe { &mut *self.cache.as_mut_ptr() }).clear();
}
pub fn is_init(&self) -> bool {
self.init
}
pub fn is_empty(&self) -> bool {
if self.init {
(unsafe { &*self.cache.as_ptr() }).is_empty()
} else {
true
}
}
pub fn cache<F: Fn(&mut BTreeMap<P, V>)>(&mut self, f: F) {
if !self.init {
self.init();
}
unsafe {
f(&mut *self.cache.as_mut_ptr());
}
}
}
impl<P: Ord, V: Clone, C: Fn(P) -> V> Drop for LazyCache<P, V, C> {
fn drop(&mut self) {
if self.init {
unsafe { self.cache.as_mut_ptr().drop_in_place() }
}
}
}