labview_interop/types/mod.rs
1//! The types module provides some of the common structures
2//! and functions for handling types from LabVIEW.
3
4pub mod array;
5mod boolean;
6#[cfg(target_pointer_width = "64")]
7mod lv_errors;
8mod lv_status;
9pub mod string;
10pub mod timestamp;
11
12use std::ffi::c_void;
13
14use crate::memory::UHandle;
15
16//surface some of the common types.
17#[cfg(feature = "link")]
18pub use array::LVArrayOwned;
19pub use array::{LVArray, LVArrayHandle};
20pub use boolean::LVBool;
21#[cfg(target_pointer_width = "64")]
22pub use lv_errors::{ErrorClusterPtr, ToLvError};
23pub use lv_status::LVStatusCode;
24pub use string::LStrHandle;
25#[cfg(feature = "link")]
26pub use string::LStrOwned;
27pub use timestamp::LVTime;
28
29/// Wrap a struct declaration to have the packing attributes
30/// set for exchanging the data with the LabVIEW cluster type.
31///
32/// # 64 Bit
33///
34/// For 64 bit this is just the standard C packing and is fully
35/// functional as a Rust struct.
36///
37/// # 32 Bit
38///
39/// On 32 bit this uses a packed representation.
40///
41/// Because Rust references must be aligned this means you cannot get
42/// a reference to an individual item and instead must use
43/// [std::ptr::read_unaligned] or [std::ptr::write_unaligned] after getting
44/// the address with [std::ptr::addr_of]. The 32 bit access example below shows this.
45///
46/// # Basic Example
47/// ```
48/// use labview_interop::labview_layout;
49///
50/// labview_layout!(
51/// pub struct TestStruct {
52/// one: u8,
53/// two: u16,
54/// three: u32,
55/// }
56/// );
57///
58/// ```
59///
60/// # 32 Bit Reference Access
61/// ```
62/// use labview_interop::labview_layout;
63/// use std::ptr::{addr_of, read_unaligned};
64///
65/// labview_layout!(
66/// pub struct TestStruct {
67/// one: u8,
68/// two: u16,
69/// three: u32,
70/// }
71/// );
72///
73/// let value = TestStruct {
74/// one: 1,
75/// two: 2,
76/// three: 3
77/// };
78///
79/// // Not allowed on 32 bit.
80/// //let three_ref = &value.three;
81/// unsafe {
82/// let three_ptr: *const u32 = addr_of!(value.three);
83/// let three: u32 = read_unaligned(three_ptr);
84/// }
85///
86/// ```
87#[macro_export]
88macro_rules! labview_layout {
89 ($struct:item) => {
90 #[repr(C)]
91 #[cfg_attr(target_pointer_width = "32", repr(packed))]
92 $struct
93 };
94}
95
96/// Represents a LabVIEW Variant. The internal structure is undefined
97/// by NI and therefore unavailable.
98///
99/// This is available as a placeholder in clusters etc.
100#[repr(transparent)]
101pub struct LVVariant<'variant>(UHandle<'variant, c_void>);
102
103labview_layout!(
104 /// Represents the LabVIEW waveform type where:
105 ///
106 /// * t0: The start time of the data.
107 /// * dt: The time delte between samples.
108 /// * data: A 1d array of type T
109 ///
110 /// ## Padding
111 ///
112 /// The padding scheme here is wierd and unexpected and has been reverse engineered
113 /// based on real calls. No idea why the padding exists whether it is documented anywhere.
114 pub struct Waveform<'waveform, T> {
115 /// The timestamp for the first data value.
116 pub t0: timestamp::LVTime,
117 /// The time in seconds beween samples.
118 pub dt: f64,
119 /// A 1D array of the contained data.
120 pub data: LVArrayHandle<'waveform, 1, T>,
121 #[cfg(target_pointer_width = "64")]
122 _pad: u64,
123 #[cfg(target_pointer_width = "32")]
124 _pad: u32,
125 #[cfg(target_pointer_width = "32")]
126 _mini_pad: u8,
127 attributes: LVVariant<'waveform>,
128 #[cfg(target_pointer_width = "64")]
129 _pad2: u64,
130 #[cfg(target_pointer_width = "32")]
131 _pad2: u32,
132 }
133);