nautilus_model/ffi/data/
bar.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::{
17    collections::hash_map::DefaultHasher,
18    ffi::c_char,
19    hash::{Hash, Hasher},
20    str::FromStr,
21};
22
23use nautilus_core::{
24    UnixNanos,
25    ffi::string::{cstr_as_str, str_to_cstr},
26};
27
28use crate::{
29    data::bar::{Bar, BarSpecification, BarType},
30    enums::{AggregationSource, BarAggregation, PriceType},
31    identifiers::InstrumentId,
32    types::{Price, Quantity},
33};
34
35#[unsafe(no_mangle)]
36pub extern "C" fn bar_specification_new(
37    step: usize,
38    aggregation: u8,
39    price_type: u8,
40) -> BarSpecification {
41    let aggregation =
42        BarAggregation::from_repr(aggregation as usize).expect("Error converting enum");
43    let price_type = PriceType::from_repr(price_type as usize).expect("Error converting enum");
44    BarSpecification::new(step, aggregation, price_type)
45}
46
47/// Returns a [`BarSpecification`] as a C string pointer.
48#[unsafe(no_mangle)]
49pub extern "C" fn bar_specification_to_cstr(bar_spec: &BarSpecification) -> *const c_char {
50    str_to_cstr(&bar_spec.to_string())
51}
52
53#[unsafe(no_mangle)]
54pub extern "C" fn bar_specification_hash(bar_spec: &BarSpecification) -> u64 {
55    let mut h = DefaultHasher::new();
56    bar_spec.hash(&mut h);
57    h.finish()
58}
59
60#[unsafe(no_mangle)]
61pub extern "C" fn bar_specification_eq(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
62    u8::from(lhs == rhs)
63}
64
65#[unsafe(no_mangle)]
66pub extern "C" fn bar_specification_lt(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
67    u8::from(lhs < rhs)
68}
69
70#[unsafe(no_mangle)]
71pub extern "C" fn bar_specification_le(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
72    u8::from(lhs <= rhs)
73}
74
75#[unsafe(no_mangle)]
76pub extern "C" fn bar_specification_gt(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
77    u8::from(lhs > rhs)
78}
79
80#[unsafe(no_mangle)]
81pub extern "C" fn bar_specification_ge(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
82    u8::from(lhs >= rhs)
83}
84
85#[unsafe(no_mangle)]
86pub extern "C" fn bar_type_new(
87    instrument_id: InstrumentId,
88    spec: BarSpecification,
89    aggregation_source: u8,
90) -> BarType {
91    let aggregation_source =
92        AggregationSource::from_repr(aggregation_source as usize).expect("Error converting enum");
93
94    BarType::Standard {
95        instrument_id,
96        spec,
97        aggregation_source,
98    }
99}
100
101#[unsafe(no_mangle)]
102pub extern "C" fn bar_type_new_composite(
103    instrument_id: InstrumentId,
104    spec: BarSpecification,
105    aggregation_source: AggregationSource,
106
107    composite_step: usize,
108    composite_aggregation: BarAggregation,
109    composite_aggregation_source: AggregationSource,
110) -> BarType {
111    BarType::new_composite(
112        instrument_id,
113        spec,
114        aggregation_source,
115        composite_step,
116        composite_aggregation,
117        composite_aggregation_source,
118    )
119}
120
121#[unsafe(no_mangle)]
122pub extern "C" fn bar_type_is_standard(bar_type: &BarType) -> u8 {
123    bar_type.is_standard() as u8
124}
125
126#[unsafe(no_mangle)]
127pub extern "C" fn bar_type_is_composite(bar_type: &BarType) -> u8 {
128    bar_type.is_composite() as u8
129}
130
131#[unsafe(no_mangle)]
132pub extern "C" fn bar_type_standard(bar_type: &BarType) -> BarType {
133    bar_type.standard()
134}
135
136#[unsafe(no_mangle)]
137pub extern "C" fn bar_type_composite(bar_type: &BarType) -> BarType {
138    bar_type.composite()
139}
140
141#[unsafe(no_mangle)]
142pub extern "C" fn bar_type_instrument_id(bar_type: &BarType) -> InstrumentId {
143    bar_type.instrument_id()
144}
145
146#[unsafe(no_mangle)]
147pub extern "C" fn bar_type_spec(bar_type: &BarType) -> BarSpecification {
148    bar_type.spec()
149}
150
151#[unsafe(no_mangle)]
152pub extern "C" fn bar_type_aggregation_source(bar_type: &BarType) -> AggregationSource {
153    bar_type.aggregation_source()
154}
155
156/// Returns any [`BarType`] parsing error from the provided C string pointer.
157///
158/// # Safety
159///
160/// - Assumes `ptr` is a valid C string pointer.
161#[unsafe(no_mangle)]
162pub unsafe extern "C" fn bar_type_check_parsing(ptr: *const c_char) -> *const c_char {
163    let value = unsafe { cstr_as_str(ptr) };
164    match BarType::from_str(value) {
165        Ok(_) => str_to_cstr(""),
166        Err(e) => str_to_cstr(&e.to_string()),
167    }
168}
169
170/// Returns a [`BarType`] from a C string pointer.
171///
172/// # Safety
173///
174/// - Assumes `ptr` is a valid C string pointer.
175#[unsafe(no_mangle)]
176pub unsafe extern "C" fn bar_type_from_cstr(ptr: *const c_char) -> BarType {
177    let value = unsafe { cstr_as_str(ptr) };
178    BarType::from(value)
179}
180
181#[unsafe(no_mangle)]
182pub extern "C" fn bar_type_eq(lhs: &BarType, rhs: &BarType) -> u8 {
183    u8::from(lhs == rhs)
184}
185
186#[unsafe(no_mangle)]
187pub extern "C" fn bar_type_lt(lhs: &BarType, rhs: &BarType) -> u8 {
188    u8::from(lhs < rhs)
189}
190
191#[unsafe(no_mangle)]
192pub extern "C" fn bar_type_le(lhs: &BarType, rhs: &BarType) -> u8 {
193    u8::from(lhs <= rhs)
194}
195
196#[unsafe(no_mangle)]
197pub extern "C" fn bar_type_gt(lhs: &BarType, rhs: &BarType) -> u8 {
198    u8::from(lhs > rhs)
199}
200
201#[unsafe(no_mangle)]
202pub extern "C" fn bar_type_ge(lhs: &BarType, rhs: &BarType) -> u8 {
203    u8::from(lhs >= rhs)
204}
205
206#[unsafe(no_mangle)]
207pub extern "C" fn bar_type_hash(bar_type: &BarType) -> u64 {
208    let mut h = DefaultHasher::new();
209    bar_type.hash(&mut h);
210    h.finish()
211}
212
213/// Returns a [`BarType`] as a C string pointer.
214#[unsafe(no_mangle)]
215pub extern "C" fn bar_type_to_cstr(bar_type: &BarType) -> *const c_char {
216    str_to_cstr(&bar_type.to_string())
217}
218
219#[unsafe(no_mangle)]
220#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
221pub extern "C" fn bar_new(
222    bar_type: BarType,
223    open: Price,
224    high: Price,
225    low: Price,
226    close: Price,
227    volume: Quantity,
228    ts_event: UnixNanos,
229    ts_init: UnixNanos,
230) -> Bar {
231    Bar {
232        bar_type,
233        open,
234        high,
235        low,
236        close,
237        volume,
238        ts_event,
239        ts_init,
240    }
241}
242
243#[unsafe(no_mangle)]
244pub extern "C" fn bar_eq(lhs: &Bar, rhs: &Bar) -> u8 {
245    u8::from(lhs == rhs)
246}
247
248#[unsafe(no_mangle)]
249pub extern "C" fn bar_hash(bar: &Bar) -> u64 {
250    let mut h = DefaultHasher::new();
251    bar.hash(&mut h);
252    h.finish()
253}
254
255/// Returns a [`Bar`] as a C string.
256#[unsafe(no_mangle)]
257pub extern "C" fn bar_to_cstr(bar: &Bar) -> *const c_char {
258    str_to_cstr(&bar.to_string())
259}