nautilus_plugin/surfaces/book.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2026 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
16//! Boundary-owned handles for order book payloads.
17//!
18//! [`OrderBook`] and [`OrderBookDeltas`] own Rust collection state and
19//! cannot be `#[repr(C)]`, so the host wraps each value in a `#[repr(C)]`
20//! handle that owns the boxed value and passes a borrowed pointer to the
21//! plug-in. The plug-in's thunk dereferences the handle once and hands an
22//! `&OrderBook` or `&OrderBookDeltas` to the trait method. The deltas
23//! handle mirrors the ownership contract that
24//! [`OrderBookDeltas_API`](nautilus_model::data::OrderBookDeltas_API)
25//! uses for the Cython FFI surface.
26
27#![allow(unsafe_code)]
28
29use std::ops::Deref;
30
31use nautilus_model::{data::OrderBookDeltas, orderbook::OrderBook};
32
33/// Boundary-owned wrapper that lets [`OrderBook`] cross the cdylib FFI
34/// boundary by reference.
35///
36/// The host constructs an instance from a cloned book, hands a
37/// `*const OrderBookHandle` to the plug-in for the duration of the
38/// callback, and drops the handle when the call returns. The plug-in
39/// only borrows the handle and never owns it.
40#[repr(C)]
41#[derive(Debug, Clone)]
42pub struct OrderBookHandle(Box<OrderBook>);
43
44impl OrderBookHandle {
45 /// Wraps `book` in a boundary-owned handle.
46 #[must_use]
47 pub fn new(book: OrderBook) -> Self {
48 Self(Box::new(book))
49 }
50
51 /// Returns a reference to the wrapped book.
52 #[must_use]
53 pub fn book(&self) -> &OrderBook {
54 &self.0
55 }
56
57 /// Consumes the wrapper and returns the inner book.
58 #[must_use]
59 pub fn into_inner(self) -> OrderBook {
60 *self.0
61 }
62}
63
64impl Deref for OrderBookHandle {
65 type Target = OrderBook;
66
67 fn deref(&self) -> &Self::Target {
68 &self.0
69 }
70}
71
72/// Boundary-owned wrapper that lets [`OrderBookDeltas`] cross the cdylib
73/// FFI boundary by reference.
74///
75/// The host constructs an instance, hands a
76/// `*const OrderBookDeltasHandle` to the plug-in for the duration of the
77/// callback, and drops the handle when the call returns. The plug-in
78/// only borrows the handle and never owns it.
79#[repr(C)]
80#[derive(Debug, Clone)]
81pub struct OrderBookDeltasHandle(Box<OrderBookDeltas>);
82
83impl OrderBookDeltasHandle {
84 /// Wraps `deltas` in a boundary-owned handle.
85 #[must_use]
86 pub fn new(deltas: OrderBookDeltas) -> Self {
87 Self(Box::new(deltas))
88 }
89
90 /// Returns a reference to the wrapped deltas.
91 #[must_use]
92 pub fn deltas(&self) -> &OrderBookDeltas {
93 &self.0
94 }
95
96 /// Consumes the wrapper and returns the inner deltas.
97 #[must_use]
98 pub fn into_inner(self) -> OrderBookDeltas {
99 *self.0
100 }
101}
102
103impl Deref for OrderBookDeltasHandle {
104 type Target = OrderBookDeltas;
105
106 fn deref(&self) -> &Self::Target {
107 &self.0
108 }
109}