use std::convert::Infallible;
use std::fmt;
use std::fmt::Formatter;
use std::mem;
use std::ops::Deref;
use allocative::Allocative;
use dupe::Clone_;
use dupe::Copy_;
use dupe::Dupe;
use dupe::Dupe_;
use crate::values::FrozenHeap;
use crate::values::FrozenHeapRef;
use crate::values::FrozenRef;
#[derive(Copy_, Clone_, Dupe_)]
pub struct OwnedRefFrozenRef<'f, T: ?Sized + 'static> {
owner: &'f FrozenHeapRef,
value: FrozenRef<'f, T>,
}
#[derive(Clone, Dupe, Allocative)]
pub struct OwnedFrozenRef<T: ?Sized + 'static> {
owner: FrozenHeapRef,
value: FrozenRef<'static, T>,
}
impl<'f, T: ?Sized> OwnedRefFrozenRef<'f, T> {
pub unsafe fn new_unchecked(
value: &'f T,
owner: &'f FrozenHeapRef,
) -> OwnedRefFrozenRef<'f, T> {
OwnedRefFrozenRef {
owner,
value: FrozenRef::new(value),
}
}
pub fn owner(&self) -> &'f FrozenHeapRef {
self.owner
}
pub fn as_ref(self) -> &'f T {
self.value.as_ref()
}
pub fn add_heap_ref<'v>(self, heap: &'v FrozenHeap) -> &'v T {
heap.add_reference(self.owner);
unsafe { mem::transmute::<&'f T, &'v T>(self.value.as_ref()) }
}
pub fn to_owned(self) -> OwnedFrozenRef<T> {
OwnedFrozenRef {
owner: self.owner.dupe(),
value: unsafe { mem::transmute::<FrozenRef<'f, T>, FrozenRef<'static, T>>(self.value) },
}
}
pub fn try_map_result<F, U: ?Sized, E>(self, f: F) -> Result<OwnedRefFrozenRef<'f, U>, E>
where
F: FnOnce(&'f T) -> Result<&'f U, E>,
{
Ok(OwnedRefFrozenRef {
owner: self.owner,
value: FrozenRef::new(f(self.value.as_ref())?),
})
}
pub fn map<F, U: ?Sized>(self, f: F) -> OwnedRefFrozenRef<'f, U>
where
F: FnOnce(&'f T) -> &'f U,
{
match self.try_map_result(|x| Ok(f(x))) {
Ok(x) => x,
Err(e) => {
let e: Infallible = e;
match e {}
}
}
}
pub fn try_map_option<F, U: ?Sized>(self, f: F) -> Option<OwnedRefFrozenRef<'f, U>>
where
F: FnOnce(&'f T) -> Option<&'f U>,
{
match self.try_map_result(|x| f(x).ok_or(())) {
Ok(x) => Some(x),
Err(()) => None,
}
}
}
impl<T: ?Sized> OwnedFrozenRef<T> {
pub unsafe fn new_unchecked(value: &'static T, owner: FrozenHeapRef) -> OwnedFrozenRef<T> {
OwnedFrozenRef {
owner,
value: FrozenRef::new(value),
}
}
pub fn as_owned_ref_frozen_ref(&self) -> OwnedRefFrozenRef<'_, T> {
OwnedRefFrozenRef {
owner: &self.owner,
value: self.value,
}
}
pub fn as_ref<'a>(&'a self) -> &'a T {
self.as_owned_ref_frozen_ref().as_ref()
}
pub fn map<F, U: ?Sized>(self, f: F) -> OwnedFrozenRef<U>
where
for<'v> F: FnOnce(&'v T) -> &'v U,
{
OwnedFrozenRef {
owner: self.owner,
value: self.value.map(f),
}
}
pub fn try_map_result<F, U: ?Sized, E>(self, f: F) -> Result<OwnedFrozenRef<U>, E>
where
for<'v> F: FnOnce(&'v T) -> Result<&'v U, E>,
{
Ok(OwnedFrozenRef {
owner: self.owner,
value: self.value.try_map_result(f)?,
})
}
pub fn try_map_option<F, U: ?Sized>(self, f: F) -> Option<OwnedFrozenRef<U>>
where
for<'v> F: FnOnce(&'v T) -> Option<&'v U>,
{
Some(OwnedFrozenRef {
owner: self.owner,
value: self.value.try_map_option(f)?,
})
}
pub fn owner(&self) -> &FrozenHeapRef {
&self.owner
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for OwnedFrozenRef<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.value, f)
}
}
impl<T: ?Sized + fmt::Display> fmt::Display for OwnedFrozenRef<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.value, f)
}
}
impl<T: ?Sized> Deref for OwnedFrozenRef<T> {
type Target = T;
fn deref(&self) -> &T {
self.as_ref()
}
}