@@ -402,11 +402,28 @@ uniform_simd_int_impl! { (u8, i8), (u16, i16), (u32, i32), (u64, i64) }
402402/// this implementation will use 32-bit sampling when possible.
403403#[ cfg( any( target_pointer_width = "32" , target_pointer_width = "64" ) ) ]
404404#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
405+ #[ cfg_attr( all( feature = "serde" ) , derive( Serialize ) ) ]
406+ // To be able to deserialize on 32-bit we need to replace this with a custom
407+ // implementation of the Deserialize trait, to be able to:
408+ // - panic when `mode64` is `true` on 32-bit,
409+ // - assign the default value to `mode64` when it's missing on 64-bit,
410+ // - panic when the `usize` fields are greater than `u32::MAX` on 32-bit.
411+ #[ cfg_attr(
412+ all( feature = "serde" , target_pointer_width = "64" ) ,
413+ derive( Deserialize )
414+ ) ]
405415pub struct UniformUsize {
416+ /// The lowest possible value.
406417 low : usize ,
418+ /// The number of possible values. `0` has a special meaning: all.
407419 range : usize ,
420+ /// Threshold used when sampling to obtain a uniform distribution.
408421 thresh : usize ,
422+ /// Whether the largest possible value is greater than `u32::MAX`.
409423 #[ cfg( target_pointer_width = "64" ) ]
424+ // Handle missing field when deserializing on 64-bit an object serialized
425+ // on 32-bit. Can be removed when switching to a custom deserializer.
426+ #[ cfg_attr( feature = "serde" , serde( default ) ) ]
410427 mode64 : bool ,
411428}
412429
@@ -793,4 +810,94 @@ mod tests {
793810 ) ;
794811 }
795812 }
813+
814+ #[ test]
815+ fn test_uniform_usize_empty_range ( ) {
816+ assert_eq ! ( UniformUsize :: new( 10 , 10 ) , Err ( Error :: EmptyRange ) ) ;
817+ assert ! ( UniformUsize :: new( 10 , 11 ) . is_ok( ) ) ;
818+
819+ assert_eq ! ( UniformUsize :: new_inclusive( 10 , 9 ) , Err ( Error :: EmptyRange ) ) ;
820+ assert ! ( UniformUsize :: new_inclusive( 10 , 10 ) . is_ok( ) ) ;
821+ }
822+
823+ #[ test]
824+ fn test_uniform_usize_constructors ( ) {
825+ assert_eq ! (
826+ UniformUsize :: new_inclusive( u32 :: MAX as usize , u32 :: MAX as usize ) ,
827+ Ok ( UniformUsize {
828+ low: u32 :: MAX as usize ,
829+ range: 1 ,
830+ thresh: 0 ,
831+ #[ cfg( target_pointer_width = "64" ) ]
832+ mode64: false
833+ } )
834+ ) ;
835+ assert_eq ! (
836+ UniformUsize :: new_inclusive( 0 , u32 :: MAX as usize ) ,
837+ Ok ( UniformUsize {
838+ low: 0 ,
839+ range: 0 ,
840+ thresh: 0 ,
841+ #[ cfg( target_pointer_width = "64" ) ]
842+ mode64: false
843+ } )
844+ ) ;
845+ #[ cfg( target_pointer_width = "64" ) ]
846+ assert_eq ! (
847+ UniformUsize :: new_inclusive( 0 , u32 :: MAX as usize + 1 ) ,
848+ Ok ( UniformUsize {
849+ low: 0 ,
850+ range: u32 :: MAX as usize + 2 ,
851+ thresh: 1 ,
852+ mode64: true
853+ } )
854+ ) ;
855+ #[ cfg( target_pointer_width = "64" ) ]
856+ assert_eq ! (
857+ UniformUsize :: new_inclusive( u32 :: MAX as usize , u64 :: MAX as usize ) ,
858+ Ok ( UniformUsize {
859+ low: u32 :: MAX as usize ,
860+ range: u64 :: MAX as usize - u32 :: MAX as usize + 1 ,
861+ thresh: u32 :: MAX as usize ,
862+ mode64: true
863+ } )
864+ ) ;
865+ }
866+
867+ // This could be run also on 32-bit when deserialization is implemented.
868+ #[ cfg( all( feature = "serde" , target_pointer_width = "64" ) ) ]
869+ #[ test]
870+ fn test_uniform_usize_deserialization ( ) {
871+ use serde_json;
872+ let original = UniformUsize :: new_inclusive ( 10 , 100 ) . expect ( "creation" ) ;
873+ let serialized = serde_json:: to_string ( & original) . expect ( "serialization" ) ;
874+ let deserialized: UniformUsize =
875+ serde_json:: from_str ( & serialized) . expect ( "deserialization" ) ;
876+ assert_eq ! ( deserialized, original) ;
877+ }
878+
879+ #[ cfg( all( feature = "serde" , target_pointer_width = "64" ) ) ]
880+ #[ test]
881+ fn test_uniform_usize_deserialization_from_32bit ( ) {
882+ use serde_json;
883+ let serialized_on_32bit = r#"{"low":10,"range":91,"thresh":74}"# ;
884+ let deserialized: UniformUsize =
885+ serde_json:: from_str ( & serialized_on_32bit) . expect ( "deserialization" ) ;
886+ assert_eq ! (
887+ deserialized,
888+ UniformUsize :: new_inclusive( 10 , 100 ) . expect( "creation" )
889+ ) ;
890+ }
891+
892+ #[ cfg( all( feature = "serde" , target_pointer_width = "64" ) ) ]
893+ #[ test]
894+ fn test_uniform_usize_deserialization_64bit ( ) {
895+ use serde_json;
896+ let original = UniformUsize :: new_inclusive ( 1 , u64:: MAX as usize - 1 ) . expect ( "creation" ) ;
897+ assert ! ( original. mode64) ;
898+ let serialized = serde_json:: to_string ( & original) . expect ( "serialization" ) ;
899+ let deserialized: UniformUsize =
900+ serde_json:: from_str ( & serialized) . expect ( "deserialization" ) ;
901+ assert_eq ! ( deserialized, original) ;
902+ }
796903}
0 commit comments