nautilus_model/ffi/
enums.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.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, str::FromStr};
17
18use nautilus_core::ffi::string::{cstr_as_str, str_to_cstr};
19
20use crate::enums::{
21    AccountType, AggregationSource, AggressorSide, AssetClass, BarAggregation, BookAction,
22    BookType, ContingencyType, CurrencyType, InstrumentClass, InstrumentCloseType, LiquiditySide,
23    MarketStatus, MarketStatusAction, OmsType, OptionKind, OrderSide, OrderStatus, OrderType,
24    PositionSide, PriceType, RecordFlag, TimeInForce, TradingState, TrailingOffsetType,
25    TriggerType,
26};
27
28#[unsafe(no_mangle)]
29pub extern "C" fn account_type_to_cstr(value: AccountType) -> *const c_char {
30    str_to_cstr(value.as_ref())
31}
32
33/// Returns an enum from a Python string.
34///
35/// # Safety
36///
37/// Assumes `ptr` is a valid C string pointer.
38///
39/// # Panics
40///
41/// Panics if the C string does not correspond to a valid `AccountType` variant.
42#[unsafe(no_mangle)]
43pub unsafe extern "C" fn account_type_from_cstr(ptr: *const c_char) -> AccountType {
44    let value = unsafe { cstr_as_str(ptr) };
45    AccountType::from_str(value)
46        .unwrap_or_else(|_| panic!("invalid `AccountType` enum string value, was '{value}'"))
47}
48
49#[unsafe(no_mangle)]
50pub extern "C" fn aggregation_source_to_cstr(value: AggregationSource) -> *const c_char {
51    str_to_cstr(value.as_ref())
52}
53
54/// Returns an enum from a Python string.
55///
56/// # Safety
57///
58/// Assumes `ptr` is a valid C string pointer.
59///
60/// # Panics
61///
62/// Panics if the C string does not correspond to a valid `AggressorSide` variant.
63#[unsafe(no_mangle)]
64pub unsafe extern "C" fn aggregation_source_from_cstr(ptr: *const c_char) -> AggregationSource {
65    let value = unsafe { cstr_as_str(ptr) };
66    AggregationSource::from_str(value)
67        .unwrap_or_else(|_| panic!("invalid `AggregationSource` enum string value, was '{value}'"))
68}
69
70#[unsafe(no_mangle)]
71pub extern "C" fn aggressor_side_to_cstr(value: AggressorSide) -> *const c_char {
72    str_to_cstr(value.as_ref())
73}
74
75/// Returns an enum from a Python string.
76///
77/// # Safety
78///
79/// Assumes `ptr` is a valid C string pointer.
80///
81/// # Panics
82///
83/// Panics if the C string does not correspond to a valid `AggregationSource` variant.
84#[unsafe(no_mangle)]
85pub unsafe extern "C" fn aggressor_side_from_cstr(ptr: *const c_char) -> AggressorSide {
86    let value = unsafe { cstr_as_str(ptr) };
87    AggressorSide::from_str(value)
88        .unwrap_or_else(|_| panic!("invalid `AggressorSide` enum string value, was '{value}'"))
89}
90
91#[unsafe(no_mangle)]
92pub extern "C" fn asset_class_to_cstr(value: AssetClass) -> *const c_char {
93    str_to_cstr(value.as_ref())
94}
95
96/// Returns an enum from a Python string.
97///
98/// # Safety
99///
100/// Assumes `ptr` is a valid C string pointer.
101///
102/// # Panics
103///
104/// Panics if the C string does not correspond to a valid `AssetClass` variant.
105#[unsafe(no_mangle)]
106pub unsafe extern "C" fn asset_class_from_cstr(ptr: *const c_char) -> AssetClass {
107    let value = unsafe { cstr_as_str(ptr) };
108    AssetClass::from_str(value)
109        .unwrap_or_else(|_| panic!("invalid `AssetClass` enum string value, was '{value}'"))
110}
111
112#[unsafe(no_mangle)]
113pub extern "C" fn instrument_class_to_cstr(value: InstrumentClass) -> *const c_char {
114    str_to_cstr(value.as_ref())
115}
116
117/// Returns an enum from a Python string.
118///
119/// # Safety
120///
121/// Assumes `ptr` is a valid C string pointer.
122///
123/// # Panics
124///
125/// Panics if the C string does not correspond to a valid `InstrumentClass` variant.
126#[unsafe(no_mangle)]
127pub unsafe extern "C" fn instrument_class_from_cstr(ptr: *const c_char) -> InstrumentClass {
128    let value = unsafe { cstr_as_str(ptr) };
129    InstrumentClass::from_str(value)
130        .unwrap_or_else(|_| panic!("invalid `InstrumentClass` enum string value, was '{value}'"))
131}
132
133#[unsafe(no_mangle)]
134pub extern "C" fn bar_aggregation_to_cstr(value: BarAggregation) -> *const c_char {
135    str_to_cstr(value.as_ref())
136}
137
138/// Returns an enum from a Python string.
139///
140/// # Safety
141///
142/// Assumes `ptr` is a valid C string pointer.
143///
144/// # Panics
145///
146/// Panics if the C string does not correspond to a valid `BarAggregation` variant.
147#[unsafe(no_mangle)]
148pub unsafe extern "C" fn bar_aggregation_from_cstr(ptr: *const c_char) -> BarAggregation {
149    let value = unsafe { cstr_as_str(ptr) };
150    BarAggregation::from_str(value)
151        .unwrap_or_else(|_| panic!("invalid `BarAggregation` enum string value, was '{value}'"))
152}
153
154#[unsafe(no_mangle)]
155pub extern "C" fn book_action_to_cstr(value: BookAction) -> *const c_char {
156    str_to_cstr(value.as_ref())
157}
158
159/// Returns an enum from a Python string.
160///
161/// # Safety
162///
163/// Assumes `ptr` is a valid C string pointer.
164///
165/// # Panics
166///
167/// Panics if the C string does not correspond to a valid `BookAction` variant.
168#[unsafe(no_mangle)]
169pub unsafe extern "C" fn book_action_from_cstr(ptr: *const c_char) -> BookAction {
170    let value = unsafe { cstr_as_str(ptr) };
171    BookAction::from_str(value)
172        .unwrap_or_else(|_| panic!("invalid `BookAction` enum string value, was '{value}'"))
173}
174
175#[unsafe(no_mangle)]
176pub extern "C" fn book_type_to_cstr(value: BookType) -> *const c_char {
177    str_to_cstr(value.as_ref())
178}
179
180/// Returns an enum from a Python string.
181///
182/// # Safety
183///
184/// Assumes `ptr` is a valid C string pointer.
185///
186/// # Panics
187///
188/// Panics if the C string does not correspond to a valid `BookType` variant.
189#[unsafe(no_mangle)]
190pub unsafe extern "C" fn book_type_from_cstr(ptr: *const c_char) -> BookType {
191    let value = unsafe { cstr_as_str(ptr) };
192    BookType::from_str(value)
193        .unwrap_or_else(|_| panic!("invalid `BookType` enum string value, was '{value}'"))
194}
195
196#[unsafe(no_mangle)]
197pub extern "C" fn contingency_type_to_cstr(value: ContingencyType) -> *const c_char {
198    str_to_cstr(value.as_ref())
199}
200
201/// Returns an enum from a Python string.
202///
203/// # Safety
204///
205/// Assumes `ptr` is a valid C string pointer.
206///
207/// # Panics
208///
209/// Panics if the C string does not correspond to a valid `ContingencyType` variant.
210#[unsafe(no_mangle)]
211pub unsafe extern "C" fn contingency_type_from_cstr(ptr: *const c_char) -> ContingencyType {
212    let value = unsafe { cstr_as_str(ptr) };
213    ContingencyType::from_str(value)
214        .unwrap_or_else(|_| panic!("invalid `ContingencyType` enum string value, was '{value}'"))
215}
216
217#[unsafe(no_mangle)]
218pub extern "C" fn currency_type_to_cstr(value: CurrencyType) -> *const c_char {
219    str_to_cstr(value.as_ref())
220}
221
222/// Returns an enum from a Python string.
223///
224/// # Safety
225///
226/// Assumes `ptr` is a valid C string pointer.
227///
228/// # Panics
229///
230/// Panics if the C string does not correspond to a valid `CurrencyType` variant.
231#[unsafe(no_mangle)]
232pub unsafe extern "C" fn currency_type_from_cstr(ptr: *const c_char) -> CurrencyType {
233    let value = unsafe { cstr_as_str(ptr) };
234    CurrencyType::from_str(value)
235        .unwrap_or_else(|_| panic!("invalid `CurrencyType` enum string value, was '{value}'"))
236}
237
238/// Returns an enum from a Python string.
239///
240/// # Safety
241///
242/// Assumes `ptr` is a valid C string pointer.
243///
244/// # Panics
245///
246/// Panics if the C string does not correspond to a valid `InstrumentCloseType` variant.
247#[unsafe(no_mangle)]
248pub unsafe extern "C" fn instrument_close_type_from_cstr(
249    ptr: *const c_char,
250) -> InstrumentCloseType {
251    let value = unsafe { cstr_as_str(ptr) };
252    InstrumentCloseType::from_str(value).unwrap_or_else(|_| {
253        panic!("invalid `InstrumentCloseType` enum string value, was '{value}'")
254    })
255}
256
257#[unsafe(no_mangle)]
258pub extern "C" fn instrument_close_type_to_cstr(value: InstrumentCloseType) -> *const c_char {
259    str_to_cstr(value.as_ref())
260}
261
262#[unsafe(no_mangle)]
263pub extern "C" fn liquidity_side_to_cstr(value: LiquiditySide) -> *const c_char {
264    str_to_cstr(value.as_ref())
265}
266
267/// Returns an enum from a Python string.
268///
269/// # Safety
270///
271/// Assumes `ptr` is a valid C string pointer.
272///
273/// # Panics
274///
275/// Panics if the C string does not correspond to a valid `LiquiditySide` variant.
276#[unsafe(no_mangle)]
277pub unsafe extern "C" fn liquidity_side_from_cstr(ptr: *const c_char) -> LiquiditySide {
278    let value = unsafe { cstr_as_str(ptr) };
279    LiquiditySide::from_str(value)
280        .unwrap_or_else(|_| panic!("invalid `LiquiditySide` enum string value, was '{value}'"))
281}
282
283#[unsafe(no_mangle)]
284pub extern "C" fn market_status_to_cstr(value: MarketStatus) -> *const c_char {
285    str_to_cstr(value.as_ref())
286}
287
288/// Returns an enum from a Python string.
289///
290/// # Safety
291///
292/// Assumes `ptr` is a valid C string pointer.
293///
294/// # Panics
295///
296/// Panics if the C string does not correspond to a valid `MarketStatus` variant.
297#[unsafe(no_mangle)]
298pub unsafe extern "C" fn market_status_from_cstr(ptr: *const c_char) -> MarketStatus {
299    let value = unsafe { cstr_as_str(ptr) };
300    MarketStatus::from_str(value)
301        .unwrap_or_else(|_| panic!("invalid `MarketStatus` enum string value, was '{value}'"))
302}
303
304#[unsafe(no_mangle)]
305pub extern "C" fn market_status_action_to_cstr(value: MarketStatusAction) -> *const c_char {
306    str_to_cstr(value.as_ref())
307}
308
309/// Returns an enum from a Python string.
310///
311/// # Safety
312///
313/// Assumes `ptr` is a valid C string pointer.
314///
315/// # Panics
316///
317/// Panics if the C string does not correspond to a valid `MarketStatusAction` variant.
318#[unsafe(no_mangle)]
319pub unsafe extern "C" fn market_status_action_from_cstr(ptr: *const c_char) -> MarketStatusAction {
320    let value = unsafe { cstr_as_str(ptr) };
321    MarketStatusAction::from_str(value)
322        .unwrap_or_else(|_| panic!("invalid `MarketStatusAction` enum string value, was '{value}'"))
323}
324
325#[unsafe(no_mangle)]
326pub extern "C" fn oms_type_to_cstr(value: OmsType) -> *const c_char {
327    str_to_cstr(value.as_ref())
328}
329
330/// Returns an enum from a Python string.
331///
332/// # Safety
333///
334/// Assumes `ptr` is a valid C string pointer.
335///
336/// # Panics
337///
338/// Panics if the C string does not correspond to a valid `OmsType` variant.
339#[unsafe(no_mangle)]
340pub unsafe extern "C" fn oms_type_from_cstr(ptr: *const c_char) -> OmsType {
341    let value = unsafe { cstr_as_str(ptr) };
342    OmsType::from_str(value)
343        .unwrap_or_else(|_| panic!("invalid `OmsType` enum string value, was '{value}'"))
344}
345
346#[unsafe(no_mangle)]
347pub extern "C" fn option_kind_to_cstr(value: OptionKind) -> *const c_char {
348    str_to_cstr(value.as_ref())
349}
350
351/// Returns an enum from a Python string.
352///
353/// # Safety
354///
355/// Assumes `ptr` is a valid C string pointer.
356///
357/// # Panics
358///
359/// Panics if the C string does not correspond to a valid `OptionKind` variant.
360#[unsafe(no_mangle)]
361pub unsafe extern "C" fn option_kind_from_cstr(ptr: *const c_char) -> OptionKind {
362    let value = unsafe { cstr_as_str(ptr) };
363    OptionKind::from_str(value)
364        .unwrap_or_else(|_| panic!("invalid `OptionKind` enum string value, was '{value}'"))
365}
366
367#[unsafe(no_mangle)]
368pub extern "C" fn order_side_to_cstr(value: OrderSide) -> *const c_char {
369    str_to_cstr(value.as_ref())
370}
371
372/// Returns an enum from a Python string.
373///
374/// # Safety
375///
376/// Assumes `ptr` is a valid C string pointer.
377///
378/// # Panics
379///
380/// Panics if the C string does not correspond to a valid `OrderSide` variant.
381#[unsafe(no_mangle)]
382pub unsafe extern "C" fn order_side_from_cstr(ptr: *const c_char) -> OrderSide {
383    let value = unsafe { cstr_as_str(ptr) };
384    OrderSide::from_str(value)
385        .unwrap_or_else(|_| panic!("invalid `OrderSide` enum string value, was '{value}'"))
386}
387
388#[unsafe(no_mangle)]
389pub extern "C" fn order_status_to_cstr(value: OrderStatus) -> *const c_char {
390    str_to_cstr(value.as_ref())
391}
392
393/// Returns an enum from a Python string.
394///
395/// # Safety
396///
397/// Assumes `ptr` is a valid C string pointer.
398///
399/// # Panics
400///
401/// Panics if the C string does not correspond to a valid `OrderStatus` variant.
402#[unsafe(no_mangle)]
403pub unsafe extern "C" fn order_status_from_cstr(ptr: *const c_char) -> OrderStatus {
404    let value = unsafe { cstr_as_str(ptr) };
405    OrderStatus::from_str(value)
406        .unwrap_or_else(|_| panic!("invalid `OrderStatus` enum string value, was '{value}'"))
407}
408
409#[unsafe(no_mangle)]
410pub extern "C" fn order_type_to_cstr(value: OrderType) -> *const c_char {
411    str_to_cstr(value.as_ref())
412}
413
414/// Returns an enum from a Python string.
415///
416/// # Safety
417///
418/// Assumes `ptr` is a valid C string pointer.
419///
420/// # Panics
421///
422/// Panics if the C string does not correspond to a valid `OrderType` variant.
423#[unsafe(no_mangle)]
424pub unsafe extern "C" fn order_type_from_cstr(ptr: *const c_char) -> OrderType {
425    let value = unsafe { cstr_as_str(ptr) };
426    OrderType::from_str(value)
427        .unwrap_or_else(|_| panic!("invalid `OrderType` enum string value, was '{value}'"))
428}
429
430#[unsafe(no_mangle)]
431pub extern "C" fn position_side_to_cstr(value: PositionSide) -> *const c_char {
432    str_to_cstr(value.as_ref())
433}
434
435/// Returns an enum from a Python string.
436///
437/// # Safety
438///
439/// Assumes `ptr` is a valid C string pointer.
440///
441/// # Panics
442///
443/// Panics if the C string does not correspond to a valid `PositionSide` variant.
444#[unsafe(no_mangle)]
445pub unsafe extern "C" fn position_side_from_cstr(ptr: *const c_char) -> PositionSide {
446    let value = unsafe { cstr_as_str(ptr) };
447    PositionSide::from_str(value)
448        .unwrap_or_else(|_| panic!("invalid `PositionSide` enum string value, was '{value}'"))
449}
450
451#[unsafe(no_mangle)]
452pub extern "C" fn price_type_to_cstr(value: PriceType) -> *const c_char {
453    str_to_cstr(value.as_ref())
454}
455
456/// Returns an enum from a Python string.
457///
458/// # Safety
459///
460/// Assumes `ptr` is a valid C string pointer.
461///
462/// # Panics
463///
464/// Panics if the C string does not correspond to a valid `PriceType` variant.
465#[unsafe(no_mangle)]
466pub unsafe extern "C" fn price_type_from_cstr(ptr: *const c_char) -> PriceType {
467    let value = unsafe { cstr_as_str(ptr) };
468    PriceType::from_str(value)
469        .unwrap_or_else(|_| panic!("invalid `PriceType` enum string value, was '{value}'"))
470}
471
472#[unsafe(no_mangle)]
473pub extern "C" fn record_flag_to_cstr(value: RecordFlag) -> *const c_char {
474    str_to_cstr(value.as_ref())
475}
476
477/// Returns an enum from a Python string.
478///
479/// # Safety
480///
481/// Assumes `ptr` is a valid C string pointer.
482///
483/// # Panics
484///
485/// Panics if the C string does not correspond to a valid `RecordFlag` variant.
486#[unsafe(no_mangle)]
487pub unsafe extern "C" fn record_flag_from_cstr(ptr: *const c_char) -> RecordFlag {
488    let value = unsafe { cstr_as_str(ptr) };
489    RecordFlag::from_str(value)
490        .unwrap_or_else(|_| panic!("invalid `RecordFlag` enum string value, was '{value}'"))
491}
492
493#[unsafe(no_mangle)]
494pub extern "C" fn time_in_force_to_cstr(value: TimeInForce) -> *const c_char {
495    str_to_cstr(value.as_ref())
496}
497
498/// Returns an enum from a Python string.
499///
500/// # Safety
501///
502/// Assumes `ptr` is a valid C string pointer.
503///
504/// # Panics
505///
506/// Panics if the C string does not correspond to a valid `TimeInForce` variant.
507#[unsafe(no_mangle)]
508pub unsafe extern "C" fn time_in_force_from_cstr(ptr: *const c_char) -> TimeInForce {
509    let value = unsafe { cstr_as_str(ptr) };
510    TimeInForce::from_str(value)
511        .unwrap_or_else(|_| panic!("invalid `TimeInForce` enum string value, was '{value}'"))
512}
513
514#[unsafe(no_mangle)]
515pub extern "C" fn trading_state_to_cstr(value: TradingState) -> *const c_char {
516    str_to_cstr(value.as_ref())
517}
518
519/// Returns an enum from a Python string.
520///
521/// # Safety
522///
523/// Assumes `ptr` is a valid C string pointer.
524///
525/// # Panics
526///
527/// Panics if the C string does not correspond to a valid `TradingState` variant.
528#[unsafe(no_mangle)]
529pub unsafe extern "C" fn trading_state_from_cstr(ptr: *const c_char) -> TradingState {
530    let value = unsafe { cstr_as_str(ptr) };
531    TradingState::from_str(value)
532        .unwrap_or_else(|_| panic!("invalid `TradingState` enum string value, was '{value}'"))
533}
534
535#[unsafe(no_mangle)]
536pub extern "C" fn trailing_offset_type_to_cstr(value: TrailingOffsetType) -> *const c_char {
537    str_to_cstr(value.as_ref())
538}
539
540/// Returns an enum from a Python string.
541///
542/// # Safety
543///
544/// Assumes `ptr` is a valid C string pointer.
545///
546/// # Panics
547///
548/// Panics if the C string does not correspond to a valid `TrailingOffsetType` variant.
549#[unsafe(no_mangle)]
550pub unsafe extern "C" fn trailing_offset_type_from_cstr(ptr: *const c_char) -> TrailingOffsetType {
551    let value = unsafe { cstr_as_str(ptr) };
552    TrailingOffsetType::from_str(value)
553        .unwrap_or_else(|_| panic!("invalid `TrailingOffsetType` enum string value, was '{value}'"))
554}
555
556#[unsafe(no_mangle)]
557pub extern "C" fn trigger_type_to_cstr(value: TriggerType) -> *const c_char {
558    str_to_cstr(value.as_ref())
559}
560
561/// Returns an enum from a Python string.
562///
563/// # Safety
564///
565/// Assumes `ptr` is a valid C string pointer.
566///
567/// # Panics
568///
569/// Panics if the C string does not correspond to a valid `TriggerType` variant.
570#[unsafe(no_mangle)]
571pub unsafe extern "C" fn trigger_type_from_cstr(ptr: *const c_char) -> TriggerType {
572    let value = unsafe { cstr_as_str(ptr) };
573    TriggerType::from_str(value)
574        .unwrap_or_else(|_| panic!("invalid `TriggerType` enum string value, was '{value}'"))
575}
576
577#[cfg(test)]
578mod tests {
579    use rstest::rstest;
580
581    use super::*;
582
583    #[rstest]
584    fn test_name() {
585        assert_eq!(OrderSide::NoOrderSide.name(), "NO_ORDER_SIDE");
586        assert_eq!(OrderSide::Buy.name(), "BUY");
587        assert_eq!(OrderSide::Sell.name(), "SELL");
588    }
589
590    #[rstest]
591    fn test_value() {
592        assert_eq!(OrderSide::NoOrderSide.value(), 0);
593        assert_eq!(OrderSide::Buy.value(), 1);
594        assert_eq!(OrderSide::Sell.value(), 2);
595    }
596}