From 87b5e1273395c443c9b3eab94f70b615124de3c1 Mon Sep 17 00:00:00 2001 From: Tim Balsfulland Date: Fri, 26 Jul 2024 14:30:33 +0200 Subject: [PATCH] don't generate `as_raw` when containing mutable references --- generator/src/main.rs | 96 +++++++++++++++++++++++++---------------- openxr/src/action.rs | 37 +++++++++++++++- openxr/src/generated.rs | 51 ++++------------------ 3 files changed, 103 insertions(+), 81 deletions(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 447b215..64fde3d 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1738,6 +1738,7 @@ impl Parser { let mut variants = Vec::new(); let mut as_raw = Vec::new(); + let mut as_ref_possible = true; let mut raw_variants = Vec::new(); for name in children { @@ -1763,33 +1764,45 @@ impl Parser { Span::call_site(), ); - let inits = inits.chain(fields_as_raw); - as_raw.push(quote! { - #base_ident::#variant_ident { - #(#fields_ident),* - } => #raw_ident { - #snake_case_variant_ident: sys::#ident { - #(#inits),* + if let Some(fields_as_raw) = fields_as_raw { + let inits = inits.chain(fields_as_raw); + as_raw.push(quote! { + #base_ident::#variant_ident { + #(#fields_ident),* + } => #raw_ident { + #snake_case_variant_ident: sys::#ident { + #(#inits),* + } } - } - }); + }); + } else { + as_ref_possible = false; + } - raw_variants.push(quote! { #snake_case_variant_ident: sys::#ident }); + raw_variants.push(quote! { pub(crate) #snake_case_variant_ident: sys::#ident }); } + let as_ref_impl = if as_ref_possible { + quote! { + impl #type_params #base_ident #type_args { + pub(crate) fn as_raw(&self) -> #raw_ident { + match self { + #(#as_raw),* + } + } + } + } + } else { + quote! {} + }; + quote! { #[non_exhaustive] pub enum #base_ident #type_params { #(#variants),* } - impl #type_params #base_ident #type_args { - pub(crate) fn as_raw(&self) -> #raw_ident { - match self { - #(#as_raw),* - } - } - } + #as_ref_impl #[repr(C)] pub(crate) union #raw_ident { @@ -1809,7 +1822,7 @@ impl Parser { meta: &HashMap<&str, StructMeta>, simple: &IndexSet<&str>, s: &Struct, - ) -> (Vec, Vec, Vec) { + ) -> (Vec, Vec, Option>) { let lens = s .members .iter() @@ -1821,6 +1834,7 @@ impl Parser { let mut fields_ident = Vec::new(); let mut fields_defs = Vec::new(); let mut fields_as_raw = Vec::new(); + let mut as_ref_possible = true; for m in &s.members { if m.name == "type" || m.name == "next" || lens.contains(&m.name[..]) { @@ -1884,13 +1898,12 @@ impl Parser { quote! { #ident: *#ident }, ) } else { + // going from `&&mut T` to `*mut T` is not sound, + // so don't generate an ´as_ref` implementation + as_ref_possible = false; ( quote! { #ident: &'a mut #ty #type_args }, - // TODO not sound - // https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=630c7d6aaac22feb47abba7913ad5ed9 - // is this still invalid when passed through FFI? -> probably yes - // quote! { #ident: *#ident as *const _ as *mut _ }, - quote! { #ident: std::ptr::null_mut() }, + quote! { /* not possible */ }, ) } } else if self.structs.contains_key(&m.ty) && !simple.contains(&m.ty[..]) { @@ -1913,7 +1926,11 @@ impl Parser { fields_as_raw.push(as_raw); } - (fields_ident, fields_defs, fields_as_raw) + ( + fields_ident, + fields_defs, + as_ref_possible.then_some(fields_as_raw), + ) } fn generate_inits<'a>(&self, s: &'a Struct) -> impl Iterator + 'a { @@ -1940,9 +1957,25 @@ impl Parser { let (fields_ident, fields_defs, fields_as_raw) = self.generate_member_data(meta, simple, s); let ident = xr_ty_name(name); let (type_params, type_args) = meta.get(name).unwrap().type_params(); - let inits = self.generate_inits(s).chain(fields_as_raw); let conds = conditions(name, s.extension.as_ref().map(|x| &x[..])); - let conds2 = conds.clone(); + let as_ref_impl = if let Some(fields_as_raw) = fields_as_raw { + let inits = self.generate_inits(s).chain(fields_as_raw); + let conds2 = conds.clone(); + quote! { + #conds2 + impl #type_params #ident #type_args { + #[inline] + pub fn as_raw(&self) -> sys::#ident { + let Self { #(#fields_ident),* } = self; + sys::#ident { + #(#inits),* + } + } + } + } + } else { + quote! {} + }; quote! { #[derive(Copy, Clone)] #conds @@ -1950,16 +1983,7 @@ impl Parser { #(pub #fields_defs),* } - #conds2 - impl #type_params #ident #type_args { - #[inline] - pub fn as_raw(&self) -> sys::#ident { - let Self { #(#fields_ident),* } = self; - sys::#ident { - #(#inits),* - } - } - } + #as_ref_impl } } diff --git a/openxr/src/action.rs b/openxr/src/action.rs index a743d44..36a2052 100644 --- a/openxr/src/action.rs +++ b/openxr/src/action.rs @@ -130,6 +130,40 @@ impl Action { ) -> Result<()> { self.assert_event_validity(&data); + // There is no generated `as_raw` function because `samples_consumed` is a mut reference, + // which can't be safely converted to `*mut u32` though a `&HapticData`. + let data = match data { + HapticData::Vibration { + duration, + frequency, + amplitude, + } => builder::HapticDataRaw { + vibration: sys::HapticVibration { + ty: sys::HapticVibration::TYPE, + next: ptr::null_mut(), + duration, + frequency, + amplitude, + }, + }, + HapticData::PcmVibrationFB { + buffer, + sample_rate, + append, + samples_consumed, + } => builder::HapticDataRaw { + pcm_vibration_fb: sys::HapticPcmVibrationFB { + ty: sys::HapticPcmVibrationFB::TYPE, + next: ptr::null_mut(), + buffer_size: buffer.len() as _, + buffer: buffer.as_ptr(), + sample_rate, + append: append.into(), + samples_consumed, + }, + }, + }; + let info = sys::HapticActionInfo { ty: sys::HapticActionInfo::TYPE, next: ptr::null(), @@ -140,8 +174,7 @@ impl Action { cvt((self.fp().apply_haptic_feedback)( session.as_raw(), &info, - // TODO `samples_consumed` pointer is not set - data.as_raw().as_base(), + data.as_base(), ))?; } Ok(()) diff --git a/openxr/src/generated.rs b/openxr/src/generated.rs index f3461c9..00e98b3 100644 --- a/openxr/src/generated.rs +++ b/openxr/src/generated.rs @@ -6768,12 +6768,12 @@ pub(crate) mod builder { } #[repr(C)] pub(crate) union CompositionLayerRaw { - projection: sys::CompositionLayerProjection, - quad: sys::CompositionLayerQuad, - cylinder_khr: sys::CompositionLayerCylinderKHR, - cube_khr: sys::CompositionLayerCubeKHR, - equirect_khr: sys::CompositionLayerEquirectKHR, - equirect2_khr: sys::CompositionLayerEquirect2KHR, + pub(crate) projection: sys::CompositionLayerProjection, + pub(crate) quad: sys::CompositionLayerQuad, + pub(crate) cylinder_khr: sys::CompositionLayerCylinderKHR, + pub(crate) cube_khr: sys::CompositionLayerCubeKHR, + pub(crate) equirect_khr: sys::CompositionLayerEquirectKHR, + pub(crate) equirect2_khr: sys::CompositionLayerEquirect2KHR, } impl CompositionLayerRaw { pub(crate) fn as_base(&self) -> *const sys::CompositionLayerBaseHeader { @@ -6794,45 +6794,10 @@ pub(crate) mod builder { samples_consumed: &'a mut u32, }, } - impl<'a> HapticData<'a> { - pub(crate) fn as_raw(&self) -> HapticDataRaw { - match self { - HapticData::Vibration { - duration, - frequency, - amplitude, - } => HapticDataRaw { - vibration: sys::HapticVibration { - ty: sys::StructureType::HAPTIC_VIBRATION, - next: std::ptr::null_mut(), - duration: *duration, - frequency: *frequency, - amplitude: *amplitude, - }, - }, - HapticData::PcmVibrationFB { - buffer, - sample_rate, - append, - samples_consumed, - } => HapticDataRaw { - pcm_vibration_fb: sys::HapticPcmVibrationFB { - ty: sys::StructureType::HAPTIC_PCM_VIBRATION_FB, - next: std::ptr::null_mut(), - buffer_size: buffer.len() as _, - buffer: buffer.as_ptr() as _, - sample_rate: *sample_rate, - append: (*append).into(), - samples_consumed: std::ptr::null_mut(), - }, - }, - } - } - } #[repr(C)] pub(crate) union HapticDataRaw { - vibration: sys::HapticVibration, - pcm_vibration_fb: sys::HapticPcmVibrationFB, + pub(crate) vibration: sys::HapticVibration, + pub(crate) pcm_vibration_fb: sys::HapticPcmVibrationFB, } impl HapticDataRaw { pub(crate) fn as_base(&self) -> *const sys::HapticBaseHeader {