@@ -2173,3 +2173,43 @@ mod impl_arbitrary {
2173
2173
}
2174
2174
impl_arbitrary ! { f32 , f64 }
2175
2175
}
2176
+
2177
+ #[ cfg( feature = "bytemuck" ) ]
2178
+ mod impl_bytemuck {
2179
+ use super :: { NotNan , OrderedFloat , Float } ;
2180
+ use bytemuck:: { CheckedBitPattern , AnyBitPattern , NoUninit , Pod , Zeroable } ;
2181
+
2182
+ unsafe impl < T : Zeroable > Zeroable for OrderedFloat < T > { }
2183
+
2184
+ // The zero bit pattern is indeed not a NaN bit pattern.
2185
+ unsafe impl < T : Zeroable > Zeroable for NotNan < T > { }
2186
+
2187
+ unsafe impl < T : Pod > Pod for OrderedFloat < T > { }
2188
+
2189
+ // `NotNan<T>` can only implement `NoUninit` and not `Pod`, since not every bit pattern is
2190
+ // valid (NaN bit patterns are invalid). `NoUninit` guarantees that we can read any bit pattern
2191
+ // from the value, which is fine in this case.
2192
+ unsafe impl < T : NoUninit > NoUninit for NotNan < T > { }
2193
+
2194
+ unsafe impl < T : Float + AnyBitPattern > CheckedBitPattern for NotNan < T > {
2195
+ type Bits = T ;
2196
+
2197
+ fn is_valid_bit_pattern ( bits : & Self :: Bits ) -> bool {
2198
+ !bits. is_nan ( )
2199
+ }
2200
+ }
2201
+
2202
+ #[ test]
2203
+ fn test_not_nan_bit_pattern ( ) {
2204
+ use bytemuck:: checked:: { try_cast, CheckedCastError } ;
2205
+
2206
+ let nan = f64:: NAN ;
2207
+ assert_eq ! (
2208
+ try_cast:: <f64 , NotNan <f64 >>( nan) ,
2209
+ Err ( CheckedCastError :: InvalidBitPattern ) ,
2210
+ ) ;
2211
+
2212
+ let pi = core:: f64:: consts:: PI ;
2213
+ assert ! ( try_cast:: <f64 , NotNan <f64 >>( pi) . is_ok( ) ) ;
2214
+ }
2215
+ }
0 commit comments