From 629b67e8171cf97966af5024aafdf6fb812962eb Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Mon, 1 May 2023 13:40:35 +0200 Subject: [PATCH] Switch to safe `CStr::from_bytes_until_nul` on sized `c_char` array wrapper Certain structs contain sized character arrays that are converted to `CStr` for convenient accss to the user and our `Debug` implementation using unsafe `CStr::from_ptr(...as_ptr())`. There is no need to round-trip to a pointer and possibly read out of bounds if the NUL-terminator index (string length) is instead searched for by the newly stabilized `CStr::from_bytes_until_nul()` fn since Rust 1.69 (which panics if no NUL-terminator is found before the end of the slice). Unfortunately `unsafe` is still needed to cast the array from a `c_char` (`i8` on most platforms) to `u8`, which is what `from_bytes_until_nul()` accepts. --- .github/workflows/ci.yml | 8 +-- Changelog.md | 2 +- README.md | 2 +- ash-rewrite/Cargo.toml | 2 +- ash-window/Cargo.toml | 2 +- ash-window/Changelog.md | 2 +- ash-window/README.md | 2 +- ash/Cargo.toml | 2 +- ash/src/vk/definitions.rs | 144 +++++++++++++++++++++++++------------- ash/src/vk/prelude.rs | 8 ++- generator/src/lib.rs | 4 +- 11 files changed, 115 insertions(+), 63 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab7db47d3..1bdbbf730 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,19 +11,19 @@ jobs: - run: cargo check --workspace --all-targets --all-features check_msrv: - name: Check ash MSRV (1.60.0) + name: Check ash MSRV (1.69.0) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.60.0 + - uses: dtolnay/rust-toolchain@1.69.0 - run: cargo check -p ash -p ash-rewrite --all-features check_ash_window_msrv: - name: Check ash-window MSRV (1.64.0) + name: Check ash-window MSRV (1.69.0) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.64.0 + - uses: dtolnay/rust-toolchain@1.69.0 - run: cargo check -p ash-window -p ash-examples --all-features # TODO: add a similar job for the rewrite once that generates code diff --git a/Changelog.md b/Changelog.md index ad7fe8ee7..827082ca7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -35,7 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Replaced builders with lifetimes/setters directly on Vulkan structs (#602) - Inlined struct setters (#602) -- Bumped MSRV from 1.59 to 1.60 (#709) +- Bumped MSRV from 1.59 to 1.69 (#709, #746) - Replaced `const fn name()` with associated `NAME` constants (#715) - Generic builders now automatically set `objecttype` to `::ObjectType` (#724) - `get_calibrated_timestamps()` now returns a single value for `max_deviation` (#738) diff --git a/README.md b/README.md index 235d48aee..56f3fe936 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A very lightweight wrapper around Vulkan [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) [![LICENSE](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE-APACHE) [![Join the chat at https://gitter.im/MaikKlein/ash](https://badges.gitter.im/MaikKlein/ash.svg)](https://gitter.im/MaikKlein/ash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html) +[![MSRV](https://img.shields.io/badge/rustc-1.69.0+-ab6000.svg)](https://blog.rust-lang.org/2023/04/20/Rust-1.69.0.html) ## Overview diff --git a/ash-rewrite/Cargo.toml b/ash-rewrite/Cargo.toml index 2f1c33ac1..77cdc05e4 100644 --- a/ash-rewrite/Cargo.toml +++ b/ash-rewrite/Cargo.toml @@ -18,7 +18,7 @@ categories = [ documentation = "https://docs.rs/ash" edition = "2021" # TODO: reevaluate, then update in ci.yml -rust-version = "1.60.0" +rust-version = "1.69.0" [dependencies] libloading = { version = "0.8", optional = true } diff --git a/ash-window/Cargo.toml b/ash-window/Cargo.toml index 761bf645a..254c8d05d 100644 --- a/ash-window/Cargo.toml +++ b/ash-window/Cargo.toml @@ -16,7 +16,7 @@ categories = [ "rendering::graphics-api" ] edition = "2021" -rust-version = "1.64.0" +rust-version = "1.69.0" [dependencies] ash = { path = "../ash", version = "0.37", default-features = false } diff --git a/ash-window/Changelog.md b/ash-window/Changelog.md index bf8716f5d..557300eee 100644 --- a/ash-window/Changelog.md +++ b/ash-window/Changelog.md @@ -2,7 +2,7 @@ ## [Unreleased] - ReleaseDate -- Bumped MSRV from 1.59 to 1.64 for `winit 0.28` and `raw-window-handle 0.5.1`. (#709, #716) +- Bumped MSRV from 1.59 to 1.69 for `winit 0.28` and `raw-window-handle 0.5.1`, and `CStr::from_bytes_until_nul`. (#709, #716, #746) ## [0.12.0] - 2022-09-23 diff --git a/ash-window/README.md b/ash-window/README.md index b683999ac..307222874 100644 --- a/ash-window/README.md +++ b/ash-window/README.md @@ -8,7 +8,7 @@ Interoperability between [`ash`](https://github.com/ash-rs/ash) and [`raw-window [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) [![LICENSE](https://img.shields.io/badge/license-apache-blue.svg)](LICENSE-APACHE) [![Join the chat at https://gitter.im/MaikKlein/ash](https://badges.gitter.im/MaikKlein/ash.svg)](https://gitter.im/MaikKlein/ash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![MSRV](https://img.shields.io/badge/rustc-1.64.0+-ab6000.svg)](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html) +[![MSRV](https://img.shields.io/badge/rustc-1.69.0+-ab6000.svg)](https://blog.rust-lang.org/2023/04/20/Rust-1.69.0.html) ## Usage diff --git a/ash/Cargo.toml b/ash/Cargo.toml index 19952f37b..d58db429e 100644 --- a/ash/Cargo.toml +++ b/ash/Cargo.toml @@ -19,7 +19,7 @@ categories = [ "rendering::graphics-api" ] edition = "2021" -rust-version = "1.60.0" +rust-version = "1.69.0" [dependencies] libloading = { version = "0.8", optional = true } diff --git a/ash/src/vk/definitions.rs b/ash/src/vk/definitions.rs index 97b2f5359..85497f0b8 100644 --- a/ash/src/vk/definitions.rs +++ b/ash/src/vk/definitions.rs @@ -817,7 +817,7 @@ impl fmt::Debug for PhysicalDeviceProperties { .field("vendor_id", &self.vendor_id) .field("device_id", &self.device_id) .field("device_type", &self.device_type) - .field("device_name", &unsafe { self.device_name_as_cstr() }) + .field("device_name", &self.device_name_as_cstr()) .field("pipeline_cache_uuid", &self.pipeline_cache_uuid) .field("limits", &self.limits) .field("sparse_properties", &self.sparse_properties) @@ -872,7 +872,9 @@ impl PhysicalDeviceProperties { self } #[inline] - pub unsafe fn device_name_as_cstr(&self) -> &core::ffi::CStr { + pub fn device_name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.device_name) } #[inline] @@ -902,7 +904,7 @@ pub struct ExtensionProperties { impl fmt::Debug for ExtensionProperties { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("ExtensionProperties") - .field("extension_name", &unsafe { self.extension_name_as_cstr() }) + .field("extension_name", &self.extension_name_as_cstr()) .field("spec_version", &self.spec_version) .finish() } @@ -923,7 +925,9 @@ impl ExtensionProperties { self } #[inline] - pub unsafe fn extension_name_as_cstr(&self) -> &core::ffi::CStr { + pub fn extension_name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.extension_name) } #[inline] @@ -945,10 +949,10 @@ pub struct LayerProperties { impl fmt::Debug for LayerProperties { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("LayerProperties") - .field("layer_name", &unsafe { self.layer_name_as_cstr() }) + .field("layer_name", &self.layer_name_as_cstr()) .field("spec_version", &self.spec_version) .field("implementation_version", &self.implementation_version) - .field("description", &unsafe { self.description_as_cstr() }) + .field("description", &self.description_as_cstr()) .finish() } } @@ -970,7 +974,9 @@ impl LayerProperties { self } #[inline] - pub unsafe fn layer_name_as_cstr(&self) -> &core::ffi::CStr { + pub fn layer_name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.layer_name) } #[inline] @@ -989,7 +995,9 @@ impl LayerProperties { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } } @@ -10940,8 +10948,8 @@ impl fmt::Debug for PhysicalDeviceDriverProperties<'_> { .field("s_type", &self.s_type) .field("p_next", &self.p_next) .field("driver_id", &self.driver_id) - .field("driver_name", &unsafe { self.driver_name_as_cstr() }) - .field("driver_info", &unsafe { self.driver_info_as_cstr() }) + .field("driver_name", &self.driver_name_as_cstr()) + .field("driver_info", &self.driver_info_as_cstr()) .field("conformance_version", &self.conformance_version) .finish() } @@ -10976,7 +10984,9 @@ impl<'a> PhysicalDeviceDriverProperties<'a> { self } #[inline] - pub unsafe fn driver_name_as_cstr(&self) -> &core::ffi::CStr { + pub fn driver_name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.driver_name) } #[inline] @@ -10985,7 +10995,9 @@ impl<'a> PhysicalDeviceDriverProperties<'a> { self } #[inline] - pub unsafe fn driver_info_as_cstr(&self) -> &core::ffi::CStr { + pub fn driver_info_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.driver_info) } #[inline] @@ -27116,9 +27128,9 @@ impl fmt::Debug for PerformanceCounterDescriptionKHR<'_> { .field("s_type", &self.s_type) .field("p_next", &self.p_next) .field("flags", &self.flags) - .field("name", &unsafe { self.name_as_cstr() }) - .field("category", &unsafe { self.category_as_cstr() }) - .field("description", &unsafe { self.description_as_cstr() }) + .field("name", &self.name_as_cstr()) + .field("category", &self.category_as_cstr()) + .field("description", &self.description_as_cstr()) .finish() } } @@ -27151,7 +27163,9 @@ impl<'a> PerformanceCounterDescriptionKHR<'a> { self } #[inline] - pub unsafe fn name_as_cstr(&self) -> &core::ffi::CStr { + pub fn name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.name) } #[inline] @@ -27160,7 +27174,9 @@ impl<'a> PerformanceCounterDescriptionKHR<'a> { self } #[inline] - pub unsafe fn category_as_cstr(&self) -> &core::ffi::CStr { + pub fn category_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.category) } #[inline] @@ -27169,7 +27185,9 @@ impl<'a> PerformanceCounterDescriptionKHR<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } } @@ -28209,8 +28227,8 @@ impl fmt::Debug for PipelineExecutablePropertiesKHR<'_> { .field("s_type", &self.s_type) .field("p_next", &self.p_next) .field("stages", &self.stages) - .field("name", &unsafe { self.name_as_cstr() }) - .field("description", &unsafe { self.description_as_cstr() }) + .field("name", &self.name_as_cstr()) + .field("description", &self.description_as_cstr()) .field("subgroup_size", &self.subgroup_size) .finish() } @@ -28244,7 +28262,9 @@ impl<'a> PipelineExecutablePropertiesKHR<'a> { self } #[inline] - pub unsafe fn name_as_cstr(&self) -> &core::ffi::CStr { + pub fn name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.name) } #[inline] @@ -28253,7 +28273,9 @@ impl<'a> PipelineExecutablePropertiesKHR<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -28333,8 +28355,8 @@ impl fmt::Debug for PipelineExecutableStatisticKHR<'_> { fmt.debug_struct("PipelineExecutableStatisticKHR") .field("s_type", &self.s_type) .field("p_next", &self.p_next) - .field("name", &unsafe { self.name_as_cstr() }) - .field("description", &unsafe { self.description_as_cstr() }) + .field("name", &self.name_as_cstr()) + .field("description", &self.description_as_cstr()) .field("format", &self.format) .field("value", &"union") .finish() @@ -28364,7 +28386,9 @@ impl<'a> PipelineExecutableStatisticKHR<'a> { self } #[inline] - pub unsafe fn name_as_cstr(&self) -> &core::ffi::CStr { + pub fn name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.name) } #[inline] @@ -28373,7 +28397,9 @@ impl<'a> PipelineExecutableStatisticKHR<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -28406,8 +28432,8 @@ impl fmt::Debug for PipelineExecutableInternalRepresentationKHR<'_> { fmt.debug_struct("PipelineExecutableInternalRepresentationKHR") .field("s_type", &self.s_type) .field("p_next", &self.p_next) - .field("name", &unsafe { self.name_as_cstr() }) - .field("description", &unsafe { self.description_as_cstr() }) + .field("name", &self.name_as_cstr()) + .field("description", &self.description_as_cstr()) .field("is_text", &self.is_text) .field("data_size", &self.data_size) .field("p_data", &self.p_data) @@ -28440,7 +28466,9 @@ impl<'a> PipelineExecutableInternalRepresentationKHR<'a> { self } #[inline] - pub unsafe fn name_as_cstr(&self) -> &core::ffi::CStr { + pub fn name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.name) } #[inline] @@ -28449,7 +28477,9 @@ impl<'a> PipelineExecutableInternalRepresentationKHR<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -29918,8 +29948,8 @@ impl fmt::Debug for PhysicalDeviceVulkan12Properties<'_> { .field("s_type", &self.s_type) .field("p_next", &self.p_next) .field("driver_id", &self.driver_id) - .field("driver_name", &unsafe { self.driver_name_as_cstr() }) - .field("driver_info", &unsafe { self.driver_info_as_cstr() }) + .field("driver_name", &self.driver_name_as_cstr()) + .field("driver_info", &self.driver_info_as_cstr()) .field("conformance_version", &self.conformance_version) .field( "denorm_behavior_independence", @@ -30188,7 +30218,9 @@ impl<'a> PhysicalDeviceVulkan12Properties<'a> { self } #[inline] - pub unsafe fn driver_name_as_cstr(&self) -> &core::ffi::CStr { + pub fn driver_name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.driver_name) } #[inline] @@ -30197,7 +30229,9 @@ impl<'a> PhysicalDeviceVulkan12Properties<'a> { self } #[inline] - pub unsafe fn driver_info_as_cstr(&self) -> &core::ffi::CStr { + pub fn driver_info_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.driver_info) } #[inline] @@ -31278,11 +31312,11 @@ impl fmt::Debug for PhysicalDeviceToolProperties<'_> { fmt.debug_struct("PhysicalDeviceToolProperties") .field("s_type", &self.s_type) .field("p_next", &self.p_next) - .field("name", &unsafe { self.name_as_cstr() }) - .field("version", &unsafe { self.version_as_cstr() }) + .field("name", &self.name_as_cstr()) + .field("version", &self.version_as_cstr()) .field("purposes", &self.purposes) - .field("description", &unsafe { self.description_as_cstr() }) - .field("layer", &unsafe { self.layer_as_cstr() }) + .field("description", &self.description_as_cstr()) + .field("layer", &self.layer_as_cstr()) .finish() } } @@ -31311,7 +31345,9 @@ impl<'a> PhysicalDeviceToolProperties<'a> { self } #[inline] - pub unsafe fn name_as_cstr(&self) -> &core::ffi::CStr { + pub fn name_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.name) } #[inline] @@ -31320,7 +31356,9 @@ impl<'a> PhysicalDeviceToolProperties<'a> { self } #[inline] - pub unsafe fn version_as_cstr(&self) -> &core::ffi::CStr { + pub fn version_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.version) } #[inline] @@ -31334,7 +31372,9 @@ impl<'a> PhysicalDeviceToolProperties<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -31343,7 +31383,9 @@ impl<'a> PhysicalDeviceToolProperties<'a> { self } #[inline] - pub unsafe fn layer_as_cstr(&self) -> &core::ffi::CStr { + pub fn layer_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.layer) } } @@ -45775,7 +45817,7 @@ impl fmt::Debug for RenderPassSubpassFeedbackInfoEXT { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("RenderPassSubpassFeedbackInfoEXT") .field("subpass_merge_status", &self.subpass_merge_status) - .field("description", &unsafe { self.description_as_cstr() }) + .field("description", &self.description_as_cstr()) .field("post_merge_index", &self.post_merge_index) .finish() } @@ -45802,7 +45844,9 @@ impl RenderPassSubpassFeedbackInfoEXT { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -48548,7 +48592,7 @@ pub struct DeviceFaultVendorInfoEXT { impl fmt::Debug for DeviceFaultVendorInfoEXT { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("DeviceFaultVendorInfoEXT") - .field("description", &unsafe { self.description_as_cstr() }) + .field("description", &self.description_as_cstr()) .field("vendor_fault_code", &self.vendor_fault_code) .field("vendor_fault_data", &self.vendor_fault_data) .finish() @@ -48571,7 +48615,9 @@ impl DeviceFaultVendorInfoEXT { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] @@ -48648,7 +48694,7 @@ impl fmt::Debug for DeviceFaultInfoEXT<'_> { fmt.debug_struct("DeviceFaultInfoEXT") .field("s_type", &self.s_type) .field("p_next", &self.p_next) - .field("description", &unsafe { self.description_as_cstr() }) + .field("description", &self.description_as_cstr()) .field("p_address_infos", &self.p_address_infos) .field("p_vendor_infos", &self.p_vendor_infos) .field("p_vendor_binary_data", &self.p_vendor_binary_data) @@ -48679,7 +48725,9 @@ impl<'a> DeviceFaultInfoEXT<'a> { self } #[inline] - pub unsafe fn description_as_cstr(&self) -> &core::ffi::CStr { + pub fn description_as_cstr( + &self, + ) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.description) } #[inline] diff --git a/ash/src/vk/prelude.rs b/ash/src/vk/prelude.rs index 3166629d5..5f710938a 100644 --- a/ash/src/vk/prelude.rs +++ b/ash/src/vk/prelude.rs @@ -61,8 +61,12 @@ pub unsafe trait TaggedStructure { } #[inline] -pub(crate) unsafe fn wrap_cstr_slice_until_nul(str: &[core::ffi::c_char]) -> &core::ffi::CStr { - core::ffi::CStr::from_ptr(str.as_ptr()) +pub(crate) fn wrap_cstr_slice_until_nul( + str: &[core::ffi::c_char], +) -> Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { + // SAFETY: The cast from c_char to u8 is ok because a c_char is always one byte. + let bytes = unsafe { core::slice::from_raw_parts(str.as_ptr().cast(), str.len()) }; + core::ffi::CStr::from_bytes_until_nul(bytes) } #[inline] diff --git a/generator/src/lib.rs b/generator/src/lib.rs index 8c26b7eeb..5bac79037 100644 --- a/generator/src/lib.rs +++ b/generator/src/lib.rs @@ -1823,7 +1823,7 @@ fn derive_debug( let param_str = param_ident.to_string(); let debug_value = if is_static_array(field) && field.basetype == "char" { let param_ident = format_ident!("{}_as_cstr", param_ident); - quote!(&unsafe { self.#param_ident() }) + quote!(&self.#param_ident()) } else if param_str.contains("pfn") { quote!(&(self.#param_ident.map(|x| x as *const ()))) } else if union_types.contains(field.basetype.as_str()) { @@ -2009,7 +2009,7 @@ fn derive_setters( } #[inline] #deprecated - pub unsafe fn #param_ident_as_cstr(&self) -> &core::ffi::CStr { + pub fn #param_ident_as_cstr(&self) -> core::result::Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> { wrap_cstr_slice_until_nul(&self.#param_ident) } });