@@ -426,6 +426,15 @@ pub struct UniformInt<X> {
426426
427427macro_rules! uniform_int_impl {
428428 ( $ty: ty, $unsigned: ident, $u_large: ident) => {
429+ impl UniformInt <$ty> {
430+ /// Get the maximum possible value
431+ #[ allow( unused) ]
432+ #[ inline]
433+ pub ( crate ) fn max( & self ) -> $ty {
434+ self . range. wrapping_sub( 1 ) . wrapping_add( self . low)
435+ }
436+ }
437+
429438 impl SampleUniform for $ty {
430439 type Sampler = UniformInt <$ty>;
431440 }
@@ -583,9 +592,24 @@ impl SampleUniform for char {
583592#[ derive( Clone , Copy , Debug ) ]
584593#[ cfg_attr( feature = "serde1" , derive( Serialize , Deserialize ) ) ]
585594pub struct UniformChar {
595+ #[ cfg_attr( feature = "serde1" , serde( deserialize_with = "deser_sampler" ) ) ]
586596 sampler : UniformInt < u32 > ,
587597}
588598
599+ #[ cfg( feature = "serde1" ) ]
600+ fn deser_sampler < ' de , D > ( d : D ) -> Result < UniformInt < u32 > , D :: Error >
601+ where
602+ D : serde:: Deserializer < ' de > ,
603+ {
604+ let sampler = <UniformInt < u32 > as serde:: Deserialize >:: deserialize ( d) ?;
605+ if sampler. max ( ) > char:: MAX as u32 - CHAR_SURROGATE_LEN {
606+ return Err ( serde:: de:: Error :: custom (
607+ "bad sampler range for UniformChar" ,
608+ ) ) ;
609+ }
610+ Ok ( sampler)
611+ }
612+
589613/// UTF-16 surrogate range start
590614const CHAR_SURROGATE_START : u32 = 0xD800 ;
591615/// UTF-16 surrogate range size
@@ -1154,6 +1178,24 @@ mod tests {
11541178 }
11551179 }
11561180
1181+ #[ test]
1182+ #[ cfg( feature = "serde1" ) ]
1183+ fn test_char_bad_deser ( ) {
1184+ let json = r#"{"sampler":{"low":4294967200,"range":0,"z":0}}"# ;
1185+ let result = serde_json:: from_str :: < Uniform < char > > ( json) ;
1186+ assert ! ( result. is_err( ) ) ;
1187+ let err = result. unwrap_err ( ) ;
1188+ assert_eq ! ( err. classify( ) , serde_json:: error:: Category :: Data ) ;
1189+
1190+ #[ cfg( feature = "alloc" ) ]
1191+ {
1192+ assert_eq ! (
1193+ alloc:: string:: ToString :: to_string( & err) ,
1194+ "bad sampler range for UniformChar at line 1 column 46"
1195+ ) ;
1196+ }
1197+ }
1198+
11571199 #[ test]
11581200 #[ cfg_attr( miri, ignore) ] // Miri is too slow
11591201 fn test_floats ( ) {
@@ -1381,6 +1423,7 @@ mod tests {
13811423 let r = Uniform :: from ( 2u32 ..7 ) ;
13821424 assert_eq ! ( r. 0 . low, 2 ) ;
13831425 assert_eq ! ( r. 0 . range, 5 ) ;
1426+ assert_eq ! ( r. 0 . max( ) , 6 ) ;
13841427 let r = Uniform :: from ( 2.0f64 ..7.0 ) ;
13851428 assert_eq ! ( r. 0 . low, 2.0 ) ;
13861429 assert_eq ! ( r. 0 . scale, 5.0 ) ;
@@ -1391,6 +1434,7 @@ mod tests {
13911434 let r = Uniform :: from ( 2u32 ..=6 ) ;
13921435 assert_eq ! ( r. 0 . low, 2 ) ;
13931436 assert_eq ! ( r. 0 . range, 5 ) ;
1437+ assert_eq ! ( r. 0 . max( ) , 6 ) ;
13941438 let r = Uniform :: from ( 2.0f64 ..=7.0 ) ;
13951439 assert_eq ! ( r. 0 . low, 2.0 ) ;
13961440 assert ! ( r. 0 . scale > 5.0 ) ;
0 commit comments