use core::mem::{ManuallyDrop, size_of};
use core::ptr::{self, NonNull};
use crate::handle::RawHandle;
use crate::state::GlobalState;
use crate::value::{RawTValue, TValue, TValueCursor};
#[repr(C)]
pub struct RawUpVal {
pub tt: u8,
pub marked: u8,
pub memcat: u8,
pub marked_open: u8,
pub value: *mut RawTValue,
pub data: RawUpValData,
}
#[repr(C)]
pub struct RawUpValOpen {
pub prev: *mut RawUpVal,
pub next: *mut RawUpVal,
pub thread_next: *mut RawUpVal,
}
#[repr(C)]
pub union RawUpValData {
pub value: ManuallyDrop<RawTValue>,
pub open: ManuallyDrop<RawUpValOpen>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct UpVal {
raw: NonNull<RawUpVal>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct UpValOpen {
raw: NonNull<RawUpValOpen>,
}
#[allow(
clippy::missing_safety_doc,
reason = "UpVal's shared raw-handle contract is documented on UpVal"
)]
impl UpVal {
pub const fn allocation_size() -> usize {
size_of::<RawUpVal>()
}
pub const unsafe fn from_raw(raw: NonNull<RawUpVal>) -> Self {
Self { raw }
}
pub unsafe fn from_ref(raw: &RawUpVal) -> Self {
Self {
raw: NonNull::from(raw),
}
}
pub unsafe fn open_data(&self) -> UpValOpen {
unsafe {
UpValOpen::from_raw(NonNull::new_unchecked(
(&raw mut (*self.as_ptr()).data.open).cast::<RawUpValOpen>(),
))
}
}
pub unsafe fn value_ptr(&self) -> *mut RawTValue {
unsafe { self.as_ptr().as_ref().unwrap_unchecked().value }
}
pub unsafe fn value(&self) -> TValue {
unsafe { TValue::from_raw(NonNull::new_unchecked(self.value_ptr())) }
}
pub unsafe fn closed_value(&self) -> TValue {
unsafe {
TValue::from_raw(NonNull::new_unchecked(
(&raw mut (*self.as_ptr()).data.value).cast::<RawTValue>(),
))
}
}
pub unsafe fn set_value(&self, value: TValue) {
unsafe {
(*self.as_ptr()).value = value.as_ptr();
}
}
pub unsafe fn rebase_value(&self, old_stack: TValueCursor, new_stack: TValueCursor) {
debug_assert!(unsafe { self.is_open() });
unsafe {
let value = TValueCursor::from_ptr(self.value_ptr());
let value_offset = value.addr_offset_from(old_stack) as usize;
(*self.as_ptr()).value = new_stack.add(value_offset).as_ptr();
}
}
pub unsafe fn close(&self) {
unsafe {
let closed_value = self.closed_value();
closed_value.set_obj(self.value());
self.set_value(closed_value);
}
}
pub unsafe fn is_open(&self) -> bool {
let closed_value = unsafe { (&raw const (*self.as_ptr()).data.value).cast::<RawTValue>() };
!core::ptr::eq(unsafe { self.value_ptr() }.cast_const(), closed_value)
}
}
#[allow(
clippy::missing_safety_doc,
reason = "UpValOpen's shared raw-view contract is documented on UpValOpen"
)]
impl UpValOpen {
pub const unsafe fn from_raw(raw: NonNull<RawUpValOpen>) -> Self {
Self { raw }
}
pub unsafe fn prev(&self) -> UpVal {
unsafe {
UpVal::from_raw(NonNull::new_unchecked(
self.as_ptr().as_ref().unwrap_unchecked().prev,
))
}
}
pub unsafe fn set_prev(&self, prev: UpVal) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().prev = prev.as_ptr();
}
}
pub unsafe fn next(&self) -> UpVal {
unsafe {
UpVal::from_raw(NonNull::new_unchecked(
self.as_ptr().as_ref().unwrap_unchecked().next,
))
}
}
pub unsafe fn set_next(&self, next: UpVal) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().next = next.as_ptr();
}
}
pub unsafe fn thread_next(&self) -> Option<UpVal> {
unsafe {
NonNull::new(self.as_ptr().as_ref().unwrap_unchecked().thread_next)
.map(|upvalue| UpVal::from_raw(upvalue))
}
}
pub unsafe fn set_thread_next(&self, thread_next: Option<UpVal>) {
unsafe {
self.as_ptr().as_mut().unwrap_unchecked().thread_next =
thread_next.map_or(ptr::null_mut(), |upvalue| upvalue.as_ptr());
}
}
}
#[allow(
clippy::missing_safety_doc,
reason = "GlobalState's shared raw-handle contract is documented on GlobalState"
)]
impl GlobalState {
pub unsafe fn uv_head(&self) -> UpVal {
unsafe { UpVal::from_raw(NonNull::new_unchecked(&raw mut (*self.as_ptr()).uv_head)) }
}
}
impl crate::handle::sealed::Sealed for UpVal {}
impl crate::handle::sealed::Sealed for UpValOpen {}
impl RawHandle for UpVal {
type Raw = RawUpVal;
fn as_ptr(&self) -> *mut Self::Raw {
self.raw.as_ptr()
}
}
impl AsRef<UpVal> for UpVal {
fn as_ref(&self) -> &UpVal {
self
}
}
impl RawHandle for UpValOpen {
type Raw = RawUpValOpen;
fn as_ptr(&self) -> *mut Self::Raw {
self.raw.as_ptr()
}
}
impl AsRef<UpValOpen> for UpValOpen {
fn as_ref(&self) -> &UpValOpen {
self
}
}