diff --git a/fix-runtime/src/forced.rs b/fix-runtime/src/forced.rs index 7b3cf1c..6c4cdbe 100644 --- a/fix-runtime/src/forced.rs +++ b/fix-runtime/src/forced.rs @@ -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)] diff --git a/fix-runtime/src/value.rs b/fix-runtime/src/value.rs index 2fee91c..7945ebb 100644 --- a/fix-runtime/src/value.rs +++ b/fix-runtime/src/value.rs @@ -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> for $itype { + type Error = (); + fn try_from(val: Value<'gc>) -> Result { + ::is(&val.raw) + // SAFETY: `is` returned true, so `val.raw` represents a + // valid `Self` of this GC type. + .then(|| unsafe { ::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> for Gc<'gc, unelide_lifetimes!('gc; $gtype)> { + type Error = (); + fn try_from(val: Value<'gc>) -> Result { + ::is(&val.raw) + // SAFETY: `is` returned true, so `val.raw` represents a + // valid `Self` of this GC type. + .then(|| unsafe { ::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(self) -> bool { + pub fn is>(self) -> bool { T::Ty::is(&self.raw) } #[inline] - pub fn downcast(self) -> Option> { + pub fn downcast>(self) -> Option { self.is::() // SAFETY: `is::()` returned true, so `self.raw` represents a // valid `T::Ty`. @@ -332,7 +352,7 @@ impl<'gc> Value<'gc> { } #[inline] - pub fn expect(self) -> Result, NixType> { + pub fn expect>(self) -> Result { self.downcast::().ok_or_else(|| self.ty()) } @@ -365,12 +385,12 @@ impl StaticValue { } #[inline] - pub fn is(self) -> bool { + pub fn is>(self) -> bool { self.0.is::() } #[inline] - pub fn downcast(self) -> Option> { + pub fn downcast>(self) -> Option { self.0.downcast::() } @@ -696,6 +716,12 @@ impl<'gc> Deref for StrictValue<'gc> { } } +impl<'gc> From> 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)