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