1use std::{
17 ffi::c_char,
18 ops::{Deref, DerefMut},
19};
20
21use nautilus_core::{
22 UnixNanos,
23 correctness::FAILED,
24 ffi::{
25 cvec::CVec,
26 parsing::u8_as_bool,
27 string::{cstr_as_str, str_to_cstr},
28 },
29};
30#[cfg(feature = "python")]
31use pyo3::{ffi, prelude::*};
32
33use super::timer::TimeEventHandler;
34use crate::{
35 clock::{Clock, LiveClock, TestClock},
36 timer::{TimeEvent, TimeEventCallback},
37};
38
39#[repr(C)]
48#[allow(non_camel_case_types)]
49#[derive(Debug)]
50pub struct TestClock_API(Box<TestClock>);
51
52impl Deref for TestClock_API {
53 type Target = TestClock;
54
55 fn deref(&self) -> &Self::Target {
56 &self.0
57 }
58}
59
60impl DerefMut for TestClock_API {
61 fn deref_mut(&mut self) -> &mut Self::Target {
62 &mut self.0
63 }
64}
65
66#[unsafe(no_mangle)]
67pub extern "C" fn test_clock_new() -> TestClock_API {
68 TestClock_API(Box::default())
69}
70
71#[unsafe(no_mangle)]
72pub extern "C" fn test_clock_drop(clock: TestClock_API) {
73 drop(clock); }
75
76#[cfg(feature = "python")]
86#[unsafe(no_mangle)]
87pub unsafe extern "C" fn test_clock_register_default_handler(
88 clock: &mut TestClock_API,
89 callback_ptr: *mut ffi::PyObject,
90) {
91 assert!(!callback_ptr.is_null());
92 assert!(unsafe { ffi::Py_None() } != callback_ptr);
93
94 let callback = Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
95 let callback = TimeEventCallback::from(callback);
96
97 clock.register_default_handler(callback);
98}
99
100#[unsafe(no_mangle)]
101pub extern "C" fn test_clock_set_time(clock: &TestClock_API, to_time_ns: u64) {
102 clock.set_time(to_time_ns.into());
103}
104
105#[unsafe(no_mangle)]
106pub extern "C" fn test_clock_timestamp(clock: &TestClock_API) -> f64 {
107 clock.get_time()
108}
109
110#[unsafe(no_mangle)]
111pub extern "C" fn test_clock_timestamp_ms(clock: &TestClock_API) -> u64 {
112 clock.get_time_ms()
113}
114
115#[unsafe(no_mangle)]
116pub extern "C" fn test_clock_timestamp_us(clock: &TestClock_API) -> u64 {
117 clock.get_time_us()
118}
119
120#[unsafe(no_mangle)]
121pub extern "C" fn test_clock_timestamp_ns(clock: &TestClock_API) -> u64 {
122 clock.get_time_ns().as_u64()
123}
124
125#[unsafe(no_mangle)]
126pub extern "C" fn test_clock_timer_names(clock: &TestClock_API) -> *const c_char {
127 str_to_cstr(&clock.timer_names().join("<,>"))
130}
131
132#[unsafe(no_mangle)]
133pub extern "C" fn test_clock_timer_count(clock: &mut TestClock_API) -> usize {
134 clock.timer_count()
135}
136
137#[cfg(feature = "python")]
147#[unsafe(no_mangle)]
148pub unsafe extern "C" fn test_clock_set_time_alert(
149 clock: &mut TestClock_API,
150 name_ptr: *const c_char,
151 alert_time_ns: UnixNanos,
152 callback_ptr: *mut ffi::PyObject,
153 allow_past: u8,
154) {
155 assert!(!callback_ptr.is_null());
156
157 let name = unsafe { cstr_as_str(name_ptr) };
158 let callback = if callback_ptr == unsafe { ffi::Py_None() } {
159 None
160 } else {
161 let callback =
162 Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
163 Some(TimeEventCallback::from(callback))
164 };
165
166 clock
167 .set_time_alert_ns(name, alert_time_ns, callback, Some(allow_past != 0))
168 .expect(FAILED);
169}
170
171#[cfg(feature = "python")]
181#[unsafe(no_mangle)]
182pub unsafe extern "C" fn test_clock_set_timer(
183 clock: &mut TestClock_API,
184 name_ptr: *const c_char,
185 interval_ns: u64,
186 start_time_ns: UnixNanos,
187 stop_time_ns: UnixNanos,
188 callback_ptr: *mut ffi::PyObject,
189 allow_past: u8,
190) {
191 assert!(!callback_ptr.is_null());
192
193 let name = unsafe { cstr_as_str(name_ptr) };
194 let stop_time_ns = match stop_time_ns.into() {
195 0 => None,
196 _ => Some(stop_time_ns),
197 };
198 let callback = if callback_ptr == unsafe { ffi::Py_None() } {
199 None
200 } else {
201 let callback =
202 Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
203 Some(TimeEventCallback::from(callback))
204 };
205
206 clock
207 .set_timer_ns(
208 name,
209 interval_ns,
210 start_time_ns,
211 stop_time_ns,
212 callback,
213 Some(allow_past != 0),
214 )
215 .expect(FAILED);
216}
217
218#[unsafe(no_mangle)]
222pub unsafe extern "C" fn test_clock_advance_time(
223 clock: &mut TestClock_API,
224 to_time_ns: u64,
225 set_time: u8,
226) -> CVec {
227 let events: Vec<TimeEvent> = clock.advance_time(to_time_ns.into(), u8_as_bool(set_time));
228 let t: Vec<TimeEventHandler> = clock
229 .match_handlers(events)
230 .into_iter()
231 .map(Into::into)
232 .collect();
233 t.into()
234}
235
236#[allow(clippy::drop_non_drop)]
239#[unsafe(no_mangle)]
240pub extern "C" fn vec_time_event_handlers_drop(v: CVec) {
241 let CVec { ptr, len, cap } = v;
242 let data: Vec<TimeEventHandler> =
243 unsafe { Vec::from_raw_parts(ptr.cast::<TimeEventHandler>(), len, cap) };
244 drop(data); }
246
247#[unsafe(no_mangle)]
251pub unsafe extern "C" fn test_clock_next_time(
252 clock: &mut TestClock_API,
253 name_ptr: *const c_char,
254) -> UnixNanos {
255 let name = unsafe { cstr_as_str(name_ptr) };
256 clock.next_time_ns(name).unwrap_or_default()
257}
258
259#[unsafe(no_mangle)]
263pub unsafe extern "C" fn test_clock_cancel_timer(
264 clock: &mut TestClock_API,
265 name_ptr: *const c_char,
266) {
267 let name = unsafe { cstr_as_str(name_ptr) };
268 clock.cancel_timer(name);
269}
270
271#[unsafe(no_mangle)]
272pub extern "C" fn test_clock_cancel_timers(clock: &mut TestClock_API) {
273 clock.cancel_timers();
274}
275
276#[repr(C)]
286#[allow(non_camel_case_types)]
287#[derive(Debug)]
288pub struct LiveClock_API(Box<LiveClock>);
289
290impl Deref for LiveClock_API {
291 type Target = LiveClock;
292
293 fn deref(&self) -> &Self::Target {
294 &self.0
295 }
296}
297
298impl DerefMut for LiveClock_API {
299 fn deref_mut(&mut self) -> &mut Self::Target {
300 &mut self.0
301 }
302}
303
304#[unsafe(no_mangle)]
305pub extern "C" fn live_clock_new() -> LiveClock_API {
306 LiveClock_API(Box::default())
307}
308
309#[unsafe(no_mangle)]
310pub extern "C" fn live_clock_drop(clock: LiveClock_API) {
311 drop(clock); }
313
314#[cfg(feature = "python")]
322#[unsafe(no_mangle)]
323pub unsafe extern "C" fn live_clock_register_default_handler(
324 clock: &mut LiveClock_API,
325 callback_ptr: *mut ffi::PyObject,
326) {
327 assert!(!callback_ptr.is_null());
328 assert!(unsafe { ffi::Py_None() } != callback_ptr);
329
330 let callback = Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
331 let callback = TimeEventCallback::from(callback);
332
333 clock.register_default_handler(callback);
334}
335
336#[unsafe(no_mangle)]
337pub extern "C" fn live_clock_timestamp(clock: &mut LiveClock_API) -> f64 {
338 clock.get_time()
339}
340
341#[unsafe(no_mangle)]
342pub extern "C" fn live_clock_timestamp_ms(clock: &mut LiveClock_API) -> u64 {
343 clock.get_time_ms()
344}
345
346#[unsafe(no_mangle)]
347pub extern "C" fn live_clock_timestamp_us(clock: &mut LiveClock_API) -> u64 {
348 clock.get_time_us()
349}
350
351#[unsafe(no_mangle)]
352pub extern "C" fn live_clock_timestamp_ns(clock: &mut LiveClock_API) -> u64 {
353 clock.get_time_ns().as_u64()
354}
355
356#[unsafe(no_mangle)]
357pub extern "C" fn live_clock_timer_names(clock: &LiveClock_API) -> *const c_char {
358 str_to_cstr(&clock.timer_names().join("<,>"))
361}
362
363#[unsafe(no_mangle)]
364pub extern "C" fn live_clock_timer_count(clock: &mut LiveClock_API) -> usize {
365 clock.timer_count()
366}
367
368#[cfg(feature = "python")]
380#[unsafe(no_mangle)]
381pub unsafe extern "C" fn live_clock_set_time_alert(
382 clock: &mut LiveClock_API,
383 name_ptr: *const c_char,
384 alert_time_ns: UnixNanos,
385 callback_ptr: *mut ffi::PyObject,
386 allow_past: u8,
387) {
388 assert!(!callback_ptr.is_null());
389
390 let name = unsafe { cstr_as_str(name_ptr) };
391 let callback = if callback_ptr == unsafe { ffi::Py_None() } {
392 None
393 } else {
394 let callback =
395 Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
396 Some(TimeEventCallback::from(callback))
397 };
398
399 clock
400 .set_time_alert_ns(name, alert_time_ns, callback, Some(allow_past != 0))
401 .expect(FAILED);
402}
403
404#[cfg(feature = "python")]
416#[unsafe(no_mangle)]
417pub unsafe extern "C" fn live_clock_set_timer(
418 clock: &mut LiveClock_API,
419 name_ptr: *const c_char,
420 interval_ns: u64,
421 start_time_ns: UnixNanos,
422 stop_time_ns: UnixNanos,
423 callback_ptr: *mut ffi::PyObject,
424 allow_past: u8,
425) {
426 assert!(!callback_ptr.is_null());
427
428 let name = unsafe { cstr_as_str(name_ptr) };
429 let stop_time_ns = match stop_time_ns.into() {
430 0 => None,
431 _ => Some(stop_time_ns),
432 };
433
434 let callback = if callback_ptr == unsafe { ffi::Py_None() } {
435 None
436 } else {
437 let callback =
438 Python::with_gil(|py| unsafe { PyObject::from_borrowed_ptr(py, callback_ptr) });
439 Some(TimeEventCallback::from(callback))
440 };
441
442 clock
443 .set_timer_ns(
444 name,
445 interval_ns,
446 start_time_ns,
447 stop_time_ns,
448 callback,
449 Some(allow_past != 0),
450 )
451 .expect(FAILED);
452}
453
454#[unsafe(no_mangle)]
458pub unsafe extern "C" fn live_clock_next_time(
459 clock: &mut LiveClock_API,
460 name_ptr: *const c_char,
461) -> UnixNanos {
462 let name = unsafe { cstr_as_str(name_ptr) };
463 clock.next_time_ns(name).unwrap_or_default()
464}
465
466#[unsafe(no_mangle)]
470pub unsafe extern "C" fn live_clock_cancel_timer(
471 clock: &mut LiveClock_API,
472 name_ptr: *const c_char,
473) {
474 let name = unsafe { cstr_as_str(name_ptr) };
475 clock.cancel_timer(name);
476}
477
478#[unsafe(no_mangle)]
479pub extern "C" fn live_clock_cancel_timers(clock: &mut LiveClock_API) {
480 clock.cancel_timers();
481}