@@ -487,7 +487,7 @@ impl VALUE {
487487
488488 pub fn as_fixnum ( self ) -> i64 {
489489 assert ! ( self . fixnum_p( ) ) ;
490- ( self . 0 >> 1 ) as i64
490+ ( self . 0 as i64 ) >> 1
491491 }
492492
493493 pub fn as_isize ( self ) -> isize {
@@ -572,6 +572,13 @@ impl VALUE {
572572 let k: usize = item. wrapping_add ( item. wrapping_add ( 1 ) ) ;
573573 VALUE ( k)
574574 }
575+
576+ pub const fn fixnum_from_isize ( item : isize ) -> Self {
577+ assert ! ( item >= RUBY_FIXNUM_MIN ) ;
578+ assert ! ( item <= RUBY_FIXNUM_MAX ) ;
579+ let k: isize = item. wrapping_add ( item. wrapping_add ( 1 ) ) ;
580+ VALUE ( k as usize )
581+ }
575582}
576583
577584impl From < IseqPtr > for VALUE {
@@ -1074,6 +1081,51 @@ pub mod test_utils {
10741081 eval ( "raise" ) ;
10751082 }
10761083
1084+ #[ test]
1085+ fn value_from_fixnum_in_range ( ) {
1086+ assert_eq ! ( VALUE :: fixnum_from_usize( 2 ) , VALUE ( 5 ) ) ;
1087+ assert_eq ! ( VALUE :: fixnum_from_usize( 0 ) , VALUE ( 1 ) ) ;
1088+ assert_eq ! ( VALUE :: fixnum_from_isize( -1 ) , VALUE ( 0xffffffffffffffff ) ) ;
1089+ assert_eq ! ( VALUE :: fixnum_from_isize( -2 ) , VALUE ( 0xfffffffffffffffd ) ) ;
1090+ assert_eq ! ( VALUE :: fixnum_from_usize( RUBY_FIXNUM_MAX as usize ) , VALUE ( 0x7fffffffffffffff ) ) ;
1091+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MAX ) , VALUE ( 0x7fffffffffffffff ) ) ;
1092+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MIN ) , VALUE ( 0x8000000000000001 ) ) ;
1093+ }
1094+
1095+ #[ test]
1096+ fn value_as_fixnum ( ) {
1097+ assert_eq ! ( VALUE :: fixnum_from_usize( 2 ) . as_fixnum( ) , 2 ) ;
1098+ assert_eq ! ( VALUE :: fixnum_from_usize( 0 ) . as_fixnum( ) , 0 ) ;
1099+ assert_eq ! ( VALUE :: fixnum_from_isize( -1 ) . as_fixnum( ) , -1 ) ;
1100+ assert_eq ! ( VALUE :: fixnum_from_isize( -2 ) . as_fixnum( ) , -2 ) ;
1101+ assert_eq ! ( VALUE :: fixnum_from_usize( RUBY_FIXNUM_MAX as usize ) . as_fixnum( ) , RUBY_FIXNUM_MAX . try_into( ) . unwrap( ) ) ;
1102+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MAX ) . as_fixnum( ) , RUBY_FIXNUM_MAX . try_into( ) . unwrap( ) ) ;
1103+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MIN ) . as_fixnum( ) , RUBY_FIXNUM_MIN . try_into( ) . unwrap( ) ) ;
1104+ }
1105+
1106+ #[ test]
1107+ #[ should_panic]
1108+ fn value_from_fixnum_too_big_usize ( ) {
1109+ assert_eq ! ( VALUE :: fixnum_from_usize( ( RUBY_FIXNUM_MAX +1 ) as usize ) , VALUE ( 1 ) ) ;
1110+ }
1111+
1112+ #[ test]
1113+ #[ should_panic]
1114+ fn value_from_fixnum_too_big_isize ( ) {
1115+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MAX +1 ) , VALUE ( 1 ) ) ;
1116+ }
1117+
1118+ #[ test]
1119+ #[ should_panic]
1120+ fn value_from_fixnum_too_small_usize ( ) {
1121+ assert_eq ! ( VALUE :: fixnum_from_usize( ( RUBY_FIXNUM_MIN -1 ) as usize ) , VALUE ( 1 ) ) ;
1122+ }
1123+
1124+ #[ test]
1125+ #[ should_panic]
1126+ fn value_from_fixnum_too_small_isize ( ) {
1127+ assert_eq ! ( VALUE :: fixnum_from_isize( RUBY_FIXNUM_MIN -1 ) , VALUE ( 1 ) ) ;
1128+ }
10771129}
10781130#[ cfg( test) ]
10791131pub use test_utils:: * ;
0 commit comments