44#![ deny( clippy:: missing_docs_in_private_items) ]
55#![ allow( deprecated) ]
66
7- use std:: cmp:: Ordering ;
87use std:: io;
98use std:: str:: FromStr ;
109
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+
1157/// This macro defines the [`RustTarget`] and [`RustFeatures`] types.
1258macro_rules! define_rust_targets {
1359 (
@@ -18,38 +64,24 @@ macro_rules! define_rust_targets {
1864 ) *
1965 $( , ) ?
2066 ) => {
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:"
3070 $( #[ doc = concat!(
3171 "- [`" , stringify!( $nightly_feature) , "`]" ,
3272 "(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $issue) , ) * ")" ,
3373 ) ] ) *
34- Nightly ,
74+ pub const Nightly : Self = Self ( Version :: Nightly ) ;
75+
3576 $(
36- #[ doc = concat!( "Rust 1." , stringify!( $minor) ) ]
77+ #[ doc = concat!( "Version 1." , stringify!( $minor) , " of Rust, which introduced the following features:" ) ]
3778 $( #[ doc = concat!(
3879 "- [`" , stringify!( $feature) , "`]" ,
3980 "(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $pull) , ) * ")" ,
4081 ) ] ) *
4182 $( #[ $attrs] ) *
42- $variant,
83+ pub const $variant: Self = Self ( Version :: Stable ( $minor , 0 ) ) ;
4384 ) *
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- }
5385
5486 const fn stable_releases( ) -> [ ( Self , u64 ) ; [ $( $minor, ) * ] . len( ) ] {
5587 [ $( ( Self :: $variant, $minor) , ) * ]
@@ -58,7 +90,7 @@ macro_rules! define_rust_targets {
5890
5991 #[ cfg( feature = "__cli" ) ]
6092 /// 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) ) , ) * ] ;
6294
6395 #[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
6496 pub ( crate ) struct RustFeatures {
@@ -80,7 +112,7 @@ macro_rules! define_rust_targets {
80112 $( $nightly_feature: false , ) *
81113 } ;
82114
83- $( if target >= RustTarget :: $variant {
115+ $( if target. is_compatible ( & RustTarget :: $variant) {
84116 $( features. $feature = true ; ) *
85117 } ) *
86118
@@ -206,29 +238,6 @@ pub const EARLIEST_STABLE_RUST: RustTarget = {
206238 }
207239} ;
208240
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-
232241fn invalid_input < T > ( input : & str , msg : impl std:: fmt:: Display ) -> io:: Result < T > {
233242 Err ( io:: Error :: new (
234243 io:: ErrorKind :: InvalidInput ,
@@ -255,8 +264,7 @@ impl FromStr for RustTarget {
255264 ) ;
256265 }
257266
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 ( '.' ) {
260268 Some ( ( minor_str, patch_str) ) => {
261269 let Ok ( minor) = minor_str. parse :: < u64 > ( ) else {
262270 return invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ;
@@ -274,26 +282,7 @@ impl FromStr for RustTarget {
274282 }
275283 } ;
276284
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) ) )
297286 }
298287}
299288
@@ -351,16 +340,23 @@ mod test {
351340 ) ;
352341 }
353342
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 ( ) ) ;
355347 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:#? }"
359351 ) ;
360352 }
361353
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+ ) ;
364360 }
365361
366362 #[ test]
0 commit comments