Skip to content

Commit

Permalink
don't generate as_raw when containing mutable references
Browse files Browse the repository at this point in the history
  • Loading branch information
Timbals committed Jul 26, 2024
1 parent 9af2aba commit 87b5e12
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 81 deletions.
96 changes: 60 additions & 36 deletions generator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -1809,7 +1822,7 @@ impl Parser {
meta: &HashMap<&str, StructMeta>,
simple: &IndexSet<&str>,
s: &Struct,
) -> (Vec<Ident>, Vec<TokenStream>, Vec<TokenStream>) {
) -> (Vec<Ident>, Vec<TokenStream>, Option<Vec<TokenStream>>) {
let lens = s
.members
.iter()
Expand All @@ -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[..]) {
Expand Down Expand Up @@ -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[..]) {
Expand All @@ -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<Item = TokenStream> + 'a {
Expand All @@ -1940,26 +1957,33 @@ 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
pub struct #ident #type_params {
#(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
}
}

Expand Down
37 changes: 35 additions & 2 deletions openxr/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,40 @@ impl Action<Haptic> {
) -> 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(),
Expand All @@ -140,8 +174,7 @@ impl Action<Haptic> {
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(())
Expand Down
51 changes: 8 additions & 43 deletions openxr/src/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down

0 comments on commit 87b5e12

Please sign in to comment.