use std::hint::unreachable_unchecked;
use crate::{
ll::{
gc::{Gc, Memory},
value::{Dict, RawValue, ValueKind},
},
Error, Hidden, Object, UnsafeMutGuard, UnsafeRefGuard, UserData, Value,
};
impl Value {
pub(crate) fn to_raw(&self, gc: &mut Memory) -> RawValue {
match self {
Value::Nil => RawValue::from(()),
Value::False => RawValue::from(false),
Value::True => RawValue::from(true),
Value::Number(x) => RawValue::from(*x),
Value::String(s) => RawValue::from(gc.manage(s)),
Value::Function(f) => RawValue::from(gc.manage(&f.0)),
Value::Struct(s) => RawValue::from(gc.manage(&s.0)),
Value::Trait(t) => RawValue::from(gc.manage(&t.0)),
Value::List(l) => RawValue::from(gc.manage(&l.0)),
Value::Dict(d) => RawValue::from(gc.manage(&d.0)),
Value::UserData(u) => RawValue::from(gc.manage(u)),
}
}
pub(crate) fn to_raw_unmanaged(&self) -> RawValue {
match self {
Value::Nil => RawValue::from(()),
Value::False => RawValue::from(false),
Value::True => RawValue::from(true),
Value::Number(x) => RawValue::from(*x),
Value::String(s) => RawValue::from(Gc::as_raw(s)),
Value::Function(f) => RawValue::from(Gc::as_raw(&f.0)),
Value::Struct(s) => RawValue::from(Gc::as_raw(&s.0)),
Value::Trait(t) => RawValue::from(Gc::as_raw(&t.0)),
Value::List(l) => RawValue::from(Gc::as_raw(&l.0)),
Value::Dict(d) => RawValue::from(Gc::as_raw(&d.0)),
Value::UserData(u) => RawValue::from(Gc::as_raw(u)),
}
}
pub(crate) fn from_raw(raw: RawValue) -> Self {
unsafe {
match raw.kind() {
ValueKind::Nil => Self::new(()),
ValueKind::Boolean => Self::new(raw.get_boolean_unchecked()),
ValueKind::Number => Self::new(*raw.get_number_unchecked()),
ValueKind::String => Self::new(Gc::from_raw(raw.get_raw_string_unchecked())),
ValueKind::Function => {
Self::Function(Hidden(Gc::from_raw(raw.get_raw_function_unchecked())))
}
ValueKind::Struct => {
Self::Struct(Hidden(Gc::from_raw(raw.get_raw_struct_unchecked())))
}
ValueKind::Trait => {
Self::Trait(Hidden(Gc::from_raw(raw.get_raw_trait_unchecked())))
}
ValueKind::List => Self::List(Hidden(Gc::from_raw(raw.get_raw_list_unchecked()))),
ValueKind::Dict => Self::Dict(Hidden(Gc::from_raw(raw.get_raw_dict_unchecked()))),
ValueKind::UserData => {
Self::UserData(Gc::from_raw(raw.get_raw_user_data_unchecked()))
}
}
}
}
}
pub trait SelfFromRawValue {
type Guard;
unsafe fn self_from_raw_value(value: &RawValue) -> Result<(&Self, Self::Guard), Error>;
}
impl SelfFromRawValue for () {
type Guard = ();
unsafe fn self_from_raw_value(_: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((&(), ()))
}
}
impl SelfFromRawValue for bool {
type Guard = ();
unsafe fn self_from_raw_value(v: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((
match v.get_boolean_unchecked() {
true => &true,
false => &false,
},
(),
))
}
}
impl SelfFromRawValue for f64 {
type Guard = ();
unsafe fn self_from_raw_value(v: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((v.get_number_unchecked(), ()))
}
}
impl SelfFromRawValue for String {
type Guard = ();
unsafe fn self_from_raw_value(v: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((v.get_raw_string_unchecked().get(), ()))
}
}
impl SelfFromRawValue for Vec<RawValue> {
type Guard = ();
unsafe fn self_from_raw_value(v: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((&*v.get_raw_list_unchecked().get().get_mut(), ()))
}
}
impl SelfFromRawValue for Dict {
type Guard = ();
unsafe fn self_from_raw_value(v: &RawValue) -> Result<(&Self, Self::Guard), Error> {
Ok((v.get_raw_dict_unchecked().get(), ()))
}
}
impl<T> SelfFromRawValue for T
where
T: UserData,
{
type Guard = UnsafeRefGuard<T>;
unsafe fn self_from_raw_value(value: &RawValue) -> Result<(&Self, Self::Guard), Error> {
let user_data = value.get_raw_user_data_unchecked().get();
if let Some(object) = user_data.as_any().downcast_ref::<Object<T>>() {
object.unsafe_borrow()
} else {
unreachable_unchecked()
}
}
}
pub trait MutSelfFromRawValue
where
Self: Sized,
{
type Guard;
unsafe fn mut_self_from_raw_value(value: &RawValue) -> Result<(&mut Self, Self::Guard), Error>;
}
impl MutSelfFromRawValue for Vec<RawValue> {
type Guard = ();
unsafe fn mut_self_from_raw_value(v: &RawValue) -> Result<(&mut Self, Self::Guard), Error> {
Ok((&mut *v.get_raw_list_unchecked().get().get_mut(), ()))
}
}
impl<T> MutSelfFromRawValue for T
where
T: UserData,
{
type Guard = UnsafeMutGuard<T>;
unsafe fn mut_self_from_raw_value(value: &RawValue) -> Result<(&mut Self, Self::Guard), Error> {
let user_data = value.get_raw_user_data_unchecked().get();
if let Some(object) = user_data.as_any().downcast_ref::<Object<T>>() {
object.unsafe_borrow_mut()
} else {
unreachable_unchecked()
}
}
}