@@ -31,14 +31,10 @@ pub struct Opts {
3131 #[ cfg_attr( feature = "clap" , arg( long) ) ]
3232 pub rustfmt : bool ,
3333
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")` .
3636 #[ 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 ,
4238
4339 /// If true, adds `#[macro_export]` to the `export_*!` macro generated to
4440 /// export it from the Rust crate.
@@ -622,8 +618,8 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
622618 }
623619 }
624620
625- fn use_std ( & self ) -> bool {
626- ! self . gen . opts . no_std
621+ fn std_feature ( & self ) -> bool {
622+ self . gen . opts . std_feature
627623 }
628624
629625 fn use_raw_strings ( & self ) -> bool {
@@ -937,7 +933,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
937933 operands : & mut Vec < String > ,
938934 results : & mut Vec < String > ,
939935 ) {
940- let unchecked = self . gen . gen . opts . unchecked ;
941936 let mut top_as = |cvt : & str | {
942937 let mut s = operands. pop ( ) . unwrap ( ) ;
943938 s. push_str ( " as " ) ;
@@ -995,17 +990,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
995990 Instruction :: U32FromI32 => top_as ( "u32" ) ,
996991 Instruction :: U64FromI64 => top_as ( "u64" ) ,
997992 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+ ) ) ;
10091002 }
10101003
10111004 Instruction :: Bitcasts { casts } => {
@@ -1016,21 +1009,21 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10161009 results. push ( format ! ( "match {} {{ true => 1, false => 0 }}" , operands[ 0 ] ) ) ;
10171010 }
10181011 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+ ) ) ;
10341027 }
10351028
10361029 Instruction :: FlagsLower { flags, .. } => {
@@ -1095,47 +1088,62 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10951088 self . push_str ( "};\n " ) ;
10961089 }
10971090
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 ( "{" ) ;
11131096
1114- Instruction :: VariantLift { variant , ty , .. } => {
1097+ let named_enum = variant . cases . iter ( ) . all ( |c| c . ty . is_none ( ) ) ;
11151098 let blocks = self
11161099 . blocks
11171100 . drain ( self . blocks . len ( ) - variant. cases . len ( ) ..)
11181101 . collect :: < Vec < _ > > ( ) ;
11191102 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 " ) ) ;
11211124 let name = self . typename_lift ( * ty) ;
11221125 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 ( ) ;
11281127 let block = if case. ty . is_some ( ) {
11291128 format ! ( "({block})" )
11301129 } else {
11311130 String :: new ( )
11321131 } ;
11331132 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+ }
11381141 }
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+
11391147 result. push_str ( "}" ) ;
11401148 results. push ( result) ;
11411149 }
@@ -1174,17 +1182,19 @@ impl Bindgen for FunctionBindgen<'_, '_> {
11741182 . zip ( blocks)
11751183 . enumerate ( )
11761184 {
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 ( ) ;
11821186 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+ }
11871195 }
1196+ result. push_str ( "#[cfg(debug_assertions)]" ) ;
1197+ result. push_str ( "_ => panic!(\" invalid union discriminant\" ),\n " ) ;
11881198 result. push_str ( "}" ) ;
11891199 results. push ( result) ;
11901200 }
@@ -1210,16 +1220,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12101220 let none = self . blocks . pop ( ) . unwrap ( ) ;
12111221 assert_eq ! ( none, "()" ) ;
12121222 let operand = & operands[ 0 ] ;
1213- let invalid = if unchecked {
1214- "core::hint::unreachable_unchecked()"
1215- } else {
1216- "panic!(\" invalid enum discriminant\" )"
1217- } ;
12181223 results. push ( format ! (
12191224 "match {operand} {{
12201225 0 => None,
12211226 1 => Some({some}),
1222- _ => {invalid},
1227+ #[cfg(not(debug_assertions))]
1228+ _ => core::hint::unreachable_unchecked(),
1229+ #[cfg(debug_assertions)]
1230+ _ => panic!(\" invalid enum discriminant\" ),
12231231 }}"
12241232 ) ) ;
12251233 }
@@ -1247,16 +1255,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12471255 let err = self . blocks . pop ( ) . unwrap ( ) ;
12481256 let ok = self . blocks . pop ( ) . unwrap ( ) ;
12491257 let operand = & operands[ 0 ] ;
1250- let invalid = if unchecked {
1251- "core::hint::unreachable_unchecked()"
1252- } else {
1253- "panic!(\" invalid enum discriminant\" )"
1254- } ;
12551258 results. push ( format ! (
12561259 "match {operand} {{
12571260 0 => Ok({ok}),
12581261 1 => Err({err}),
1259- _ => {invalid},
1262+ #[cfg(not(debug_assertions))]
1263+ _ => core::hint::unreachable_unchecked(),
1264+ #[cfg(debug_assertions)]
1265+ _ => panic!(\" invalid enum discriminant\" ),
12601266 }}"
12611267 ) ) ;
12621268 }
@@ -1272,21 +1278,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12721278 results. push ( result) ;
12731279 }
12741280
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-
12881281 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 " ) ;
12901289 result. push_str ( & operands[ 0 ] ) ;
12911290 result. push_str ( " {\n " ) ;
12921291 let name = self . gen . type_path ( * ty, true ) ;
@@ -1295,6 +1294,22 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12951294 result. push_str ( & format ! ( "{i} => {name}::{case},\n " ) ) ;
12961295 }
12971296 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+
12981313 result. push_str ( "}" ) ;
12991314 results. push ( result) ;
13001315 }
@@ -1360,10 +1375,22 @@ impl Bindgen for FunctionBindgen<'_, '_> {
13601375 ) ;
13611376 if self . gen . gen . opts . raw_strings {
13621377 results. push ( result) ;
1363- } else if unchecked {
1364- results. push ( format ! ( "String::from_utf8_unchecked({})" , result) ) ;
13651378 } 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) ;
13671394 }
13681395 }
13691396
0 commit comments