nautilus_model/ffi/identifiers/
instrument_id.rs1use std::{
17 collections::hash_map::DefaultHasher,
18 ffi::c_char,
19 hash::{Hash, Hasher},
20 str::FromStr,
21};
22
23use nautilus_core::ffi::string::{cstr_as_str, str_to_cstr};
24
25use crate::identifiers::{InstrumentId, Symbol, Venue};
26
27#[no_mangle]
28pub extern "C" fn instrument_id_new(symbol: Symbol, venue: Venue) -> InstrumentId {
29 InstrumentId::new(symbol, venue)
30}
31
32#[no_mangle]
38pub unsafe extern "C" fn instrument_id_check_parsing(ptr: *const c_char) -> *const c_char {
39 match InstrumentId::from_str(cstr_as_str(ptr)) {
40 Ok(_) => str_to_cstr(""),
41 Err(e) => str_to_cstr(&e.to_string()),
42 }
43}
44
45#[no_mangle]
51pub unsafe extern "C" fn instrument_id_from_cstr(ptr: *const c_char) -> InstrumentId {
52 InstrumentId::from(cstr_as_str(ptr))
53}
54
55#[no_mangle]
57pub extern "C" fn instrument_id_to_cstr(instrument_id: &InstrumentId) -> *const c_char {
58 str_to_cstr(&instrument_id.to_string())
59}
60
61#[no_mangle]
62pub extern "C" fn instrument_id_hash(instrument_id: &InstrumentId) -> u64 {
63 let mut h = DefaultHasher::new();
64 instrument_id.hash(&mut h);
65 h.finish()
66}
67
68#[no_mangle]
69pub extern "C" fn instrument_id_is_synthetic(instrument_id: &InstrumentId) -> u8 {
70 u8::from(instrument_id.is_synthetic())
71}
72
73#[cfg(test)]
74pub mod stubs {
75 use std::str::FromStr;
76
77 use rstest::fixture;
78
79 use crate::identifiers::{stubs::*, InstrumentId, Symbol, Venue};
80
81 #[fixture]
82 pub fn btc_usdt_perp_binance() -> InstrumentId {
83 InstrumentId::from_str("BTCUSDT-PERP.BINANCE").unwrap()
84 }
85
86 #[fixture]
87 pub fn audusd_sim(symbol_aud_usd: Symbol, venue_sim: Venue) -> InstrumentId {
88 InstrumentId {
89 symbol: symbol_aud_usd,
90 venue: venue_sim,
91 }
92 }
93}
94
95#[cfg(test)]
99mod tests {
100 use std::ffi::CStr;
101
102 use rstest::rstest;
103
104 use super::{InstrumentId, *};
105 use crate::identifiers::{Symbol, Venue};
106
107 #[rstest]
108 fn test_to_cstr() {
109 unsafe {
110 let id = InstrumentId::from("ETH/USDT.BINANCE");
111 let result = instrument_id_to_cstr(&id);
112 assert_eq!(CStr::from_ptr(result).to_str().unwrap(), "ETH/USDT.BINANCE");
113 }
114 }
115
116 #[rstest]
117 fn test_to_cstr_and_back() {
118 unsafe {
119 let id = InstrumentId::from("ETH/USDT.BINANCE");
120 let result = instrument_id_to_cstr(&id);
121 let id2 = instrument_id_from_cstr(result);
122 assert_eq!(id, id2);
123 }
124 }
125
126 #[rstest]
127 fn test_from_symbol_and_back() {
128 unsafe {
129 let id = InstrumentId::new(Symbol::from("ETH/USDT"), Venue::from("BINANCE"));
130 let result = instrument_id_to_cstr(&id);
131 let id2 = instrument_id_from_cstr(result);
132 assert_eq!(id, id2);
133 }
134 }
135}