1use crate::prelude::*;
2
3#[macro_export]
28macro_rules! wl_array_for_each {
29 ($pos:ident: *const $T:ty, $array:expr, $body:block) => {
30 for $pos in $crate::_macro_helpers::WlArrayForEachIter::<$T>::new($array) {
31 let $pos = $pos.as_ptr().cast_const();
32 $body
33 }
34 };
35 ($pos:ident: *mut $T:ty, $array:expr, $body:block) => {
36 for $pos in $crate::_macro_helpers::WlArrayForEachIter::<$T>::new($array) {
37 let $pos = $pos.as_ptr();
38 $body
39 }
40 };
41}
42pub use wl_array_for_each;
43
44#[macro_export]
51macro_rules! wl_container_of {
52 ($ptr:expr, *const $Container:ty, $member:ident) => {{
53 let ptr: *const _ = $ptr;
54 let ptr = ptr.cast::<$crate::_macro_helpers::u8>();
55 let offset = $crate::_macro_helpers::offset_of!($Container, $member);
56 ptr.sub(offset).cast::<$Container>()
57 }};
58 ($ptr:expr, *mut $Container:ty, $member:ident) => {{
59 let ptr: *const _ = $ptr;
60 let ptr = ptr.cast::<$crate::_macro_helpers::u8>();
61 let offset = $crate::_macro_helpers::offset_of!($Container, $member);
62 ptr.sub(offset).cast::<$Container>().cast_mut()
63 }};
64}
65pub use wl_container_of;
66
67#[macro_export]
102macro_rules! wl_list_for_each {
103 ($pos:ident: *const $T:ty, $head:expr, $member:ident, $body:block) => {
104 for $pos in $crate::_macro_helpers::WlListForEachIter::new($head) {
105 let $pos = $crate::wl_container_of!($pos.as_ptr(), *const $T, $member);
106 $body
107 }
108 };
109 ($pos:ident: *mut $T:ty, $head:expr, $member:ident, $body:block) => {
110 for $pos in $crate::_macro_helpers::WlListForEachIter::new($head) {
111 let $pos = $crate::wl_container_of!($pos.as_ptr(), *mut $T, $member);
112 $body
113 }
114 };
115}
116pub use wl_list_for_each;
117
118#[macro_export]
153macro_rules! wl_list_for_each_reverse {
154 ($pos:ident: *const $T:ty, $head:expr, $member:ident, $body:block) => {
155 for $pos in $crate::_macro_helpers::WlListForEachReverseIter::new($head) {
156 let $pos = $crate::wl_container_of!($pos.as_ptr(), *const $T, $member);
157 $body
158 }
159 };
160 ($pos:ident: *mut $T:ty, $head:expr, $member:ident, $body:block) => {
161 for $pos in $crate::_macro_helpers::WlListForEachReverseIter::new($head) {
162 let $pos = $crate::wl_container_of!($pos.as_ptr(), *mut $T, $member);
163 $body
164 }
165 };
166}
167pub use wl_list_for_each_reverse;
168
169#[macro_export]
206macro_rules! wl_list_for_each_reverse_safe {
207 ($pos:ident: *const $T:ty, $head:expr, $member:ident, $body:block) => {
208 for $pos in $crate::_macro_helpers::WlListForEachReverseSafeIter::new($head) {
209 let $pos = $crate::wl_container_of!($pos.as_ptr(), *const $T, $member);
210 $body
211 }
212 };
213 ($pos:ident: *mut $T:ty, $head:expr, $member:ident, $body:block) => {
214 for $pos in $crate::_macro_helpers::WlListForEachReverseSafeIter::new($head) {
215 let $pos = $crate::wl_container_of!($pos.as_ptr(), *mut $T, $member);
216 $body
217 }
218 };
219}
220pub use wl_list_for_each_reverse_safe;
221
222#[macro_export]
259macro_rules! wl_list_for_each_safe {
260 ($pos:ident: *const $T:ty, $head:expr, $member:ident, $body:block) => {
261 for $pos in $crate::_macro_helpers::WlListForEachSafeIter::new($head) {
262 let $pos = $crate::wl_container_of!($pos.as_ptr(), *const $T, $member);
263 $body
264 }
265 };
266 ($pos:ident: *mut $T:ty, $head:expr, $member:ident, $body:block) => {
267 for $pos in $crate::_macro_helpers::WlListForEachSafeIter::new($head) {
268 let $pos = $crate::wl_container_of!($pos.as_ptr(), *mut $T, $member);
269 $body
270 }
271 };
272}
273pub use wl_list_for_each_safe;
274
275#[derive(Clone, Copy)]
276#[repr(C)]
277pub struct wl_array {
278 pub size: usize,
279 pub alloc: usize,
280 pub data: *mut c_void,
281}
282
283#[derive(Clone, Copy)]
284#[repr(C)]
285pub struct wl_interface {
286 pub name: *const c_char,
287 pub version: c_int,
288 pub method_count: c_int,
289 pub methods: *const wl_message,
290 pub event_count: c_int,
291 pub events: *const wl_message,
292}
293
294#[derive(Clone, Copy)]
295#[repr(C)]
296pub struct wl_list {
297 pub prev: *mut wl_list,
298 pub next: *mut wl_list,
299}
300
301#[derive(Clone, Copy)]
302#[repr(C)]
303pub struct wl_message {
304 pub name: *const c_char,
305 pub signature: *const c_char,
306 pub types: *mut *const wl_interface,
307}
308
309#[repr(C)]
310pub struct wl_object {
311 _data: (),
312 _marker: PhantomData<(*mut u8, PhantomPinned)>,
313}
314
315pub const WL_ITERATOR_CONTINUE: wl_iterator_result = 1;
316pub const WL_ITERATOR_STOP: wl_iterator_result = 0;
317
318unsafe extern "C" {
319 pub fn wl_array_add(array: *mut wl_array, size: usize) -> *mut c_void;
320
321 pub fn wl_array_copy(array: *mut wl_array, source: *mut wl_array) -> c_int;
322
323 pub fn wl_array_init(array: *mut wl_array);
324
325 pub fn wl_array_release(array: *mut wl_array);
326}
327
328#[inline]
329pub extern "C" fn wl_fixed_from_double(d: c_double) -> wl_fixed_t {
330 let d = d + ((3i64 << (51 - 8)) as c_double);
331 d.to_bits() as wl_fixed_t
332}
333
334#[inline]
335pub extern "C" fn wl_fixed_from_int(i: c_int) -> wl_fixed_t {
336 i * 256
337}
338
339#[inline]
340pub extern "C" fn wl_fixed_to_double(f: wl_fixed_t) -> c_double {
341 let i = ((1023i64 + 44i64) << 52) + (1i64 << 51) + (f as i64);
342 c_double::from_bits(i as u64) - ((3i64 << 43) as c_double)
343}
344
345#[inline]
346pub extern "C" fn wl_fixed_to_int(f: wl_fixed_t) -> c_int {
347 f / 256
348}
349
350unsafe extern "C" {
351 pub fn wl_list_empty(list: *const wl_list) -> c_int;
352
353 pub fn wl_list_init(list: *mut wl_list);
354
355 pub fn wl_list_insert(list: *mut wl_list, elm: *mut wl_list);
356
357 pub fn wl_list_insert_list(list: *mut wl_list, other: *mut wl_list);
358
359 pub fn wl_list_length(list: *const wl_list) -> c_int;
360
361 pub fn wl_list_remove(elm: *mut wl_list);
362}
363
364pub type wl_dispatcher_func_t = Option<
365 unsafe extern "C" fn(
366 _: *const c_void,
367 _: *mut c_void,
368 _: u32,
369 _: *const wl_message,
370 _: *mut wl_argument,
371 ) -> c_int,
372>;
373
374pub type wl_fixed_t = i32;
375pub type wl_iterator_result = c_int;
376
377pub type wl_log_func_t = Option<
378 unsafe extern "C" fn(
379 _: *const c_char,
380 _: *mut c_void, ),
382>;
383
384#[repr(C)]
385pub union wl_argument {
386 pub i: i32,
387 pub u: u32,
388 pub f: wl_fixed_t,
389 pub s: *const c_char,
390 pub o: *mut wl_object,
391 pub n: u32,
392 pub a: *mut wl_array,
393 pub h: i32,
394}
395
396#[cfg(test)]
397mod tests {
398 use core::{mem::MaybeUninit, ptr::null_mut};
399
400 use super::*;
401
402 #[link(name = "wayland-client")]
403 unsafe extern "C" {}
404
405 struct Foo {
406 _m: i32,
407 link: wl_list,
408 }
409
410 impl Foo {
411 fn new() -> Self {
412 Self {
413 _m: 0,
414 link: wl_list {
415 prev: null_mut(),
416 next: null_mut(),
417 },
418 }
419 }
420 }
421
422 #[test]
423 fn test_wl_array_for_each() {
424 unsafe {
425 let mut array = MaybeUninit::uninit();
426 wl_array_init(array.as_mut_ptr());
427 let data = wl_array_add(array.as_mut_ptr(), size_of::<Foo>() * 3);
428
429 let mut i = 0;
430 wl_array_for_each!(foo: *const Foo, array.as_ptr(), {
431 assert!(i < 3);
432 assert_eq!(foo, data.cast::<Foo>().add(i));
433 i += 1;
434 });
435 assert_eq!(i, 3);
436
437 let mut i = 0;
438 wl_array_for_each!(foo: *mut Foo, array.as_ptr(), {
439 assert!(i < 3);
440 assert_eq!(foo, data.cast::<Foo>().add(i));
441 i += 1;
442 });
443 assert_eq!(i, 3);
444
445 wl_array_release(array.as_mut_ptr());
446 }
447 }
448
449 #[test]
450 fn test_wl_container_of() {
451 let mut foo = Foo::new();
452 assert_eq!(
453 unsafe { wl_container_of!(&foo.link, *const Foo, link) },
454 &raw const foo
455 );
456 assert_eq!(
457 unsafe { wl_container_of!(&foo.link, *mut Foo, link) },
458 &raw mut foo
459 );
460 }
461
462 fn with_test_list<F>(f: F)
463 where
464 F: FnOnce(&mut wl_list, [&mut Foo; 3]),
465 {
466 unsafe {
467 let mut list = MaybeUninit::uninit();
468 wl_list_init(list.as_mut_ptr());
469 let list = &mut *list.as_mut_ptr();
470
471 let mut e1 = Foo::new();
472 wl_list_insert(list, &mut e1.link);
473
474 let mut e2 = Foo::new();
475 wl_list_insert(&mut e1.link, &mut e2.link);
476
477 let mut e3 = Foo::new();
478 wl_list_insert(&mut e2.link, &mut e3.link);
479
480 f(list, [&mut e1, &mut e2, &mut e3]);
481 }
482 }
483
484 #[test]
485 fn test_wl_list_for_each() {
486 with_test_list(|list, elems| unsafe {
487 let mut i = 0;
488 wl_list_for_each!(foo: *const Foo, list, link, {
489 assert_eq!(foo, elems[i] as *const _);
490 i += 1;
491 });
492 assert_eq!(i, 3);
493
494 let mut i = 0;
495 wl_list_for_each!(foo: *mut Foo, list, link, {
496 assert_eq!(foo, elems[i] as *mut _);
497 i += 1;
498 });
499 assert_eq!(i, 3);
500 });
501 }
502
503 #[test]
504 fn test_wl_list_for_each_reverse() {
505 with_test_list(|list, elems| unsafe {
506 let mut i = elems.len();
507 wl_list_for_each_reverse!(foo: *const Foo, list, link, {
508 i -= 1;
509 assert_eq!(foo, elems[i] as *const _);
510 });
511 assert_eq!(i, 0);
512
513 let mut i = elems.len();
514 wl_list_for_each_reverse!(foo: *mut Foo, list, link, {
515 i -= 1;
516 assert_eq!(foo, elems[i] as *mut _);
517 });
518 assert_eq!(i, 0);
519 });
520 }
521
522 #[test]
523 fn test_wl_list_for_each_reverse_safe() {
524 with_test_list(|list, elems| unsafe {
525 let mut i = elems.len();
526 wl_list_for_each_reverse_safe!(foo: *const Foo, list, link, {
527 i -= 1;
528 assert_eq!(foo, elems[i] as *const _);
529 });
530 assert_eq!(i, 0);
531
532 let mut i = elems.len();
533 wl_list_for_each_reverse_safe!(foo: *mut Foo, list, link, {
534 i -= 1;
535 assert_eq!(foo, elems[i] as *mut _);
536 wl_list_remove(&raw mut (*foo).link);
537 });
538 assert_eq!(i, 0);
539 });
540 }
541
542 #[test]
543 fn test_wl_list_for_each_safe() {
544 with_test_list(|list, elems| unsafe {
545 let mut i = 0;
546 wl_list_for_each_safe!(foo: *const Foo, list, link, {
547 assert_eq!(foo, elems[i] as *const _);
548 i += 1;
549 });
550 assert_eq!(i, 3);
551
552 let mut i = 0;
553 wl_list_for_each_safe!(foo: *mut Foo, list, link, {
554 assert_eq!(foo, elems[i] as *mut _);
555 wl_list_remove(&raw mut (*foo).link);
556 i += 1;
557 });
558 assert_eq!(i, 3);
559 });
560 }
561}