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