use std::mem::MaybeUninit;
use crate::{StaticReflect, field_offset, TypeInfo};
#[cfg(feature = "gc")]
use zerogc_derive::Trace;
#[derive(Debug)]
#[repr(C)]
pub struct AsmSlice<T> {
pub ptr: *mut T,
pub len: usize
}
impl<T: StaticReflect> Clone for AsmSlice<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T: StaticReflect> Copy for AsmSlice<T> {}
impl<'a, T: 'a> From<&'a [T]> for AsmSlice<T> {
#[inline]
fn from(slice: &'a [T]) -> Self {
AsmSlice { ptr: slice.as_ptr() as *mut _, len: slice.len() }
}
}
unsafe impl<T: StaticReflect> StaticReflect for AsmSlice<T> {
const TYPE_INFO: TypeInfo<'static> = TypeInfo::Slice {
element_type: &T::TYPE_INFO
};
}
unsafe impl<T: Sync> Send for AsmSlice<T> {}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "gc", derive(Trace))]
#[cfg_attr(feature = "gc", zerogc(nop_trace, copy))]
pub struct AsmStr {
#[cfg_attr(feature = "gc", zerogc(unsafe_skip_trace))]
pub bytes: AsmSlice<u8>
}
impl AsmStr {
#[inline]
pub fn bytes_ptr(&self) -> *mut u8 {
self.bytes.ptr
}
#[inline]
pub fn len(&self) -> usize {
self.bytes.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.bytes.len == 0
}
}
unsafe impl StaticReflect for AsmStr {
const TYPE_INFO: TypeInfo<'static> = TypeInfo::Str;
}
impl<'a> From<&'a str> for AsmStr {
fn from(s: &'a str) -> AsmStr {
AsmStr { bytes: s.as_bytes().into() }
}
}
#[derive(Debug)]
#[repr(C)]
pub struct AsmOption<T> {
present: bool,
value: MaybeUninit<T>
}
impl AsmOption<()> {
#[inline]
pub const fn present_field_offset() -> usize {
assert!(field_offset!(AsmOption::<()>, present) == 0);
0
}
#[inline]
pub const fn value_field_offset(element_type: &TypeInfo<'_>) -> usize {
element_type.alignment()
}
}
impl<T> AsmOption<T> {
#[inline]
pub fn none() -> AsmOption<T> {
AsmOption {
present: false,
value: MaybeUninit::uninit()
}
}
#[inline]
pub fn some(value: T) -> AsmOption<T> {
AsmOption {
present: true,
value: MaybeUninit::new(value)
}
}
#[inline]
pub unsafe fn assume_valid(self) -> Option<T> {
if self.present {
Some(self.value.assume_init())
} else {
None
}
}
#[inline]
pub fn is_present(&self) -> bool {
self.present
}
}
impl<T> From<Option<T>> for AsmOption<T> {
fn from(o: Option<T>) -> AsmOption<T> {
match o {
None => AsmOption::none(),
Some(v) => AsmOption::some(v)
}
}
}
unsafe impl<T: StaticReflect> StaticReflect for AsmOption<T> {
const TYPE_INFO: TypeInfo<'static> = TypeInfo::Optional(&T::TYPE_INFO);
}
unsafe impl<T: Send> Send for AsmOption<T> {}