nautilus_common/ffi/
timer.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Posei Systems Pty Ltd. All rights reserved.
3//  https://poseitrader.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::ffi::c_char;
17
18use nautilus_core::{
19    UUID4,
20    ffi::string::{cstr_to_ustr, str_to_cstr},
21};
22
23use crate::timer::{TimeEvent, TimeEventCallback, TimeEventHandlerV2};
24
25#[repr(C)]
26#[derive(Clone, Debug)]
27/// Legacy time event handler for Cython/FFI inter-operatbility
28///
29/// TODO: Remove once Cython is deprecated
30///
31/// `TimeEventHandler` associates a `TimeEvent` with a callback function that is triggered
32/// when the event's timestamp is reached.
33pub struct TimeEventHandler {
34    /// The time event.
35    pub event: TimeEvent,
36    /// The callable raw pointer.
37    pub callback_ptr: *mut c_char,
38}
39
40// Legacy conversion from TimeEventHandlerV2 to pure-C TimeEventHandler
41// Only supports Python callbacks; available when `python` feature is enabled
42#[cfg(feature = "python")]
43impl From<TimeEventHandlerV2> for TimeEventHandler {
44    /// # Panics
45    ///
46    /// Panics if the provided `TimeEventHandlerV2` contains a Rust callback,
47    /// since only Python callbacks are supported by the legacy `TimeEventHandler`.
48    fn from(value: TimeEventHandlerV2) -> Self {
49        Self {
50            event: value.event,
51            callback_ptr: match value.callback {
52                #[cfg(feature = "python")]
53                TimeEventCallback::Python(callback) => callback.as_ptr().cast::<c_char>(),
54                TimeEventCallback::Rust(_) => {
55                    panic!("Legacy time event handler is not supported for Rust callback")
56                }
57            },
58        }
59    }
60}
61
62// Fallback conversion for non-Python callbacks: Rust callbacks only
63#[cfg(not(feature = "python"))]
64impl From<TimeEventHandlerV2> for TimeEventHandler {
65    fn from(value: TimeEventHandlerV2) -> Self {
66        // Only Rust callbacks are supported in non-python builds
67        match value.callback {
68            TimeEventCallback::Rust(_) => TimeEventHandler {
69                event: value.event,
70                callback_ptr: std::ptr::null_mut(),
71            },
72            #[cfg(feature = "python")]
73            TimeEventCallback::Python(_) => {
74                unreachable!("Python callback not supported without python feature")
75            }
76        }
77    }
78}
79
80/// # Safety
81///
82/// Assumes `name_ptr` is borrowed from a valid Python UTF-8 `str`.
83#[unsafe(no_mangle)]
84pub unsafe extern "C" fn time_event_new(
85    name_ptr: *const c_char,
86    event_id: UUID4,
87    ts_event: u64,
88    ts_init: u64,
89) -> TimeEvent {
90    TimeEvent::new(
91        unsafe { cstr_to_ustr(name_ptr) },
92        event_id,
93        ts_event.into(),
94        ts_init.into(),
95    )
96}
97
98/// Returns a [`TimeEvent`] as a C string pointer.
99#[unsafe(no_mangle)]
100pub extern "C" fn time_event_to_cstr(event: &TimeEvent) -> *const c_char {
101    str_to_cstr(&event.to_string())
102}
103
104// This function only exists so that `TimeEventHandler` is included in the definitions
105#[unsafe(no_mangle)]
106pub const extern "C" fn dummy(v: TimeEventHandler) -> TimeEventHandler {
107    v
108}