#![expect(non_camel_case_types)]
use {
isnt::std_1::primitive::IsntConstPtrExt,
std::{
ffi::{CStr, c_char, c_int, c_void},
ptr,
},
};
#[cfg(test)]
mod tests;
#[repr(C)]
pub struct wl_message {
pub name: *const c_char,
pub signature: *const c_char,
pub types: *const *const wl_interface,
}
unsafe impl Sync for wl_message {}
unsafe impl Send for wl_message {}
#[repr(C)]
pub struct wl_interface {
pub name: *const c_char,
pub version: c_int,
pub method_count: c_int,
pub methods: *const wl_message,
pub event_count: c_int,
pub events: *const wl_message,
}
unsafe impl Send for wl_interface {}
unsafe impl Sync for wl_interface {}
#[repr(C)]
pub struct wl_array {
pub size: usize,
pub alloc: usize,
pub data: *mut c_void,
}
unsafe impl Send for wl_array {}
unsafe impl Sync for wl_array {}
pub type wl_fixed_t = i32;
pub(crate) type wl_dispatcher_func_t = unsafe extern "C" fn(
user_data: *const c_void,
target: *mut c_void,
opcode: u32,
msg: *const wl_message,
args: *mut wl_argument,
) -> c_int;
#[repr(C)]
pub struct wl_object(());
#[derive(Copy, Clone)]
#[repr(C)]
pub union wl_argument {
pub i: i32,
pub u: u32,
pub f: wl_fixed_t,
pub s: *const c_char,
pub o: *mut wl_object,
pub n: u32,
pub a: *mut wl_array,
pub h: i32,
}
unsafe impl Send for wl_argument {}
unsafe impl Sync for wl_argument {}
#[repr(C)]
pub struct wl_display(());
#[repr(C)]
pub struct wl_proxy(());
#[repr(C)]
pub struct wl_event_queue(());
pub(crate) const WL_MARSHAL_FLAG_DESTROY: u32 = 1 << 0;
pub(crate) unsafe fn interface_compatible(l: &wl_interface, r: &wl_interface) -> bool {
if ptr::eq(l, r) {
return true;
}
macro_rules! cmp_sig {
($count:ident, $messages:ident) => {
if l.$count != r.$count {
return false;
}
for i in 0..l.$count as usize {
let l_msg = unsafe { &*l.$messages.add(i) };
let r_msg = unsafe { &*r.$messages.add(i) };
let l_sig = unsafe { CStr::from_ptr(l_msg.signature) };
let r_sig = unsafe { CStr::from_ptr(r_msg.signature) };
if l_sig != r_sig {
return false;
}
}
};
}
cmp_sig!(method_count, methods);
cmp_sig!(event_count, events);
for i in 0..l.event_count as usize {
let l_msg = unsafe { &*l.events.add(i) };
let r_msg = unsafe { &*r.events.add(i) };
let sig = unsafe { CStr::from_ptr(l_msg.signature) };
let mut idx = 0;
for &b in sig.to_bytes() {
if b == b'?' {
continue;
}
if b == b'o' || b == b'n' {
let l_if = unsafe { *l_msg.types.add(idx as usize) };
let r_if = unsafe { *r_msg.types.add(idx as usize) };
if l_if.is_null() != r_if.is_null() {
return false;
}
if l_if.is_not_null() {
let l_if = unsafe { &*l_if };
let r_if = unsafe { &*r_if };
if unsafe { !interface_compatible(l_if, r_if) } {
return false;
}
}
}
idx += 1;
}
}
true
}