Skip to content

Commit 66caf51

Browse files
committed
Automatic support for C-String literals
When `generate_cstr` is enabled, and the target rust version is >= 1.77, generate `c"..."` literals instead of the unsafe `from_bytes_with_nul_unchecked` calls.
1 parent d2e30fb commit 66caf51

File tree

5 files changed

+45
-21
lines changed

5 files changed

+45
-21
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/strings_cstr2.rs

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --rust-target=1.77 --generate-cstr
2+
3+
const char* MY_STRING_UTF8 = "Hello, world!";
4+
const char* MY_STRING_INTERIOR_NULL = "Hello,\0World!";
5+
const char* MY_STRING_NON_UTF8 = "ABCDE\xFF";

bindgen/codegen/mod.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -717,26 +717,38 @@ impl CodeGenerator for Var {
717717
let len = proc_macro2::Literal::usize_unsuffixed(
718718
cstr_bytes.len(),
719719
);
720+
let cstr =
721+
if options.generate_cstr && rust_features.const_cstr {
722+
CStr::from_bytes_with_nul(&cstr_bytes).ok()
723+
} else {
724+
None
725+
};
720726

721-
// TODO: Here we ignore the type we just made up, probably
722-
// we should refactor how the variable type and ty ID work.
723-
let array_ty = quote! { [u8; #len] };
724-
let cstr_ty = quote! { ::#prefix::ffi::CStr };
725-
726-
let bytes = proc_macro2::Literal::byte_string(&cstr_bytes);
727-
728-
if options.generate_cstr &&
729-
rust_features.const_cstr &&
730-
CStr::from_bytes_with_nul(&cstr_bytes).is_ok()
731-
{
732-
result.push(quote! {
733-
#(#attrs)*
734-
#[allow(unsafe_code)]
735-
pub const #canonical_ident: &#cstr_ty = unsafe {
736-
#cstr_ty::from_bytes_with_nul_unchecked(#bytes)
737-
};
738-
});
727+
if let Some(cstr) = cstr {
728+
let cstr_ty = quote! { ::#prefix::ffi::CStr };
729+
if rust_features.literal_cstr {
730+
let cstr = proc_macro2::Literal::c_string(&cstr);
731+
result.push(quote! {
732+
#(#attrs)*
733+
pub const #canonical_ident: &#cstr_ty = #cstr;
734+
});
735+
} else {
736+
let bytes =
737+
proc_macro2::Literal::byte_string(&cstr_bytes);
738+
result.push(quote! {
739+
#(#attrs)*
740+
#[allow(unsafe_code)]
741+
pub const #canonical_ident: &#cstr_ty = unsafe {
742+
#cstr_ty::from_bytes_with_nul_unchecked(#bytes)
743+
};
744+
});
745+
}
739746
} else {
747+
// TODO: Here we ignore the type we just made up, probably
748+
// we should refactor how the variable type and ty ID work.
749+
let array_ty = quote! { [u8; #len] };
750+
let bytes =
751+
proc_macro2::Literal::byte_string(&cstr_bytes);
740752
let lifetime =
741753
if true { None } else { Some(quote! { 'static }) }
742754
.into_iter();

bindgen/features.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ define_rust_targets! {
159159
ptr_metadata: #81513,
160160
layout_for_ptr: #69835,
161161
},
162-
Stable_1_77(77) => { offset_of: #106655 },
162+
Stable_1_77(77) => {
163+
offset_of: #106655,
164+
literal_cstr: #117472,
165+
},
163166
Stable_1_73(73) => { thiscall_abi: #42202 },
164167
Stable_1_71(71) => { c_unwind_abi: #106075 },
165168
Stable_1_68(68) => { abi_efiapi: #105795 },

0 commit comments

Comments
 (0)