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);