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 {
|
||||
($($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;
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
+39
-13
@@ -21,12 +21,12 @@ mod private {
|
||||
pub trait Cealed {}
|
||||
}
|
||||
|
||||
pub trait ValueVariant: private::Cealed {
|
||||
pub trait ValueVariant<'gc>: private::Cealed {
|
||||
#[expect(
|
||||
private_bounds,
|
||||
reason = "Storable is a sealed implementation detail of the value system"
|
||||
)]
|
||||
type Ty<'gc>: Storable + 'gc;
|
||||
type Ty: Storable + 'gc;
|
||||
const TYPE: NixType;
|
||||
}
|
||||
|
||||
@@ -64,10 +64,20 @@ macro_rules! define_value_types {
|
||||
}
|
||||
}
|
||||
impl private::Cealed for $itype {}
|
||||
impl ValueVariant for $itype {
|
||||
type Ty<'gc> = $itype;
|
||||
impl<'gc> ValueVariant<'gc> for $itype {
|
||||
type Ty = $itype;
|
||||
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> {
|
||||
@@ -88,10 +98,20 @@ macro_rules! define_value_types {
|
||||
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 $gtype {}
|
||||
impl ValueVariant for $gtype {
|
||||
type Ty<'gc> = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
|
||||
impl<'gc> ValueVariant<'gc> for unelide_lifetimes!('gc; $gtype) {
|
||||
type Ty = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
|
||||
const TYPE: NixType = $gty;
|
||||
}
|
||||
)*
|
||||
@@ -199,8 +219,8 @@ impl Storable for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueVariant for f64 {
|
||||
type Ty<'gc> = f64;
|
||||
impl<'gc> ValueVariant<'gc> for f64 {
|
||||
type Ty = f64;
|
||||
const TYPE: NixType = NixType::Float;
|
||||
}
|
||||
|
||||
@@ -257,12 +277,12 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is<T: ValueVariant>(self) -> bool {
|
||||
pub fn is<T: ValueVariant<'gc>>(self) -> bool {
|
||||
T::Ty::is(&self.raw)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'gc>> {
|
||||
pub fn downcast<T: ValueVariant<'gc>>(self) -> Option<T::Ty> {
|
||||
self.is::<T>()
|
||||
// SAFETY: `is::<T>()` returned true, so `self.raw` represents a
|
||||
// valid `T::Ty`.
|
||||
@@ -332,7 +352,7 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
|
||||
#[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())
|
||||
}
|
||||
|
||||
@@ -365,12 +385,12 @@ impl StaticValue {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is<T: ValueVariant>(self) -> bool {
|
||||
pub fn is<T: ValueVariant<'static>>(self) -> bool {
|
||||
self.0.is::<T>()
|
||||
}
|
||||
|
||||
#[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>()
|
||||
}
|
||||
|
||||
@@ -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<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
|
||||
Reference in New Issue
Block a user