4
4
#![ deny( clippy:: missing_docs_in_private_items) ]
5
5
#![ allow( deprecated) ]
6
6
7
- use std:: io;
8
7
use std:: str:: FromStr ;
8
+ use std:: { fmt, io} ;
9
9
10
10
/// Represents the version of the Rust language to target.
11
11
#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
12
12
#[ repr( transparent) ]
13
13
pub struct RustTarget ( Version ) ;
14
14
15
15
impl RustTarget {
16
+ /// Create a new [`RustTarget`] for a stable release of Rust.
17
+ pub fn stable ( minor : u64 , patch : u64 ) -> Result < Self , InvalidRustTarget > {
18
+ let target = Self ( Version :: Stable ( minor, patch) ) ;
19
+
20
+ if target < EARLIEST_STABLE_RUST {
21
+ return Err ( InvalidRustTarget :: TooEarly ) ;
22
+ }
23
+
24
+ Ok ( target)
25
+ }
26
+
16
27
const fn minor ( & self ) -> Option < u64 > {
17
28
match self . 0 {
18
29
Version :: Nightly => None ,
@@ -39,8 +50,8 @@ impl Default for RustTarget {
39
50
}
40
51
}
41
52
42
- impl std :: fmt:: Display for RustTarget {
43
- fn fmt ( & self , f : & mut std :: fmt:: Formatter < ' _ > ) -> std :: fmt:: Result {
53
+ impl fmt:: Display for RustTarget {
54
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
44
55
match self . 0 {
45
56
Version :: Stable ( minor, patch) => write ! ( f, "1.{minor}.{patch}" ) ,
46
57
Version :: Nightly => "nightly" . fmt ( f) ,
@@ -54,6 +65,18 @@ enum Version {
54
65
Nightly ,
55
66
}
56
67
68
+ pub enum InvalidRustTarget {
69
+ TooEarly ,
70
+ }
71
+
72
+ impl fmt:: Display for InvalidRustTarget {
73
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
74
+ match self {
75
+ Self :: TooEarly => write ! ( f, "the earliest Rust version supported by bindgen is {EARLIEST_STABLE_RUST}" ) ,
76
+ }
77
+ }
78
+ }
79
+
57
80
/// This macro defines the [`RustTarget`] and [`RustFeatures`] types.
58
81
macro_rules! define_rust_targets {
59
82
(
@@ -71,7 +94,16 @@ macro_rules! define_rust_targets {
71
94
"- [`" , stringify!( $nightly_feature) , "`]" ,
72
95
"(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $issue) , ) * ")" ,
73
96
) ] ) *
74
- pub const Nightly : Self = Self ( Version :: Nightly ) ;
97
+ pub const Nightly : Self = Self :: nightly( ) ;
98
+
99
+ /// The nightly version of Rust, which introduces the following features:"
100
+ $( #[ doc = concat!(
101
+ "- [`" , stringify!( $nightly_feature) , "`]" ,
102
+ "(" , $( "https://github.com/rust-lang/rust/pull/" , stringify!( $issue) , ) * ")" ,
103
+ ) ] ) *
104
+ pub const fn nightly( ) -> Self {
105
+ Self ( Version :: Nightly )
106
+ }
75
107
76
108
$(
77
109
#[ doc = concat!( "Version 1." , stringify!( $minor) , " of Rust, which introduced the following features:" ) ]
@@ -238,11 +270,11 @@ pub const EARLIEST_STABLE_RUST: RustTarget = {
238
270
}
239
271
} ;
240
272
241
- fn invalid_input < T > ( input : & str , msg : impl std :: fmt:: Display ) -> io:: Result < T > {
242
- Err ( io:: Error :: new (
273
+ fn invalid_input ( input : & str , msg : impl fmt:: Display ) -> io:: Error {
274
+ io:: Error :: new (
243
275
io:: ErrorKind :: InvalidInput ,
244
276
format ! ( "\" {input}\" is not a valid Rust target, {msg}" ) ,
245
- ) )
277
+ )
246
278
}
247
279
248
280
impl FromStr for RustTarget {
@@ -254,35 +286,35 @@ impl FromStr for RustTarget {
254
286
}
255
287
256
288
let Some ( ( major_str, tail) ) = input. split_once ( '.' ) else {
257
- return invalid_input ( input, "accepted values are of the form \" 1.71\" , \" 1.71.1\" or \" nightly\" ." ) ;
289
+ return Err ( invalid_input ( input, "accepted values are of the form \" 1.71\" , \" 1.71.1\" or \" nightly\" ." ) ) ;
258
290
} ;
259
291
260
292
if major_str != "1" {
261
- return invalid_input (
293
+ return Err ( invalid_input (
262
294
input,
263
295
"The largest major version of Rust released is \" 1\" " ,
264
- ) ;
296
+ ) ) ;
265
297
}
266
298
267
299
let ( minor, patch) = match tail. split_once ( '.' ) {
268
300
Some ( ( minor_str, patch_str) ) => {
269
301
let Ok ( minor) = minor_str. parse :: < u64 > ( ) else {
270
- return invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ;
302
+ return Err ( invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ) ;
271
303
} ;
272
304
let Ok ( patch) = patch_str. parse :: < u64 > ( ) else {
273
- return invalid_input ( input, "the patch version number must be an unsigned 64-bit integer" ) ;
305
+ return Err ( invalid_input ( input, "the patch version number must be an unsigned 64-bit integer" ) ) ;
274
306
} ;
275
307
( minor, patch)
276
308
}
277
309
None => {
278
310
let Ok ( minor) = tail. parse :: < u64 > ( ) else {
279
- return invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ;
311
+ return Err ( invalid_input ( input, "the minor version number must be an unsigned 64-bit integer" ) ) ;
280
312
} ;
281
313
( minor, 0 )
282
314
}
283
315
} ;
284
316
285
- Ok ( Self ( Version :: Stable ( minor, patch) ) )
317
+ Self :: stable ( minor, patch) . map_err ( |err| invalid_input ( input , err ) )
286
318
}
287
319
}
288
320
@@ -380,5 +412,7 @@ mod test {
380
412
test_invalid_target ( "1.-1.0" ) ;
381
413
test_invalid_target ( "1.0.-1" ) ;
382
414
test_invalid_target ( "beta" ) ;
415
+ test_invalid_target ( "1.0.0" ) ;
416
+ test_invalid_target ( "1.32.0" ) ;
383
417
}
384
418
}
0 commit comments