nautilus_plugin/surfaces/option_chain.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 handle for [`OptionChainSlice`].
17//!
18//! [`OptionChainSlice`] owns `BTreeMap<Price, OptionStrikeData>` call and
19//! put maps and cannot be `#[repr(C)]`, so the host wraps it in a
20//! `#[repr(C)]` handle that owns the boxed value and passes a borrowed
21//! pointer to the plug-in. The plug-in's thunk dereferences the handle
22//! once and hands an `&OptionChainSlice` to the trait method. Mirrors
23//! the ownership contract that
24//! [`OrderBookDeltasHandle`](crate::surfaces::book::OrderBookDeltasHandle)
25//! uses for [`OrderBookDeltas`](nautilus_model::data::OrderBookDeltas).
26
27#![allow(unsafe_code)]
28
29use std::ops::Deref;
30
31use nautilus_model::data::OptionChainSlice;
32
33/// Boundary-owned wrapper that lets [`OptionChainSlice`] cross the
34/// cdylib FFI boundary by reference.
35///
36/// The host constructs an instance, hands a
37/// `*const OptionChainSliceHandle` to the plug-in for the duration of
38/// the callback, and drops the handle when the call returns. The
39/// plug-in only borrows the handle and never owns it.
40#[repr(C)]
41#[derive(Debug, Clone)]
42pub struct OptionChainSliceHandle(Box<OptionChainSlice>);
43
44impl OptionChainSliceHandle {
45 /// Wraps `slice` in a boundary-owned handle.
46 #[must_use]
47 pub fn new(slice: OptionChainSlice) -> Self {
48 Self(Box::new(slice))
49 }
50
51 /// Returns a reference to the wrapped option chain slice.
52 #[must_use]
53 pub fn chain(&self) -> &OptionChainSlice {
54 &self.0
55 }
56
57 /// Consumes the wrapper and returns the inner option chain slice.
58 #[must_use]
59 pub fn into_inner(self) -> OptionChainSlice {
60 *self.0
61 }
62}
63
64impl Deref for OptionChainSliceHandle {
65 type Target = OptionChainSlice;
66
67 fn deref(&self) -> &Self::Target {
68 &self.0
69 }
70}