#![doc = include_str!("../README.md")]
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
#![allow(clippy::derive_partial_eq_without_eq)]
#![allow(repr_transparent_external_private_fields)]
mod proxy;
#[rustfmt::skip]
#[path = "gen/api.rs"]
mod api;
use std::{fmt, path::Path, sync::Arc, time::Duration};
use abi_stable::{erased_types::TD_Opaque, library::lib_header_from_path, StableAbi};
use arci::{async_trait, WaitFuture};
pub use crate::api::*;
#[doc(hidden)]
pub use crate::proxy::PluginMod_Ref;
use crate::proxy::{GamepadTraitObject, JointTrajectoryClientTraitObject};
#[macro_export]
macro_rules! export_plugin {
($plugin_constructor:expr $(,)?) => {
#[allow(clippy::drop_non_drop)] #[::abi_stable::export_root_module]
pub fn instantiate_root_module() -> $crate::PluginMod_Ref {
$crate::PluginMod_Ref::new(plugin_constructor)
}
#[allow(clippy::drop_non_drop)] #[::abi_stable::sabi_extern_fn]
pub fn plugin_constructor() -> $crate::PluginProxy {
$crate::PluginProxy::new($plugin_constructor)
}
};
}
impl PluginProxy {
pub fn from_path(path: impl AsRef<Path>) -> Result<Self, arci::Error> {
let path = path.as_ref();
let header = lib_header_from_path(path).map_err(anyhow::Error::from)?;
let root_module = header
.init_root_module::<PluginMod_Ref>()
.map_err(anyhow::Error::from)?;
let plugin_constructor = root_module.plugin_constructor();
let plugin = plugin_constructor();
Ok(plugin)
}
}
impl fmt::Debug for PluginProxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PluginProxy").finish()
}
}
#[repr(C)]
#[derive(StableAbi)]
pub struct JointTrajectoryClientProxy(JointTrajectoryClientTraitObject);
impl JointTrajectoryClientProxy {
pub fn new<T>(client: T) -> Self
where
T: arci::JointTrajectoryClient + 'static,
{
Self(JointTrajectoryClientTraitObject::from_value(
client, TD_Opaque,
))
}
}
impl arci::JointTrajectoryClient for JointTrajectoryClientProxy {
fn joint_names(&self) -> Vec<String> {
self.0.joint_names().into_iter().map(|s| s.into()).collect()
}
fn current_joint_positions(&self) -> Result<Vec<f64>, arci::Error> {
Ok(self
.0
.current_joint_positions()
.into_result()?
.into_iter()
.map(f64::from)
.collect())
}
fn send_joint_positions(
&self,
positions: Vec<f64>,
duration: Duration,
) -> Result<WaitFuture, arci::Error> {
Ok(self
.0
.send_joint_positions(
positions.into_iter().map(Into::into).collect(),
duration.into(),
)
.into_result()?
.into())
}
fn send_joint_trajectory(
&self,
trajectory: Vec<arci::TrajectoryPoint>,
) -> Result<WaitFuture, arci::Error> {
Ok(self
.0
.send_joint_trajectory(trajectory.into_iter().map(Into::into).collect())
.into_result()?
.into())
}
}
impl fmt::Debug for JointTrajectoryClientProxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("JointTrajectoryClientProxy").finish()
}
}
#[repr(C)]
#[derive(StableAbi)]
pub struct GamepadProxy(GamepadTraitObject);
impl GamepadProxy {
pub fn new<T>(gamepad: T) -> Self
where
T: arci::Gamepad + 'static,
{
Self(GamepadTraitObject::from_value(Arc::new(gamepad), TD_Opaque))
}
}
#[async_trait]
impl arci::Gamepad for GamepadProxy {
async fn next_event(&self) -> arci::gamepad::GamepadEvent {
let this = Self(self.0.clone());
tokio::task::spawn_blocking(move || this.0.next_event().into())
.await
.unwrap_or(arci::gamepad::GamepadEvent::Unknown)
}
fn stop(&self) {
self.0.stop();
}
}
impl fmt::Debug for GamepadProxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GamepadProxy").finish()
}
}