runtime: make ValueVariant lifetime-generic and add TryFrom<Value> conversions
This commit is contained in:
@@ -50,7 +50,7 @@ impl<'gc> Forced<'gc> for StrictValue<'gc> {
|
|||||||
macro_rules! impl_forced {
|
macro_rules! impl_forced {
|
||||||
($($ty:ty),* $(,)?) => {
|
($($ty:ty),* $(,)?) => {
|
||||||
$(
|
$(
|
||||||
impl<'gc> Forced<'gc> for <$ty as ValueVariant>::Ty<'gc> {
|
impl<'gc> Forced<'gc> for <$ty as ValueVariant<'gc>>::Ty {
|
||||||
const WIDTH: usize = 1;
|
const WIDTH: usize = 1;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
+39
-13
@@ -21,12 +21,12 @@ mod private {
|
|||||||
pub trait Cealed {}
|
pub trait Cealed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ValueVariant: private::Cealed {
|
pub trait ValueVariant<'gc>: private::Cealed {
|
||||||
#[expect(
|
#[expect(
|
||||||
private_bounds,
|
private_bounds,
|
||||||
reason = "Storable is a sealed implementation detail of the value system"
|
reason = "Storable is a sealed implementation detail of the value system"
|
||||||
)]
|
)]
|
||||||
type Ty<'gc>: Storable + 'gc;
|
type Ty: Storable + 'gc;
|
||||||
const TYPE: NixType;
|
const TYPE: NixType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +64,20 @@ macro_rules! define_value_types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl private::Cealed for $itype {}
|
impl private::Cealed for $itype {}
|
||||||
impl ValueVariant for $itype {
|
impl<'gc> ValueVariant<'gc> for $itype {
|
||||||
type Ty<'gc> = $itype;
|
type Ty = $itype;
|
||||||
const TYPE: NixType = $ity;
|
const TYPE: NixType = $ity;
|
||||||
}
|
}
|
||||||
|
impl<'gc> TryFrom<Value<'gc>> for $itype {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(val: Value<'gc>) -> Result<Self, Self::Error> {
|
||||||
|
<Self as Storable>::is(&val.raw)
|
||||||
|
// SAFETY: `is` returned true, so `val.raw` represents a
|
||||||
|
// valid `Self` of this GC type.
|
||||||
|
.then(|| unsafe { <Self as Storable>::from_raw_box(val.raw) })
|
||||||
|
.ok_or(())
|
||||||
|
}
|
||||||
|
}
|
||||||
)*
|
)*
|
||||||
$(
|
$(
|
||||||
impl Storable for Gc<'_, $gtype> {
|
impl Storable for Gc<'_, $gtype> {
|
||||||
@@ -88,10 +98,20 @@ macro_rules! define_value_types {
|
|||||||
unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) }
|
unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'gc> TryFrom<Value<'gc>> for Gc<'gc, unelide_lifetimes!('gc; $gtype)> {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(val: Value<'gc>) -> Result<Self, Self::Error> {
|
||||||
|
<Self as Storable>::is(&val.raw)
|
||||||
|
// SAFETY: `is` returned true, so `val.raw` represents a
|
||||||
|
// valid `Self` of this GC type.
|
||||||
|
.then(|| unsafe { <Self as Storable>::from_raw_box(val.raw) })
|
||||||
|
.ok_or(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl private::Cealed for Gc<'_, $gtype> {}
|
impl private::Cealed for Gc<'_, $gtype> {}
|
||||||
impl private::Cealed for $gtype {}
|
impl private::Cealed for $gtype {}
|
||||||
impl ValueVariant for $gtype {
|
impl<'gc> ValueVariant<'gc> for unelide_lifetimes!('gc; $gtype) {
|
||||||
type Ty<'gc> = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
|
type Ty = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
|
||||||
const TYPE: NixType = $gty;
|
const TYPE: NixType = $gty;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
@@ -199,8 +219,8 @@ impl Storable for f64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueVariant for f64 {
|
impl<'gc> ValueVariant<'gc> for f64 {
|
||||||
type Ty<'gc> = f64;
|
type Ty = f64;
|
||||||
const TYPE: NixType = NixType::Float;
|
const TYPE: NixType = NixType::Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,12 +277,12 @@ impl<'gc> Value<'gc> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is<T: ValueVariant>(self) -> bool {
|
pub fn is<T: ValueVariant<'gc>>(self) -> bool {
|
||||||
T::Ty::is(&self.raw)
|
T::Ty::is(&self.raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'gc>> {
|
pub fn downcast<T: ValueVariant<'gc>>(self) -> Option<T::Ty> {
|
||||||
self.is::<T>()
|
self.is::<T>()
|
||||||
// SAFETY: `is::<T>()` returned true, so `self.raw` represents a
|
// SAFETY: `is::<T>()` returned true, so `self.raw` represents a
|
||||||
// valid `T::Ty`.
|
// valid `T::Ty`.
|
||||||
@@ -332,7 +352,7 @@ impl<'gc> Value<'gc> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn expect<T: ValueVariant>(self) -> Result<T::Ty<'gc>, NixType> {
|
pub fn expect<T: ValueVariant<'gc>>(self) -> Result<T::Ty, NixType> {
|
||||||
self.downcast::<T>().ok_or_else(|| self.ty())
|
self.downcast::<T>().ok_or_else(|| self.ty())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,12 +385,12 @@ impl StaticValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is<T: ValueVariant>(self) -> bool {
|
pub fn is<T: ValueVariant<'static>>(self) -> bool {
|
||||||
self.0.is::<T>()
|
self.0.is::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'static>> {
|
pub fn downcast<T: ValueVariant<'static>>(self) -> Option<T::Ty> {
|
||||||
self.0.downcast::<T>()
|
self.0.downcast::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +716,12 @@ impl<'gc> Deref for StrictValue<'gc> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'gc> From<StrictValue<'gc>> for Value<'gc> {
|
||||||
|
fn from(value: StrictValue<'gc>) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for StrictValue<'_> {
|
impl fmt::Debug for StrictValue<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&self.0, f)
|
fmt::Debug::fmt(&self.0, f)
|
||||||
|
|||||||
Reference in New Issue
Block a user