qwac_sys/
lib.rs

1use std::{
2    future::Future,
3    ops::{Deref, DerefMut},
4    pin::Pin,
5    ptr::null_mut,
6    sync::{
7        atomic::{AtomicBool, Ordering},
8        Arc,
9    },
10    task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
11};
12
13pub mod audio;
14pub mod core;
15pub mod data;
16pub mod graphics;
17pub mod input;
18
19#[derive(Debug)]
20struct Promise {
21    index: i32,
22    resolved: AtomicBool,
23}
24
25impl From<i32> for Promise {
26    fn from(index: i32) -> Self {
27        Self {
28            index,
29            resolved: AtomicBool::new(false),
30        }
31    }
32}
33
34impl Promise {
35    /// Resolve the promise only if it's not resolved already.
36    fn resolve(&self) {
37        if !self.resolved.swap(true, Ordering::Relaxed) {
38            unsafe {
39                crate::core::resolve_promise(self.index);
40            }
41        }
42    }
43}
44
45mod vtable {
46    use crate::Promise;
47    use std::mem::ManuallyDrop;
48    use std::sync::Arc;
49    use std::task::RawWaker;
50
51    pub unsafe fn clone(data: *const ()) -> RawWaker {
52        Arc::increment_strong_count(data as *const Promise);
53        RawWaker::new(data, &crate::V_TABLE)
54    }
55    pub unsafe fn wake(data: *const ()) {
56        let data = Arc::from_raw(data as *const Promise);
57        data.resolve();
58    }
59    pub unsafe fn wake_by_ref(data: *const ()) {
60        let data = ManuallyDrop::new(Arc::from_raw(data as *const Promise));
61        data.resolve();
62    }
63    pub unsafe fn drop(data: *const ()) {
64        std::mem::drop(Arc::from_raw(data as *const Promise));
65    }
66}
67
68const V_TABLE: RawWakerVTable = RawWakerVTable::new(
69    vtable::clone,
70    vtable::wake,
71    vtable::wake_by_ref,
72    vtable::drop,
73);
74
75/// A buffer type, allowing abstracting away the internal implementation without breaking API.
76#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
77#[repr(transparent)]
78pub struct Buffer(Box<[u8]>);
79
80impl Buffer {
81    fn new(size: usize) -> Self {
82        let mut vec = Vec::new();
83        vec.reserve_exact(size);
84        vec.resize(size, 0);
85        Self(vec.into_boxed_slice())
86    }
87}
88
89impl Deref for Buffer {
90    type Target = [u8];
91
92    fn deref(&self) -> &Self::Target {
93        &self.0
94    }
95}
96
97impl DerefMut for Buffer {
98    fn deref_mut(&mut self) -> &mut Self::Target {
99        &mut self.0
100    }
101}
102
103impl From<Buffer> for Box<[u8]> {
104    fn from(value: Buffer) -> Self {
105        value.0
106    }
107}
108impl From<Buffer> for Vec<u8> {
109    fn from(value: Buffer) -> Self {
110        value.0.into_vec()
111    }
112}
113
114#[no_mangle]
115pub extern "C" fn qwac_buffer_create(size: i32) -> *mut Buffer {
116    let buffer = Buffer::new(size.try_into().expect("Out of range"));
117    Box::into_raw(Box::new(buffer))
118}
119
120#[no_mangle]
121pub extern "C" fn qwac_buffer_pointer(buffer: *mut Buffer) -> *mut u8 {
122    let buffer = unsafe { &mut *buffer };
123    buffer.as_mut_ptr()
124}
125
126#[no_mangle]
127pub extern "C" fn qwac_poll(
128    raw_future: *mut Pin<Box<dyn Future<Output = ()>>>,
129    promise: i32,
130) -> *mut Pin<Box<dyn Future<Output = ()>>> {
131    let future = unsafe { &mut *raw_future }.as_mut();
132    let data: Arc<Promise> = Arc::new(promise.into());
133    let data = Arc::into_raw(data) as *const ();
134    let raw_waker = RawWaker::new(data, &V_TABLE);
135    let waker = unsafe { Waker::from_raw(raw_waker) };
136    let mut context = Context::from_waker(&waker);
137    match future.poll(&mut context) {
138        Poll::Ready(()) => {
139            // Finishing a future drops it as well.
140            unsafe {
141                drop(Box::from_raw(raw_future));
142            }
143            null_mut()
144        }
145        Poll::Pending => raw_future,
146    }
147}