openrr_plugin/
proxy.rs

1//! This module defines FFI-safe equivalents of the various types and traits
2//! used in arci and openrr-plugin. The types defined by this module will never
3//! appear in the public API, and the conversion is done internally.
4
5#![allow(clippy::let_unit_value)] // this lint is triggered for code generated by #[sabi_trait]
6#![allow(clippy::unnecessary_cast)] // this lint is triggered for code generated by #[sabi_trait]
7
8#[rustfmt::skip]
9#[path = "gen/proxy.rs"]
10mod impls;
11
12use std::{sync::Arc, time::SystemTime};
13
14use abi_stable::{
15    declare_root_module_statics,
16    library::RootModule,
17    package_version_strings,
18    prefix_type::PrefixTypeTrait,
19    rtry, sabi_trait,
20    sabi_types::VersionStrings,
21    std_types::{RBoxError, RDuration, ROk, ROption, RString, RVec},
22    StableAbi,
23};
24use anyhow::format_err;
25use arci::nalgebra;
26use async_ffi::{FfiFuture, FutureExt as _};
27
28pub(crate) use self::impls::*;
29use crate::PluginProxy;
30
31type RResult<T, E = RError> = abi_stable::std_types::RResult<T, E>;
32
33// =============================================================================
34// std::time::SystemTime
35
36/// FFI-safe equivalent of [`std::time::SystemTime`].
37///
38/// `SystemTime` does not implement `StableAbi`, so convert it to duration since unix epoch,
39/// and recover it on conversion to `SystemTime`.
40/// This is inspired by the way `serde` implements `Serialize`/`Deserialize` on `SystemTime`.
41///
42/// Refs:
43/// - <https://github.com/serde-rs/serde/blob/v1.0.126/serde/src/ser/impls.rs#L610-L625>
44/// - <https://github.com/serde-rs/serde/blob/v1.0.126/serde/src/de/impls.rs#L1993-L2138>
45#[repr(C)]
46#[derive(StableAbi)]
47pub(crate) struct RSystemTime {
48    duration_since_epoch: RDuration,
49}
50
51impl TryFrom<SystemTime> for RSystemTime {
52    type Error = RError;
53
54    fn try_from(val: SystemTime) -> Result<Self, Self::Error> {
55        let duration_since_epoch = val
56            .duration_since(SystemTime::UNIX_EPOCH)
57            .map_err(|_| format_err!("SystemTime must be later than UNIX_EPOCH"))?;
58        Ok(Self {
59            duration_since_epoch: duration_since_epoch.into(),
60        })
61    }
62}
63
64impl TryFrom<RSystemTime> for SystemTime {
65    type Error = RError;
66
67    fn try_from(val: RSystemTime) -> Result<Self, Self::Error> {
68        let duration_since_epoch = val.duration_since_epoch.into();
69        SystemTime::UNIX_EPOCH
70            .checked_add(duration_since_epoch)
71            .ok_or_else(|| format_err!("overflow deserializing SystemTime").into())
72    }
73}
74
75// =============================================================================
76// nalgebra::Isometry2<f64>
77
78/// FFI-safe equivalent of [`nalgebra::Isometry2<f64>`](nalgebra::Isometry2).
79#[repr(C)]
80#[derive(StableAbi)]
81pub(crate) struct RIsometry2F64 {
82    rotation: RUnitComplexF64,
83    translation: RTranslation2F64,
84}
85
86impl From<nalgebra::Isometry2<f64>> for RIsometry2F64 {
87    fn from(val: nalgebra::Isometry2<f64>) -> Self {
88        Self {
89            rotation: val.rotation.into(),
90            translation: val.translation.into(),
91        }
92    }
93}
94
95impl From<RIsometry2F64> for nalgebra::Isometry2<f64> {
96    fn from(val: RIsometry2F64) -> Self {
97        Self::from_parts(val.translation.into(), val.rotation.into())
98    }
99}
100
101/// FFI-safe equivalent of [`nalgebra::UnitComplex<f64>`](nalgebra::UnitComplex).
102#[repr(C)]
103#[derive(StableAbi)]
104struct RUnitComplexF64 {
105    re: f64,
106    im: f64,
107}
108
109impl From<nalgebra::UnitComplex<f64>> for RUnitComplexF64 {
110    fn from(val: nalgebra::UnitComplex<f64>) -> Self {
111        let val = val.into_inner();
112        Self {
113            re: val.re,
114            im: val.im,
115        }
116    }
117}
118
119impl From<RUnitComplexF64> for nalgebra::UnitComplex<f64> {
120    fn from(val: RUnitComplexF64) -> Self {
121        Self::from_complex(nalgebra::Complex {
122            re: val.re,
123            im: val.im,
124        })
125    }
126}
127
128/// FFI-safe equivalent of [`nalgebra::Translation2<f64>`](nalgebra::Translation2).
129#[repr(C)]
130#[derive(StableAbi)]
131struct RTranslation2F64 {
132    x: f64,
133    y: f64,
134}
135
136impl From<nalgebra::Translation2<f64>> for RTranslation2F64 {
137    fn from(val: nalgebra::Translation2<f64>) -> Self {
138        Self {
139            x: val.vector.x,
140            y: val.vector.y,
141        }
142    }
143}
144
145impl From<RTranslation2F64> for nalgebra::Translation2<f64> {
146    fn from(val: RTranslation2F64) -> Self {
147        Self::new(val.x, val.y)
148    }
149}
150
151// =============================================================================
152// nalgebra::Isometry3<f64>
153
154/// FFI-safe equivalent of [`nalgebra::Isometry3<f64>`](nalgebra::Isometry3).
155#[repr(C)]
156#[derive(StableAbi)]
157pub(crate) struct RIsometry3F64 {
158    rotation: RUnitQuaternionF64,
159    translation: RTranslation3F64,
160}
161
162impl From<nalgebra::Isometry3<f64>> for RIsometry3F64 {
163    fn from(val: nalgebra::Isometry3<f64>) -> Self {
164        Self {
165            rotation: val.rotation.into(),
166            translation: val.translation.into(),
167        }
168    }
169}
170
171impl From<RIsometry3F64> for nalgebra::Isometry3<f64> {
172    fn from(val: RIsometry3F64) -> Self {
173        Self::from_parts(val.translation.into(), val.rotation.into())
174    }
175}
176
177/// FFI-safe equivalent of [`nalgebra::UnitQuaternion<f64>`](nalgebra::UnitQuaternion).
178#[repr(C)]
179#[derive(StableAbi)]
180struct RUnitQuaternionF64 {
181    x: f64,
182    y: f64,
183    z: f64,
184    w: f64,
185}
186
187impl From<nalgebra::UnitQuaternion<f64>> for RUnitQuaternionF64 {
188    fn from(val: nalgebra::UnitQuaternion<f64>) -> Self {
189        let val = val.into_inner();
190        Self {
191            x: val.coords.x,
192            y: val.coords.y,
193            z: val.coords.z,
194            w: val.coords.w,
195        }
196    }
197}
198
199impl From<RUnitQuaternionF64> for nalgebra::UnitQuaternion<f64> {
200    fn from(val: RUnitQuaternionF64) -> Self {
201        Self::from_quaternion(nalgebra::Quaternion::new(val.w, val.x, val.y, val.z))
202    }
203}
204
205/// FFI-safe equivalent of [`nalgebra::Translation3<f64>`](nalgebra::Translation3).
206#[repr(C)]
207#[derive(StableAbi)]
208struct RTranslation3F64 {
209    x: f64,
210    y: f64,
211    z: f64,
212}
213
214impl From<nalgebra::Translation3<f64>> for RTranslation3F64 {
215    fn from(val: nalgebra::Translation3<f64>) -> Self {
216        Self {
217            x: val.vector.x,
218            y: val.vector.y,
219            z: val.vector.z,
220        }
221    }
222}
223
224impl From<RTranslation3F64> for nalgebra::Translation3<f64> {
225    fn from(val: RTranslation3F64) -> Self {
226        Self::new(val.x, val.y, val.z)
227    }
228}
229
230// =============================================================================
231// arci::Error
232
233/// FFI-safe equivalent of [`arci::Error`].
234#[repr(C)]
235#[derive(StableAbi)]
236pub(crate) struct RError {
237    repr: RBoxError,
238}
239
240impl From<arci::Error> for RError {
241    fn from(e: arci::Error) -> Self {
242        Self {
243            // TODO: propagate error kind.
244            repr: RBoxError::from_box(e.into()),
245        }
246    }
247}
248
249impl From<anyhow::Error> for RError {
250    fn from(e: anyhow::Error) -> Self {
251        Self {
252            // TODO: propagate error kind.
253            repr: RBoxError::from_box(e.into()),
254        }
255    }
256}
257
258impl From<RError> for arci::Error {
259    fn from(e: RError) -> Self {
260        // TODO: propagate error kind.
261        Self::Other(format_err!("{}", e.repr))
262    }
263}
264
265// =============================================================================
266// arci::WaitFuture
267
268#[repr(C)]
269#[derive(StableAbi)]
270#[must_use]
271pub(crate) struct RWaitFuture(FfiFuture<RResult<()>>);
272
273impl From<arci::WaitFuture> for RWaitFuture {
274    #[allow(clippy::unit_arg)] // false positive that triggered for external macro
275    fn from(wait: arci::WaitFuture) -> Self {
276        Self(async move { ROk(rtry!(wait.await)) }.into_ffi())
277    }
278}
279
280impl From<RWaitFuture> for arci::WaitFuture {
281    fn from(wait: RWaitFuture) -> Self {
282        arci::WaitFuture::new(async move { Ok(wait.0.await.into_result()?) })
283    }
284}
285
286// =============================================================================
287// PluginMod
288
289// Not public API.
290#[doc(hidden)]
291#[allow(missing_debug_implementations)]
292#[repr(C)]
293#[derive(StableAbi)]
294#[sabi(kind(Prefix))]
295#[sabi(missing_field(panic))]
296pub struct PluginMod {
297    #[sabi(last_prefix_field)]
298    pub(crate) plugin_constructor: extern "C" fn() -> PluginProxy,
299}
300
301impl RootModule for PluginMod_Ref {
302    const BASE_NAME: &'static str = "plugin";
303    const NAME: &'static str = "plugin";
304    const VERSION_STRINGS: VersionStrings = package_version_strings!();
305
306    declare_root_module_statics!(PluginMod_Ref);
307}
308
309impl PluginMod_Ref {
310    #[doc(hidden)]
311    pub fn new(plugin_constructor: extern "C" fn() -> PluginProxy) -> Self {
312        PluginMod { plugin_constructor }.leak_into_prefix()
313    }
314}