File tree 3 files changed +20
-12
lines changed
3 files changed +20
-12
lines changed Original file line number Diff line number Diff line change @@ -269,26 +269,31 @@ impl Crate {
269
269
. unwrap_or ( false )
270
270
}
271
271
272
+ /// Validates the THIS parts of `features = ["THIS", "and/THIS"]`.
272
273
pub fn valid_feature_name ( name : & str ) -> bool {
273
274
!name. is_empty ( )
274
275
&& name
275
276
. chars ( )
276
- . all ( |c| c. is_alphanumeric ( ) || c == '_' || c == '-' )
277
- && name. chars ( ) . all ( |c| c. is_ascii ( ) )
277
+ . all ( |c| c. is_ascii_alphanumeric ( ) || c == '_' || c == '-' || c == '+' )
278
278
}
279
279
280
+ /// Validates the prefix in front of the slash: `features = ["THIS/feature"]`.
281
+ /// Normally this corresponds to the crate name of a dependency.
282
+ fn valid_feature_prefix ( name : & str ) -> bool {
283
+ !name. is_empty ( )
284
+ && name
285
+ . chars ( )
286
+ . all ( |c| c. is_ascii_alphanumeric ( ) || c == '_' || c == '-' )
287
+ }
288
+
289
+ /// Validates a whole feature string, `features = ["THIS", "ALL/THIS"]`.
280
290
pub fn valid_feature ( name : & str ) -> bool {
281
291
let mut parts = name. split ( '/' ) ;
282
- match parts. next ( ) {
283
- Some ( part) if !Crate :: valid_feature_name ( part) => return false ,
284
- None => return false ,
285
- _ => { }
286
- }
287
- match parts. next ( ) {
288
- Some ( part) if !Crate :: valid_feature_name ( part) => return false ,
289
- _ => { }
290
- }
292
+ let name_part = parts. next_back ( ) ; // required
293
+ let prefix_part = parts. next_back ( ) ; // optional
291
294
parts. next ( ) . is_none ( )
295
+ && name_part. map_or ( false , Crate :: valid_feature_name)
296
+ && prefix_part. map_or ( true , Crate :: valid_feature_prefix)
292
297
}
293
298
294
299
pub fn minimal_encodable (
Original file line number Diff line number Diff line change @@ -983,6 +983,9 @@ fn valid_feature_names() {
983
983
assert ! ( !Crate :: valid_feature( "%/%" ) ) ;
984
984
assert ! ( Crate :: valid_feature( "a/a" ) ) ;
985
985
assert ! ( Crate :: valid_feature( "32-column-tables" ) ) ;
986
+ assert ! ( Crate :: valid_feature( "c++20" ) ) ;
987
+ assert ! ( Crate :: valid_feature( "krate/c++20" ) ) ;
988
+ assert ! ( !Crate :: valid_feature( "c++20/wow" ) ) ;
986
989
}
987
990
988
991
#[ test]
Original file line number Diff line number Diff line change @@ -113,7 +113,7 @@ impl<'de> Deserialize<'de> for EncodableFeatureName {
113
113
if !Crate :: valid_feature_name ( & s) {
114
114
let value = de:: Unexpected :: Str ( & s) ;
115
115
let expected = "a valid feature name containing only letters, \
116
- numbers, hyphens, or underscores ";
116
+ numbers, '-', '+', or '_' ";
117
117
Err ( de:: Error :: invalid_value ( value, & expected) )
118
118
} else {
119
119
Ok ( EncodableFeatureName ( s) )
You can’t perform that action at this time.
0 commit comments