@@ -31,14 +31,10 @@ pub struct Opts {
31
31
#[ cfg_attr( feature = "clap" , arg( long) ) ]
32
32
pub rustfmt : bool ,
33
33
34
- /// Whether or not the bindings assume interface values are always
35
- /// well-formed or whether checks are performed .
34
+ /// If true, code generation should qualify any features that depend on
35
+ /// `std` with `cfg(feature = "std")` .
36
36
#[ cfg_attr( feature = "clap" , arg( long) ) ]
37
- pub unchecked : bool ,
38
-
39
- /// If true, code generation should avoid any features that depend on `std`.
40
- #[ cfg_attr( feature = "clap" , arg( long) ) ]
41
- pub no_std : bool ,
37
+ pub std_feature : bool ,
42
38
43
39
/// If true, adds `#[macro_export]` to the `export_*!` macro generated to
44
40
/// export it from the Rust crate.
@@ -622,8 +618,8 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
622
618
}
623
619
}
624
620
625
- fn use_std ( & self ) -> bool {
626
- ! self . gen . opts . no_std
621
+ fn std_feature ( & self ) -> bool {
622
+ self . gen . opts . std_feature
627
623
}
628
624
629
625
fn use_raw_strings ( & self ) -> bool {
@@ -937,7 +933,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
937
933
operands : & mut Vec < String > ,
938
934
results : & mut Vec < String > ,
939
935
) {
940
- let unchecked = self . gen . gen . opts . unchecked ;
941
936
let mut top_as = |cvt : & str | {
942
937
let mut s = operands. pop ( ) . unwrap ( ) ;
943
938
s. push_str ( " as " ) ;
@@ -995,17 +990,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
995
990
Instruction :: U32FromI32 => top_as ( "u32" ) ,
996
991
Instruction :: U64FromI64 => top_as ( "u64" ) ,
997
992
Instruction :: CharFromI32 => {
998
- if unchecked {
999
- results. push ( format ! (
1000
- "core::char::from_u32_unchecked({} as u32)" ,
1001
- operands[ 0 ]
1002
- ) ) ;
1003
- } else {
1004
- results. push ( format ! (
1005
- "core::char::from_u32({} as u32).unwrap()" ,
1006
- operands[ 0 ]
1007
- ) ) ;
1008
- }
993
+ results. push ( format ! (
994
+ "{{
995
+ #[cfg(not(debug_assertions))]
996
+ {{ core::char::from_u32_unchecked({} as u32) }}
997
+ #[cfg(debug_assertions)]
998
+ {{ core::char::from_u32({} as u32).unwrap() }}
999
+ }}" ,
1000
+ operands[ 0 ] , operands[ 0 ]
1001
+ ) ) ;
1009
1002
}
1010
1003
1011
1004
Instruction :: Bitcasts { casts } => {
@@ -1016,21 +1009,21 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1016
1009
results. push ( format ! ( "match {} {{ true => 1, false => 0 }}" , operands[ 0 ] ) ) ;
1017
1010
}
1018
1011
Instruction :: BoolFromI32 => {
1019
- if unchecked {
1020
- results . push ( format ! (
1021
- "core::mem::transmute::<u8, bool>({} as u8)" ,
1022
- operands [ 0 ] ,
1023
- ) ) ;
1024
- } else {
1025
- results . push ( format ! (
1026
- "match {} {{
1027
- 0 => false ,
1028
- 1 => true ,
1029
- _ => panic!( \" invalid bool discriminant \" ),
1030
- }}" ,
1031
- operands [ 0 ] ,
1032
- ) ) ;
1033
- }
1012
+ results . push ( format ! (
1013
+ "{{
1014
+ #[cfg(not(debug_assertions))]
1015
+ {{ core::mem::transmute::<u8, bool>({} as u8) }}
1016
+ #[cfg(debug_assertions)]
1017
+ { {
1018
+ match {} {{
1019
+ 0 => false,
1020
+ 1 => true ,
1021
+ _ => panic!( \" invalid bool discriminant \" ) ,
1022
+ }}
1023
+ }}
1024
+ }}" ,
1025
+ operands [ 0 ] , operands [ 0 ] ,
1026
+ ) ) ;
1034
1027
}
1035
1028
1036
1029
Instruction :: FlagsLower { flags, .. } => {
@@ -1095,47 +1088,62 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1095
1088
self . push_str ( "};\n " ) ;
1096
1089
}
1097
1090
1098
- // In unchecked mode when this type is a named enum then we know we
1099
- // defined the type so we can transmute directly into it.
1100
- Instruction :: VariantLift { name, variant, .. }
1101
- if variant. cases . iter ( ) . all ( |c| c. ty . is_none ( ) ) && unchecked =>
1102
- {
1103
- self . blocks . drain ( self . blocks . len ( ) - variant. cases . len ( ) ..) ;
1104
- let mut result = format ! ( "core::mem::transmute::<_, " ) ;
1105
- result. push_str ( & name. to_upper_camel_case ( ) ) ;
1106
- result. push_str ( ">(" ) ;
1107
- result. push_str ( & operands[ 0 ] ) ;
1108
- result. push_str ( " as " ) ;
1109
- result. push_str ( int_repr ( variant. tag ( ) ) ) ;
1110
- result. push_str ( ")" ) ;
1111
- results. push ( result) ;
1112
- }
1091
+ Instruction :: VariantLift {
1092
+ name, variant, ty, ..
1093
+ } => {
1094
+ let mut result = String :: new ( ) ;
1095
+ result. push_str ( "{" ) ;
1113
1096
1114
- Instruction :: VariantLift { variant , ty , .. } => {
1097
+ let named_enum = variant . cases . iter ( ) . all ( |c| c . ty . is_none ( ) ) ;
1115
1098
let blocks = self
1116
1099
. blocks
1117
1100
. drain ( self . blocks . len ( ) - variant. cases . len ( ) ..)
1118
1101
. collect :: < Vec < _ > > ( ) ;
1119
1102
let op0 = & operands[ 0 ] ;
1120
- let mut result = format ! ( "match {op0} {{\n " ) ;
1103
+
1104
+ if named_enum {
1105
+ // In unchecked mode when this type is a named enum then we know we
1106
+ // defined the type so we can transmute directly into it.
1107
+ result. push_str ( "#[cfg(not(debug_assertions))]" ) ;
1108
+ result. push_str ( "{" ) ;
1109
+ result. push_str ( "core::mem::transmute::<_, " ) ;
1110
+ result. push_str ( & name. to_upper_camel_case ( ) ) ;
1111
+ result. push_str ( ">(" ) ;
1112
+ result. push_str ( op0) ;
1113
+ result. push_str ( " as " ) ;
1114
+ result. push_str ( int_repr ( variant. tag ( ) ) ) ;
1115
+ result. push_str ( ")" ) ;
1116
+ result. push_str ( "}" ) ;
1117
+ }
1118
+
1119
+ if named_enum {
1120
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1121
+ }
1122
+ result. push_str ( "{" ) ;
1123
+ result. push_str ( & format ! ( "match {op0} {{\n " ) ) ;
1121
1124
let name = self . typename_lift ( * ty) ;
1122
1125
for ( i, ( case, block) ) in variant. cases . iter ( ) . zip ( blocks) . enumerate ( ) {
1123
- let pat = if i == variant. cases . len ( ) - 1 && unchecked {
1124
- String :: from ( "_" )
1125
- } else {
1126
- i. to_string ( )
1127
- } ;
1126
+ let pat = i. to_string ( ) ;
1128
1127
let block = if case. ty . is_some ( ) {
1129
1128
format ! ( "({block})" )
1130
1129
} else {
1131
1130
String :: new ( )
1132
1131
} ;
1133
1132
let case = case. name . to_upper_camel_case ( ) ;
1134
- result. push_str ( & format ! ( "{pat} => {name}::{case}{block},\n " ) ) ;
1135
- }
1136
- if !unchecked {
1137
- result. push_str ( "_ => panic!(\" invalid enum discriminant\" ),\n " ) ;
1133
+ if i == variant. cases . len ( ) - 1 {
1134
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1135
+ result. push_str ( & format ! ( "{pat} => {name}::{case}{block},\n " ) ) ;
1136
+ result. push_str ( "#[cfg(not(debug_assertions))]" ) ;
1137
+ result. push_str ( & format ! ( "_ => {name}::{case}{block},\n " ) ) ;
1138
+ } else {
1139
+ result. push_str ( & format ! ( "{pat} => {name}::{case}{block},\n " ) ) ;
1140
+ }
1138
1141
}
1142
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1143
+ result. push_str ( "_ => panic!(\" invalid enum discriminant\" ),\n " ) ;
1144
+ result. push_str ( "}" ) ;
1145
+ result. push_str ( "}" ) ;
1146
+
1139
1147
result. push_str ( "}" ) ;
1140
1148
results. push ( result) ;
1141
1149
}
@@ -1174,17 +1182,19 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1174
1182
. zip ( blocks)
1175
1183
. enumerate ( )
1176
1184
{
1177
- let pat = if i == union. cases . len ( ) - 1 && unchecked {
1178
- String :: from ( "_" )
1179
- } else {
1180
- i. to_string ( )
1181
- } ;
1185
+ let pat = i. to_string ( ) ;
1182
1186
let name = self . typename_lift ( * ty) ;
1183
- result. push_str ( & format ! ( "{pat} => {name}::{case_name}({block}),\n " ) ) ;
1184
- }
1185
- if !unchecked {
1186
- result. push_str ( "_ => panic!(\" invalid union discriminant\" ),\n " ) ;
1187
+ if i == union. cases . len ( ) - 1 {
1188
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1189
+ result. push_str ( & format ! ( "{pat} => {name}::{case_name}({block}),\n " ) ) ;
1190
+ result. push_str ( "#[cfg(not(debug_assertions))]" ) ;
1191
+ result. push_str ( & format ! ( "_ => {name}::{case_name}({block}),\n " ) ) ;
1192
+ } else {
1193
+ result. push_str ( & format ! ( "{pat} => {name}::{case_name}({block}),\n " ) ) ;
1194
+ }
1187
1195
}
1196
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1197
+ result. push_str ( "_ => panic!(\" invalid union discriminant\" ),\n " ) ;
1188
1198
result. push_str ( "}" ) ;
1189
1199
results. push ( result) ;
1190
1200
}
@@ -1210,16 +1220,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1210
1220
let none = self . blocks . pop ( ) . unwrap ( ) ;
1211
1221
assert_eq ! ( none, "()" ) ;
1212
1222
let operand = & operands[ 0 ] ;
1213
- let invalid = if unchecked {
1214
- "core::hint::unreachable_unchecked()"
1215
- } else {
1216
- "panic!(\" invalid enum discriminant\" )"
1217
- } ;
1218
1223
results. push ( format ! (
1219
1224
"match {operand} {{
1220
1225
0 => None,
1221
1226
1 => Some({some}),
1222
- _ => {invalid},
1227
+ #[cfg(not(debug_assertions))]
1228
+ _ => core::hint::unreachable_unchecked(),
1229
+ #[cfg(debug_assertions)]
1230
+ _ => panic!(\" invalid enum discriminant\" ),
1223
1231
}}"
1224
1232
) ) ;
1225
1233
}
@@ -1247,16 +1255,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1247
1255
let err = self . blocks . pop ( ) . unwrap ( ) ;
1248
1256
let ok = self . blocks . pop ( ) . unwrap ( ) ;
1249
1257
let operand = & operands[ 0 ] ;
1250
- let invalid = if unchecked {
1251
- "core::hint::unreachable_unchecked()"
1252
- } else {
1253
- "panic!(\" invalid enum discriminant\" )"
1254
- } ;
1255
1258
results. push ( format ! (
1256
1259
"match {operand} {{
1257
1260
0 => Ok({ok}),
1258
1261
1 => Err({err}),
1259
- _ => {invalid},
1262
+ #[cfg(not(debug_assertions))]
1263
+ _ => core::hint::unreachable_unchecked(),
1264
+ #[cfg(debug_assertions)]
1265
+ _ => panic!(\" invalid enum discriminant\" ),
1260
1266
}}"
1261
1267
) ) ;
1262
1268
}
@@ -1272,21 +1278,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1272
1278
results. push ( result) ;
1273
1279
}
1274
1280
1275
- // In unchecked mode when this type is a named enum then we know we
1276
- // defined the type so we can transmute directly into it.
1277
- Instruction :: EnumLift { enum_, ty, .. } if unchecked => {
1278
- let mut result = format ! ( "core::mem::transmute::<_, " ) ;
1279
- result. push_str ( & self . gen . type_path ( * ty, true ) ) ;
1280
- result. push_str ( ">(" ) ;
1281
- result. push_str ( & operands[ 0 ] ) ;
1282
- result. push_str ( " as " ) ;
1283
- result. push_str ( int_repr ( enum_. tag ( ) ) ) ;
1284
- result. push_str ( ")" ) ;
1285
- results. push ( result) ;
1286
- }
1287
-
1288
1281
Instruction :: EnumLift { enum_, ty, .. } => {
1289
- let mut result = format ! ( "match " ) ;
1282
+ let mut result = String :: new ( ) ;
1283
+ result. push_str ( "{" ) ;
1284
+
1285
+ // In checked mode do a `match`.
1286
+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1287
+ result. push_str ( "{" ) ;
1288
+ result. push_str ( "match " ) ;
1290
1289
result. push_str ( & operands[ 0 ] ) ;
1291
1290
result. push_str ( " {\n " ) ;
1292
1291
let name = self . gen . type_path ( * ty, true ) ;
@@ -1295,6 +1294,22 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1295
1294
result. push_str ( & format ! ( "{i} => {name}::{case},\n " ) ) ;
1296
1295
}
1297
1296
result. push_str ( "_ => panic!(\" invalid enum discriminant\" ),\n " ) ;
1297
+ result. push_str ( "}" ) ;
1298
+ result. push_str ( "}" ) ;
1299
+
1300
+ // In unchecked mode when this type is a named enum then we know we
1301
+ // defined the type so we can transmute directly into it.
1302
+ result. push_str ( "#[cfg(not(debug_assertions))]" ) ;
1303
+ result. push_str ( "{" ) ;
1304
+ result. push_str ( "core::mem::transmute::<_, " ) ;
1305
+ result. push_str ( & self . gen . type_path ( * ty, true ) ) ;
1306
+ result. push_str ( ">(" ) ;
1307
+ result. push_str ( & operands[ 0 ] ) ;
1308
+ result. push_str ( " as " ) ;
1309
+ result. push_str ( int_repr ( enum_. tag ( ) ) ) ;
1310
+ result. push_str ( ")" ) ;
1311
+ result. push_str ( "}" ) ;
1312
+
1298
1313
result. push_str ( "}" ) ;
1299
1314
results. push ( result) ;
1300
1315
}
@@ -1360,10 +1375,22 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1360
1375
) ;
1361
1376
if self . gen . gen . opts . raw_strings {
1362
1377
results. push ( result) ;
1363
- } else if unchecked {
1364
- results. push ( format ! ( "String::from_utf8_unchecked({})" , result) ) ;
1365
1378
} else {
1366
- results. push ( format ! ( "String::from_utf8({}).unwrap()" , result) ) ;
1379
+ let mut converted = String :: new ( ) ;
1380
+ converted. push_str ( "{" ) ;
1381
+
1382
+ converted. push_str ( "#[cfg(not(debug_assertions))]" ) ;
1383
+ converted. push_str ( "{" ) ;
1384
+ converted. push_str ( & format ! ( "String::from_utf8_unchecked({})" , result) ) ;
1385
+ converted. push_str ( "}" ) ;
1386
+
1387
+ converted. push_str ( "#[cfg(debug_assertions)]" ) ;
1388
+ converted. push_str ( "{" ) ;
1389
+ converted. push_str ( & format ! ( "String::from_utf8({}).unwrap()" , result) ) ;
1390
+ converted. push_str ( "}" ) ;
1391
+
1392
+ converted. push_str ( "}" ) ;
1393
+ results. push ( converted) ;
1367
1394
}
1368
1395
}
1369
1396
0 commit comments