4
4
#![ deny( clippy:: missing_docs_in_private_items) ]
5
5
#![ allow( deprecated) ]
6
6
7
- use std:: cmp:: Ordering ;
8
7
use std:: io;
9
8
use std:: str:: FromStr ;
10
9
10
+ /// Represents the version of the Rust language to target.
11
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
12
+ #[ repr( transparent) ]
13
+ pub struct RustTarget ( Version ) ;
14
+
15
+ impl RustTarget {
16
+ const fn minor ( & self ) -> Option < u64 > {
17
+ match self . 0 {
18
+ Version :: Nightly => None ,
19
+ Version :: Stable ( minor, _) => Some ( minor) ,
20
+ }
21
+ }
22
+
23
+ const fn is_compatible ( & self , other : & Self ) -> bool {
24
+ match ( self . 0 , other. 0 ) {
25
+ ( Version :: Stable ( minor, _) , Version :: Stable ( other_minor, _) ) => {
26
+ // We ignore the patch version number as they only include backwards compatible bug
27
+ // fixes.
28
+ minor >= other_minor
29
+ }
30
+ ( _, Version :: Nightly ) => false ,
31
+ ( Version :: Nightly , _) => true ,
32
+ }
33
+ }
34
+ }
35
+
36
+ impl Default for RustTarget {
37
+ fn default ( ) -> Self {
38
+ LATEST_STABLE_RUST
39
+ }
40
+ }
41
+
42
+ impl std:: fmt:: Display for RustTarget {
43
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
44
+ match self . 0 {
45
+ Version :: Stable ( minor, patch) => write ! ( f, "1.{minor}.{patch}" ) ,
46
+ Version :: Nightly => "nightly" . fmt ( f) ,
47
+ }
48
+ }
49
+ }
50
+
51
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
52
+ enum Version {
53
+ Stable ( u64 , u64 ) ,
54
+ Nightly ,
55
+ }
56
+
11
57
/// This macro defines the [`RustTarget`] and [`RustFeatures`] types.
12
58
macro_rules! define_rust_targets {
13
59
(
@@ -18,38 +64,24 @@ macro_rules! define_rust_targets {
18
64
) *
19
65
$( , ) ?
20
66
) => {
21
- /// Represents the version of the Rust language to target.
22
- ///
23
- /// To support a beta release, use the corresponding stable release.
24
- ///
25
- /// This enum will have more variants added as necessary.
26
- #[ allow( non_camel_case_types) ]
27
- #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
28
- pub enum RustTarget {
29
- /// Rust Nightly
67
+
68
+ impl RustTarget {
69
+ /// The nightly version of Rust, which introduces the following features:"
30
70
$( #[ doc = concat!(
31
71
"- [`" , stringify!( $nightly_feature) , "`]" ,
32
72
"(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $issue) , ) * ")" ,
33
73
) ] ) *
34
- Nightly ,
74
+ pub const Nightly : Self = Self ( Version :: Nightly ) ;
75
+
35
76
$(
36
- #[ doc = concat!( "Rust 1." , stringify!( $minor) ) ]
77
+ #[ doc = concat!( "Version 1." , stringify!( $minor) , " of Rust, which introduced the following features:" ) ]
37
78
$( #[ doc = concat!(
38
79
"- [`" , stringify!( $feature) , "`]" ,
39
80
"(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $pull) , ) * ")" ,
40
81
) ] ) *
41
82
$( #[ $attrs] ) *
42
- $variant,
83
+ pub const $variant: Self = Self ( Version :: Stable ( $minor , 0 ) ) ;
43
84
) *
44
- }
45
-
46
- impl RustTarget {
47
- const fn minor( self ) -> Option <u64 > {
48
- match self {
49
- $( Self :: $variant => Some ( $minor) , ) *
50
- Self :: Nightly => None
51
- }
52
- }
53
85
54
86
const fn stable_releases( ) -> [ ( Self , u64 ) ; [ $( $minor, ) * ] . len( ) ] {
55
87
[ $( ( Self :: $variant, $minor) , ) * ]
@@ -58,7 +90,7 @@ macro_rules! define_rust_targets {
58
90
59
91
#[ cfg( feature = "__cli" ) ]
60
92
/// Strings of allowed `RustTarget` values
61
- pub const RUST_TARGET_STRINGS : & [ & str ] = & [ $( concat!( "1." , stringify!( $minor) ) , ) * ] ;
93
+ pub ( crate ) const RUST_TARGET_STRINGS : & [ & str ] = & [ $( concat!( "1." , stringify!( $minor) ) , ) * ] ;
62
94
63
95
#[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
64
96
pub ( crate ) struct RustFeatures {
@@ -80,7 +112,7 @@ macro_rules! define_rust_targets {
80
112
$( $nightly_feature: false , ) *
81
113
} ;
82
114
83
- $( if target >= RustTarget :: $variant {
115
+ $( if target. is_compatible ( & RustTarget :: $variant) {
84
116
$( features. $feature = true ; ) *
85
117
} ) *
86
118
@@ -206,29 +238,6 @@ pub const EARLIEST_STABLE_RUST: RustTarget = {
206
238
}
207
239
} ;
208
240
209
- impl Default for RustTarget {
210
- fn default ( ) -> Self {
211
- LATEST_STABLE_RUST
212
- }
213
- }
214
-
215
- impl PartialOrd for RustTarget {
216
- fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
217
- Some ( self . cmp ( other) )
218
- }
219
- }
220
-
221
- impl Ord for RustTarget {
222
- fn cmp ( & self , other : & Self ) -> Ordering {
223
- match ( self . minor ( ) , other. minor ( ) ) {
224
- ( Some ( a) , Some ( b) ) => a. cmp ( & b) ,
225
- ( Some ( _) , None ) => Ordering :: Less ,
226
- ( None , Some ( _) ) => Ordering :: Greater ,
227
- ( None , None ) => Ordering :: Equal ,
228
- }
229
- }
230
- }
231
-
232
241
fn invalid_input < T > ( input : & str , msg : impl std:: fmt:: Display ) -> io:: Result < T > {
233
242
Err ( io:: Error :: new (
234
243
io:: ErrorKind :: InvalidInput ,
@@ -255,8 +264,7 @@ impl FromStr for RustTarget {
255
264
) ;
256
265
}
257
266
258
- // We ignore the patch version number as they only include backwards compatible bug fixes.
259
- let ( minor, _patch) = match tail. split_once ( '.' ) {
267
+ let ( minor, patch) = match tail. split_once ( '.' ) {
260
268
Some ( ( minor_str, patch_str) ) => {
261
269
let Ok ( minor) = minor_str. parse :: < u64 > ( ) else {
262
270
return invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ;
@@ -274,26 +282,7 @@ impl FromStr for RustTarget {
274
282
}
275
283
} ;
276
284
277
- let Some ( target) = Self :: stable_releases ( )
278
- . iter ( )
279
- . filter ( |( _, target_minor) | minor >= * target_minor)
280
- . max_by_key ( |( _, target_minor) | target_minor)
281
- . map ( |( target, _) | target)
282
- . cloned ( )
283
- else {
284
- return invalid_input ( input, format ! ( "the earliest Rust target supported by bindgen is {EARLIEST_STABLE_RUST}" ) ) ;
285
- } ;
286
-
287
- Ok ( target)
288
- }
289
- }
290
-
291
- impl std:: fmt:: Display for RustTarget {
292
- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
293
- match self . minor ( ) {
294
- Some ( minor) => write ! ( f, "1.{}" , minor) ,
295
- None => "nightly" . fmt ( f) ,
296
- }
285
+ Ok ( Self ( Version :: Stable ( minor, patch) ) )
297
286
}
298
287
}
299
288
@@ -351,16 +340,23 @@ mod test {
351
340
) ;
352
341
}
353
342
354
- fn test_target ( target_str : & str , target : RustTarget ) {
343
+ fn test_target ( input : & str , expected : RustTarget ) {
344
+ // Two targets are equivalent if they enable the same set of features
345
+ let expected = RustFeatures :: from ( expected) ;
346
+ let found = RustFeatures :: from ( input. parse :: < RustTarget > ( ) . unwrap ( ) ) ;
355
347
assert_eq ! (
356
- target ,
357
- target_str . parse :: < RustTarget > ( ) . unwrap ( ) ,
358
- "{target_str }"
348
+ expected ,
349
+ found ,
350
+ "target {input} enables features: \n {found:#?} \n and should enable features: \n {expected:#? }"
359
351
) ;
360
352
}
361
353
362
- fn test_invalid_target ( target_str : & str ) {
363
- assert ! ( target_str. parse:: <RustTarget >( ) . is_err( ) , "{}" , target_str) ;
354
+ fn test_invalid_target ( input : & str ) {
355
+ assert ! (
356
+ input. parse:: <RustTarget >( ) . is_err( ) ,
357
+ "{} should be an invalid target" ,
358
+ input
359
+ ) ;
364
360
}
365
361
366
362
#[ test]
0 commit comments