perspective_server/
ffi.rs1#[repr(C, packed)]
14pub struct CppResponse {
15 data_ptr: usize,
16 length: u32,
17 client_id: u32,
18}
19
20#[repr(C, packed)]
21pub struct CppResponseBatch {
22 length: u32,
23 entries_ptr: usize,
24}
25
26unsafe extern "C" {
27 fn psp_alloc(size: usize) -> *mut u8;
28 fn psp_free(ptr: *const u8);
29 fn psp_new_server(realtime_mode: bool) -> *const u8;
30 fn psp_new_session(server: *const u8) -> u32;
31 fn psp_delete_server(server: *const u8);
32 fn psp_handle_request(
33 server: *const u8,
34 client_id: u32,
35 buffer_ptr: *const u8,
36 buffer_len: usize,
37 ) -> ResponseBatch;
38 fn psp_poll(server: *const u8) -> ResponseBatch;
39 fn psp_close_session(server: *const u8, client_id: u32);
40 fn psp_num_cpus() -> i32;
41 fn psp_set_num_cpus(num_cpus: i32);
42}
43
44pub fn num_cpus() -> i32 {
45 unsafe { psp_num_cpus() }
46}
47
48pub fn set_num_cpus(num_cpus: i32) {
49 unsafe { psp_set_num_cpus(num_cpus) }
50}
51
52pub struct Response(*const CppResponse);
53
54impl Response {
55 pub fn msg(&self) -> &[u8] {
56 let resp = unsafe { &*self.0 };
57 let data_ptr = resp.data_ptr as *const u8;
58 let len = resp.length as usize;
59 unsafe { std::slice::from_raw_parts(data_ptr, len) }
60 }
61
62 pub fn client_id(&self) -> u32 {
63 let resp = unsafe { &*self.0 };
64 resp.client_id
65 }
66}
67
68impl Drop for Response {
69 fn drop(&mut self) {
70 unsafe {
71 let resp = &*self.0;
72 psp_free(resp.data_ptr as *const u8);
73 }
74 }
75}
76
77#[repr(transparent)]
78pub struct ResponseBatch(*const CppResponseBatch);
79
80impl ResponseBatch {
81 pub fn size(&self) -> usize {
82 let batch = unsafe { &*self.0 };
83 batch.length as usize
84 }
85
86 pub fn iter_responses(&self) -> impl Iterator<Item = Response> + Send + Sync {
87 let batch = unsafe { &*self.0 };
88 let num_responses = batch.length;
89 (0..num_responses).map(move |idx| {
90 let entries_ptr = batch.entries_ptr as *const CppResponse;
91 Response(unsafe { entries_ptr.offset(idx as isize) })
92 })
93 }
94}
95
96impl Drop for ResponseBatch {
97 fn drop(&mut self) {
98 unsafe {
99 let batch = &*self.0;
100 psp_free(batch.entries_ptr as *const u8);
101 psp_free(self.0 as *const u8)
102 }
103 }
104}
105
106pub struct Request(*const u8, usize);
107
108impl From<&[u8]> for Request {
109 fn from(value: &[u8]) -> Self {
110 let len = value.len();
111 let ptr = unsafe { psp_alloc(len) };
112 unsafe { std::ptr::copy(std::ptr::addr_of!(value[0]), ptr, len) };
113 Request(ptr, len)
114 }
115}
116
117impl Drop for Request {
118 fn drop(&mut self) {
119 unsafe {
120 psp_free(self.0);
121 };
122 }
123}
124
125pub struct Server(*const u8);
126
127impl Server {
128 pub fn new(realtime_mode: bool) -> Self {
129 Server(unsafe { psp_new_server(realtime_mode) })
130 }
131
132 pub fn new_session(&self) -> u32 {
133 unsafe { psp_new_session(self.0) }
134 }
135
136 pub fn handle_request(&self, client_id: u32, request: &Request) -> ResponseBatch {
137 unsafe { psp_handle_request(self.0, client_id, request.0, request.1) }
138 }
139
140 pub fn poll(&self) -> ResponseBatch {
141 unsafe { psp_poll(self.0) }
142 }
143
144 pub fn close_session(&self, session_id: u32) {
145 unsafe { psp_close_session(self.0, session_id) }
146 }
147}
148
149impl Drop for Server {
150 fn drop(&mut self) {
151 unsafe { psp_delete_server(self.0) }
152 }
153}
154
155unsafe impl Send for Server {}
156unsafe impl Sync for Server {}
157
158unsafe impl Send for Request {}
159unsafe impl Sync for Request {}
160
161unsafe impl Send for ResponseBatch {}
162unsafe impl Sync for ResponseBatch {}
163
164unsafe impl Send for Response {}
165unsafe impl Sync for Response {}