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