@@ -335,6 +335,25 @@ impl Type {
335335 self . is_subtype ( types:: NilClass ) || self . is_subtype ( types:: FalseClass )
336336 }
337337
338+ pub fn has_value ( & self , val : Const ) -> bool {
339+ match ( self . spec , val) {
340+ ( Specialization :: Object ( v1) , Const :: Value ( v2) ) => v1 == v2,
341+ ( Specialization :: Int ( v1) , Const :: CBool ( v2) ) if self . is_subtype ( types:: CBool ) => v1 == ( v2 as u64 ) ,
342+ ( Specialization :: Int ( v1) , Const :: CInt8 ( v2) ) if self . is_subtype ( types:: CInt8 ) => v1 == ( v2 as u64 ) ,
343+ ( Specialization :: Int ( v1) , Const :: CInt16 ( v2) ) if self . is_subtype ( types:: CInt16 ) => v1 == ( v2 as u64 ) ,
344+ ( Specialization :: Int ( v1) , Const :: CInt32 ( v2) ) if self . is_subtype ( types:: CInt32 ) => v1 == ( v2 as u64 ) ,
345+ ( Specialization :: Int ( v1) , Const :: CInt64 ( v2) ) if self . is_subtype ( types:: CInt64 ) => v1 == ( v2 as u64 ) ,
346+ ( Specialization :: Int ( v1) , Const :: CUInt8 ( v2) ) if self . is_subtype ( types:: CUInt8 ) => v1 == ( v2 as u64 ) ,
347+ ( Specialization :: Int ( v1) , Const :: CUInt16 ( v2) ) if self . is_subtype ( types:: CUInt16 ) => v1 == ( v2 as u64 ) ,
348+ ( Specialization :: Int ( v1) , Const :: CUInt32 ( v2) ) if self . is_subtype ( types:: CUInt32 ) => v1 == ( v2 as u64 ) ,
349+ ( Specialization :: Int ( v1) , Const :: CShape ( v2) ) if self . is_subtype ( types:: CShape ) => v1 == ( v2. 0 as u64 ) ,
350+ ( Specialization :: Int ( v1) , Const :: CUInt64 ( v2) ) if self . is_subtype ( types:: CUInt64 ) => v1 == v2,
351+ ( Specialization :: Int ( v1) , Const :: CPtr ( v2) ) if self . is_subtype ( types:: CPtr ) => v1 == ( v2 as u64 ) ,
352+ ( Specialization :: Double ( v1) , Const :: CDouble ( v2) ) => v1. to_bits ( ) == v2. to_bits ( ) ,
353+ _ => false ,
354+ }
355+ }
356+
338357 /// Return the object specialization, if any.
339358 pub fn ruby_object ( & self ) -> Option < VALUE > {
340359 match self . spec {
@@ -958,4 +977,80 @@ mod tests {
958977 assert_bit_equal ( d_instance. union ( c_instance) , Type { bits : bits:: ObjectSubclass , spec : Specialization :: Type ( c_class) } ) ;
959978 } ) ;
960979 }
980+
981+ #[ test]
982+ fn has_value ( ) {
983+ // With known values
984+ crate :: cruby:: with_rubyvm ( || {
985+ let a = rust_str_to_sym ( "a" ) ;
986+ let b = rust_str_to_sym ( "b" ) ;
987+ let ty = Type :: from_value ( a) ;
988+ assert ! ( ty. has_value( Const :: Value ( a) ) ) ;
989+ assert ! ( !ty. has_value( Const :: Value ( b) ) ) ;
990+ } ) ;
991+
992+ let true_ty = Type :: from_cbool ( true ) ;
993+ assert ! ( true_ty. has_value( Const :: CBool ( true ) ) ) ;
994+ assert ! ( !true_ty. has_value( Const :: CBool ( false ) ) ) ;
995+
996+ let int8_ty = Type :: from_cint ( types:: CInt8 , 42 ) ;
997+ assert ! ( int8_ty. has_value( Const :: CInt8 ( 42 ) ) ) ;
998+ assert ! ( !int8_ty. has_value( Const :: CInt8 ( -1 ) ) ) ;
999+ let neg_int8_ty = Type :: from_cint ( types:: CInt8 , -1 ) ;
1000+ assert ! ( neg_int8_ty. has_value( Const :: CInt8 ( -1 ) ) ) ;
1001+
1002+ let int16_ty = Type :: from_cint ( types:: CInt16 , 1000 ) ;
1003+ assert ! ( int16_ty. has_value( Const :: CInt16 ( 1000 ) ) ) ;
1004+ assert ! ( !int16_ty. has_value( Const :: CInt16 ( 2000 ) ) ) ;
1005+
1006+ let int32_ty = Type :: from_cint ( types:: CInt32 , 100000 ) ;
1007+ assert ! ( int32_ty. has_value( Const :: CInt32 ( 100000 ) ) ) ;
1008+ assert ! ( !int32_ty. has_value( Const :: CInt32 ( -100000 ) ) ) ;
1009+
1010+ let int64_ty = Type :: from_cint ( types:: CInt64 , i64:: MAX ) ;
1011+ assert ! ( int64_ty. has_value( Const :: CInt64 ( i64 :: MAX ) ) ) ;
1012+ assert ! ( !int64_ty. has_value( Const :: CInt64 ( 0 ) ) ) ;
1013+
1014+ let uint8_ty = Type :: from_cint ( types:: CUInt8 , u8:: MAX as i64 ) ;
1015+ assert ! ( uint8_ty. has_value( Const :: CUInt8 ( u8 :: MAX ) ) ) ;
1016+ assert ! ( !uint8_ty. has_value( Const :: CUInt8 ( 0 ) ) ) ;
1017+
1018+ let uint16_ty = Type :: from_cint ( types:: CUInt16 , u16:: MAX as i64 ) ;
1019+ assert ! ( uint16_ty. has_value( Const :: CUInt16 ( u16 :: MAX ) ) ) ;
1020+ assert ! ( !uint16_ty. has_value( Const :: CUInt16 ( 1 ) ) ) ;
1021+
1022+ let uint32_ty = Type :: from_cint ( types:: CUInt32 , u32:: MAX as i64 ) ;
1023+ assert ! ( uint32_ty. has_value( Const :: CUInt32 ( u32 :: MAX ) ) ) ;
1024+ assert ! ( !uint32_ty. has_value( Const :: CUInt32 ( 42 ) ) ) ;
1025+
1026+ let uint64_ty = Type :: from_cint ( types:: CUInt64 , i64:: MAX ) ;
1027+ assert ! ( uint64_ty. has_value( Const :: CUInt64 ( i64 :: MAX as u64 ) ) ) ;
1028+ assert ! ( !uint64_ty. has_value( Const :: CUInt64 ( 123 ) ) ) ;
1029+
1030+ let shape_ty = Type :: from_cint ( types:: CShape , 0x1234 ) ;
1031+ assert ! ( shape_ty. has_value( Const :: CShape ( crate :: cruby:: ShapeId ( 0x1234 ) ) ) ) ;
1032+ assert ! ( !shape_ty. has_value( Const :: CShape ( crate :: cruby:: ShapeId ( 0x5678 ) ) ) ) ;
1033+
1034+ let ptr = 0x1000 as * const u8 ;
1035+ let ptr_ty = Type :: from_cptr ( ptr) ;
1036+ assert ! ( ptr_ty. has_value( Const :: CPtr ( ptr) ) ) ;
1037+ assert ! ( !ptr_ty. has_value( Const :: CPtr ( 0x2000 as * const u8 ) ) ) ;
1038+
1039+ let double_ty = Type :: from_double ( std:: f64:: consts:: PI ) ;
1040+ assert ! ( double_ty. has_value( Const :: CDouble ( std:: f64 :: consts:: PI ) ) ) ;
1041+ assert ! ( !double_ty. has_value( Const :: CDouble ( 3.123 ) ) ) ;
1042+
1043+ let nan_ty = Type :: from_double ( f64:: NAN ) ;
1044+ assert ! ( nan_ty. has_value( Const :: CDouble ( f64 :: NAN ) ) ) ;
1045+
1046+ // Mismatched types
1047+ assert ! ( !int8_ty. has_value( Const :: CInt16 ( 42 ) ) ) ;
1048+ assert ! ( !int16_ty. has_value( Const :: CInt32 ( 1000 ) ) ) ;
1049+ assert ! ( !uint8_ty. has_value( Const :: CInt8 ( -1i8 ) ) ) ;
1050+
1051+ // Wrong specialization (unknown value)
1052+ assert ! ( !types:: CInt8 . has_value( Const :: CInt8 ( 42 ) ) ) ;
1053+ assert ! ( !types:: CBool . has_value( Const :: CBool ( true ) ) ) ;
1054+ assert ! ( !types:: CShape . has_value( Const :: CShape ( crate :: cruby:: ShapeId ( 0x1234 ) ) ) ) ;
1055+ }
9611056}
0 commit comments