Add the derive proc macro
This commit is contained in:
@@ -6,6 +6,10 @@ edition = "2021"
|
||||
description = "SimConnect SDK for Rust"
|
||||
license = "MIT"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
derive = ["simconnect-sdk-derive"]
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.60"
|
||||
|
||||
@@ -13,4 +17,4 @@ bindgen = "0.60"
|
||||
num_enum = "0.5"
|
||||
tracing = "0.1"
|
||||
thiserror = "1.0"
|
||||
simconnect-sdk-derive = { path = "../simconnect-sdk-derive" }
|
||||
simconnect-sdk-derive = { path = "../simconnect-sdk-derive", optional = true }
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/// Airport data.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AirportData {
|
||||
pub icao: String,
|
||||
|
@@ -1,5 +1,8 @@
|
||||
/// Specifies under which conditions the data is to be sent by the server and received by the client.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConditionEnum {
|
||||
pub enum Condition {
|
||||
/// The default, data will be sent strictly according to the defined period.
|
||||
None,
|
||||
/// Data will only be sent to the client when one or more values have changed.
|
||||
Changed,
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/// SimConnect object property data type.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DataType {
|
||||
F64,
|
||||
Float64,
|
||||
Bool,
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
use std::os::raw::c_char;
|
||||
|
||||
/// SimConnect event.
|
||||
/// As defined at <https://www.prepar3d.com/SDKv3/LearningCenter/utilities/variables/event_ids.html>
|
||||
#[derive(Debug, Copy, Clone, num_enum::TryFromPrimitive)]
|
||||
#[repr(u32)]
|
||||
pub enum Event {
|
||||
|
@@ -1,5 +0,0 @@
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum Group {
|
||||
Group0,
|
||||
}
|
@@ -2,14 +2,14 @@ mod airport_data;
|
||||
mod condition;
|
||||
mod data_type;
|
||||
mod event;
|
||||
mod group;
|
||||
mod notification;
|
||||
mod notification_group;
|
||||
mod period;
|
||||
|
||||
pub use airport_data::*;
|
||||
pub use condition::*;
|
||||
pub use data_type::*;
|
||||
pub use event::*;
|
||||
pub use group::*;
|
||||
pub use notification::*;
|
||||
pub use notification_group::*;
|
||||
pub use period::*;
|
||||
|
@@ -1,28 +1,39 @@
|
||||
use crate::{AirportData, Event, SimConnectObjectExt};
|
||||
use crate::{AirportData, Event, SimConnectError, SimConnectObjectExt};
|
||||
|
||||
/// Notification received from SimConnect.
|
||||
pub enum Notification {
|
||||
/// SimConnect open
|
||||
Open,
|
||||
/// SimConnect event
|
||||
Event(Event),
|
||||
/// SimConnect object
|
||||
Data(NotificationData),
|
||||
/// SimConnect airport list
|
||||
AirportList(Vec<AirportData>),
|
||||
/// SimConnect quit
|
||||
Quit,
|
||||
/// SimConnect exception
|
||||
Exception(u32),
|
||||
}
|
||||
|
||||
/// Notification data object.
|
||||
pub struct NotificationData {
|
||||
pub(crate) type_id: String,
|
||||
pub(crate) data_addr: *const u32,
|
||||
}
|
||||
|
||||
impl NotificationData {
|
||||
pub fn try_into<T: SimConnectObjectExt>(&self) -> Option<T> {
|
||||
pub fn try_transmute<T: SimConnectObjectExt>(&self) -> Result<T, SimConnectError> {
|
||||
let type_id: String = std::any::type_name::<T>().into();
|
||||
|
||||
if self.type_id == type_id {
|
||||
let data: &T = unsafe { std::mem::transmute_copy(&self.data_addr) };
|
||||
Some(data.clone())
|
||||
Ok(data.clone())
|
||||
} else {
|
||||
None
|
||||
Err(SimConnectError::ObjectMismatch {
|
||||
actual: self.type_id.clone(),
|
||||
expected: type_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
simconnect-sdk/src/domain/notification_group.rs
Normal file
6
simconnect-sdk/src/domain/notification_group.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
/// SimConnect event notification group.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum NotificationGroup {
|
||||
Group0,
|
||||
}
|
@@ -1,5 +1,16 @@
|
||||
/// Specifies how often the data is to be sent by the server and received by the client.
|
||||
/// 0 - every interval.
|
||||
/// 1 - every other interval.
|
||||
/// 2 - every third interval.
|
||||
/// etc.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PeriodEnum {
|
||||
VisualFrame { interval: u32 },
|
||||
pub enum Period {
|
||||
/// Specifies that the data should be sent once only. Note that this is not an efficient way of receiving data frequently, use one of the other periods if there is a regular frequency to the data request.
|
||||
Once,
|
||||
/// Specifies that the data should be sent every visual (rendered) frame.
|
||||
VisualFrame,
|
||||
/// Specifies that the data should be sent every simulated frame, whether that frame is rendered or not.
|
||||
SimFrame,
|
||||
/// Specifies that the data should be sent once every second.
|
||||
Second,
|
||||
}
|
||||
|
@@ -1,15 +1,24 @@
|
||||
use thiserror::Error;
|
||||
|
||||
/// SimConnect SDK error.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SimConnectError {
|
||||
/// SimConnect error.
|
||||
#[error("SimConnect error: {0}")]
|
||||
SimConnectError(i32),
|
||||
#[error("SimConnect unrecognized: {0}")]
|
||||
/// SimConnect unrecognized error. Occurs when an unimplemented event is received by the SDK.
|
||||
SimConnectUnrecognizedEvent(u32),
|
||||
/// Object already registered with the client instance.
|
||||
#[error("Object `{0}` has already been registered")]
|
||||
ObjectAlreadyRegistered(String),
|
||||
/// Object mismatch.
|
||||
#[error("Tried to convert object of type {actual} to {expected}")]
|
||||
ObjectMismatch { actual: String, expected: String },
|
||||
/// Conversation error.
|
||||
#[error("Conversion error: {0}")]
|
||||
ConversionError(#[from] std::num::TryFromIntError),
|
||||
/// Unexpected error.
|
||||
#[error("Unexpected error: {0}")]
|
||||
UnexpectedError(String),
|
||||
}
|
||||
|
@@ -1,3 +1,8 @@
|
||||
//! # SimConnect SDK
|
||||
//! SimConnect SDK in Rust.
|
||||
//!
|
||||
//! See [examples](https://github.com/mihai-dinculescu/simconnect-sdk/tree/main/examples/src).
|
||||
|
||||
mod bindings;
|
||||
mod domain;
|
||||
mod errors;
|
||||
@@ -13,5 +18,7 @@ pub use errors::SimConnectError;
|
||||
pub use simconnect::SimConnect;
|
||||
pub use simconnect_object_ext::SimConnectObjectExt;
|
||||
|
||||
#[cfg(feature = "simconnect-sdk-derive")]
|
||||
extern crate simconnect_sdk_derive;
|
||||
#[cfg(feature = "simconnect-sdk-derive")]
|
||||
pub use simconnect_sdk_derive::*;
|
||||
|
@@ -2,10 +2,11 @@ use std::ffi::c_void;
|
||||
|
||||
use crate::{
|
||||
as_c_string, bindings, helpers::fixed_c_str_to_string, ok_if_fail, success, AirportData,
|
||||
ConditionEnum, DataType, Event, Group, Notification, NotificationData, PeriodEnum,
|
||||
Condition, DataType, Event, Notification, NotificationData, NotificationGroup, Period,
|
||||
SimConnectError, SimConnectObjectExt,
|
||||
};
|
||||
|
||||
/// SimConnect SDK Client.
|
||||
#[derive(Debug)]
|
||||
pub struct SimConnect {
|
||||
pub handle: std::ptr::NonNull<c_void>,
|
||||
@@ -71,7 +72,7 @@ impl SimConnect {
|
||||
)
|
||||
});
|
||||
|
||||
let group = Group::Group0;
|
||||
let group = NotificationGroup::Group0;
|
||||
|
||||
success!(unsafe {
|
||||
bindings::SimConnect_AddClientEventToNotificationGroup(
|
||||
@@ -98,7 +99,7 @@ impl SimConnect {
|
||||
data_type: DataType,
|
||||
) -> Result<(), SimConnectError> {
|
||||
let c_type = match data_type {
|
||||
DataType::F64 => bindings::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_FLOAT64,
|
||||
DataType::Float64 => bindings::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_FLOAT64,
|
||||
DataType::Bool => bindings::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_INT32,
|
||||
};
|
||||
|
||||
@@ -121,21 +122,22 @@ impl SimConnect {
|
||||
pub fn request_data_on_sim_object(
|
||||
&self,
|
||||
request_id: u32,
|
||||
period: PeriodEnum,
|
||||
condition: ConditionEnum,
|
||||
period: Period,
|
||||
condition: Condition,
|
||||
interval: u32,
|
||||
) -> Result<(), SimConnectError> {
|
||||
unsafe {
|
||||
let (simconnect_period, simconnect_interval) = match period {
|
||||
PeriodEnum::VisualFrame { interval } => (
|
||||
bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_VISUAL_FRAME,
|
||||
interval,
|
||||
),
|
||||
PeriodEnum::Second => (bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_SECOND, 0),
|
||||
let simconnect_period = match period {
|
||||
Period::Once => bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_ONCE,
|
||||
Period::VisualFrame => bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_VISUAL_FRAME,
|
||||
Period::SimFrame => bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_SIM_FRAME,
|
||||
|
||||
Period::Second => bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_SECOND,
|
||||
};
|
||||
|
||||
let simconnect_flags: u32 = match condition {
|
||||
ConditionEnum::None => 0,
|
||||
ConditionEnum::Changed => bindings::SIMCONNECT_DATA_REQUEST_FLAG_CHANGED,
|
||||
Condition::None => 0,
|
||||
Condition::Changed => bindings::SIMCONNECT_DATA_REQUEST_FLAG_CHANGED,
|
||||
};
|
||||
|
||||
success!(bindings::SimConnect_RequestDataOnSimObject(
|
||||
@@ -146,7 +148,7 @@ impl SimConnect {
|
||||
simconnect_period,
|
||||
simconnect_flags,
|
||||
0,
|
||||
simconnect_interval,
|
||||
interval,
|
||||
0,
|
||||
));
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
use crate::{NotificationData, SimConnect, SimConnectError};
|
||||
|
||||
/// Trait to be implemented by objects that can be registered with SimConnect.
|
||||
pub trait SimConnectObjectExt: Clone + for<'a> TryFrom<&'a NotificationData> {
|
||||
fn register(client: &mut SimConnect, id: u32) -> Result<(), SimConnectError>;
|
||||
}
|
||||
|
Reference in New Issue
Block a user