1use fmi::fmi3::{Fmi3Error, binding};
2
3use crate::fmi3::{Clock, types::Binary};
4
5use super::{Context, Model};
6
7macro_rules! model_getter_setter {
9 ($name:ident, $ty:ty) => {
10 paste::paste! {
11 fn [<get_ $name>](
14 &self,
15 _vr: binding::fmi3ValueReference,
16 _values: &mut [$ty],
17 _context: &dyn Context<M>,
18 ) -> Result<usize, Fmi3Error> {
19 Err(Fmi3Error::Error)
20 }
21
22 fn [<set_ $name>](
25 &mut self,
26 _vr: binding::fmi3ValueReference,
27 _values: &[$ty],
28 _context: &dyn Context<M>,
29 ) -> Result<usize, Fmi3Error> {
30 Err(Fmi3Error::Error)
31 }
32 }
33 };
34}
35
36macro_rules! impl_model_get_set_primitive {
38 ($name:ident, $ty:ty, $data_type:expr) => {
39 paste::paste! {
40 impl<M: Model> ModelGetSet<M> for $ty {
41 const FIELD_COUNT: usize = 1;
42 fn [<get_ $name>](
43 &self,
44 vr: binding::fmi3ValueReference,
45 values: &mut [$ty],
46 _context: &dyn Context<M>,
47 ) -> Result<usize, Fmi3Error> {
48 if vr == 0 && !values.is_empty() {
49 values[0] = *self;
50 Ok(1)
51 } else {
52 Err(Fmi3Error::Error)
53 }
54 }
55 fn [<set_ $name>](
56 &mut self,
57 vr: binding::fmi3ValueReference,
58 values: &[$ty],
59 _context: &dyn Context<M>,
60 ) -> Result<usize, Fmi3Error> {
61 if vr == 0 && !values.is_empty() {
62 *self = values[0];
63 Ok(1)
64 } else {
65 Err(Fmi3Error::Error)
66 }
67 }
68 }
69
70 impl<M: Model, const N: usize> ModelGetSet<M> for [$ty; N] {
71 const FIELD_COUNT: usize = N;
72 fn [<get_ $name>](
73 &self,
74 vr: binding::fmi3ValueReference,
75 values: &mut [$ty],
76 _context: &dyn Context<M>,
77 ) -> Result<usize, Fmi3Error> {
78 if (vr as usize) < N && !values.is_empty() {
79 let len = std::cmp::min(N - (vr as usize), values.len());
80 values[..len].copy_from_slice(&self[(vr as usize)..(vr as usize + len)]);
81 Ok(len)
82 } else {
83 Err(Fmi3Error::Error)
84 }
85 }
86 fn [<set_ $name>](
87 &mut self,
88 vr: binding::fmi3ValueReference,
89 values: &[$ty],
90 _context: &dyn Context<M>,
91 ) -> Result<usize, Fmi3Error> {
92 if (vr as usize) < N && !values.is_empty() {
93 let len = std::cmp::min(N - (vr as usize), values.len());
94 self[(vr as usize)..(vr as usize + len)].copy_from_slice(&values[..len]);
95 Ok(len)
96 } else {
97 Err(Fmi3Error::Error)
98 }
99 }
100 }
101 }
102 };
103}
104
105pub trait ModelGetSet<M: Model> {
106 const FIELD_COUNT: usize;
108
109 model_getter_setter!(boolean, bool);
110 model_getter_setter!(float32, f32);
111 model_getter_setter!(float64, f64);
112 model_getter_setter!(int8, i8);
113 model_getter_setter!(int16, i16);
114 model_getter_setter!(int32, i32);
115 model_getter_setter!(int64, i64);
116 model_getter_setter!(uint8, u8);
117 model_getter_setter!(uint16, u16);
118 model_getter_setter!(uint32, u32);
119 model_getter_setter!(uint64, u64);
120 model_getter_setter!(string, std::ffi::CString);
121
122 fn get_binary(
125 &self,
126 _vr: binding::fmi3ValueReference,
127 _values: &mut [&mut [u8]],
128 _context: &dyn Context<M>,
129 ) -> Result<Vec<usize>, Fmi3Error> {
130 Err(Fmi3Error::Error)
131 }
132
133 fn set_binary(
136 &mut self,
137 _vr: binding::fmi3ValueReference,
138 _values: &[&[u8]],
139 _context: &dyn Context<M>,
140 ) -> Result<usize, Fmi3Error> {
141 Err(Fmi3Error::Error)
142 }
143
144 fn get_clock(
147 &mut self,
148 _vr: binding::fmi3ValueReference,
149 _value: &mut binding::fmi3Clock,
150 _context: &dyn Context<M>,
151 ) -> Result<(), Fmi3Error> {
152 Err(Fmi3Error::Error)
153 }
154
155 fn set_clock(
157 &mut self,
158 _vr: binding::fmi3ValueReference,
159 _value: &binding::fmi3Clock,
160 _context: &dyn Context<M>,
161 ) -> Result<(), Fmi3Error> {
162 Err(Fmi3Error::Error)
163 }
164}
165
166impl_model_get_set_primitive!(boolean, bool, schema::DataType::Boolean);
167impl_model_get_set_primitive!(float32, f32, schema::DataType::Float32);
168impl_model_get_set_primitive!(float64, f64, schema::DataType::Float64);
169impl_model_get_set_primitive!(int8, i8, schema::DataType::Int8);
170impl_model_get_set_primitive!(int16, i16, schema::DataType::Int16);
171impl_model_get_set_primitive!(int32, i32, schema::DataType::Int32);
172impl_model_get_set_primitive!(int64, i64, schema::DataType::Int64);
173impl_model_get_set_primitive!(uint8, u8, schema::DataType::Uint8);
174impl_model_get_set_primitive!(uint16, u16, schema::DataType::Uint16);
175impl_model_get_set_primitive!(uint32, u32, schema::DataType::Uint32);
176impl_model_get_set_primitive!(uint64, u64, schema::DataType::Uint64);
177
178impl<M: Model> ModelGetSet<M> for String {
179 const FIELD_COUNT: usize = 1;
180 fn get_string(
181 &self,
182 vr: binding::fmi3ValueReference,
183 values: &mut [std::ffi::CString],
184 _context: &dyn Context<M>,
185 ) -> Result<usize, Fmi3Error> {
186 if vr == 0 && !values.is_empty() {
187 values[0] = std::ffi::CString::new(self.as_str()).unwrap();
188 Ok(1)
189 } else {
190 Err(Fmi3Error::Error)
191 }
192 }
193 fn set_string(
194 &mut self,
195 vr: binding::fmi3ValueReference,
196 values: &[std::ffi::CString],
197 _context: &dyn Context<M>,
198 ) -> Result<usize, Fmi3Error> {
199 if vr == 0 && !values.is_empty() {
200 *self = values[0]
201 .to_str()
202 .map_err(|_| Fmi3Error::Error)?
203 .to_string();
204 Ok(1)
205 } else {
206 Err(Fmi3Error::Error)
207 }
208 }
209}
210
211impl<M: Model> ModelGetSet<M> for Clock {
212 const FIELD_COUNT: usize = 1;
213 fn get_clock(
214 &mut self,
215 vr: binding::fmi3ValueReference,
216 value: &mut binding::fmi3Clock,
217 _context: &dyn Context<M>,
218 ) -> Result<(), Fmi3Error> {
219 if vr == 0 {
220 *value = self.0;
221 self.0 = false;
223 Ok(())
224 } else {
225 Err(Fmi3Error::Error)
226 }
227 }
228 fn set_clock(
229 &mut self,
230 vr: binding::fmi3ValueReference,
231 value: &binding::fmi3Clock,
232 _context: &dyn Context<M>,
233 ) -> Result<(), Fmi3Error> {
234 if vr == 0 {
235 self.0 = *value;
236 Ok(())
237 } else {
238 Err(Fmi3Error::Error)
239 }
240 }
241}
242
243impl<M: Model> ModelGetSet<M> for Binary {
244 const FIELD_COUNT: usize = 1;
245 fn get_binary(
246 &self,
247 vr: binding::fmi3ValueReference,
248 values: &mut [&mut [u8]],
249 _context: &dyn Context<M>,
250 ) -> Result<Vec<usize>, Fmi3Error> {
251 if vr == 0 && !values.is_empty() {
252 let len = std::cmp::min(self.0.len(), values[0].len());
253 values[0][..len].copy_from_slice(&self.0[..len]);
254 Ok(vec![len])
255 } else {
256 Err(Fmi3Error::Error)
257 }
258 }
259 fn set_binary(
260 &mut self,
261 vr: binding::fmi3ValueReference,
262 values: &[&[u8]],
263 _context: &dyn Context<M>,
264 ) -> Result<usize, Fmi3Error> {
265 if vr == 0 && !values.is_empty() {
266 self.0.clear();
267 self.0.extend_from_slice(values[0]);
268 Ok(1)
269 } else {
270 Err(Fmi3Error::Error)
271 }
272 }
273}
274
275pub trait ModelGetSetStates {
276 const NUM_STATES: usize;
278
279 fn get_continuous_states(&self, states: &mut [f64]) -> Result<(), Fmi3Error>;
282
283 fn set_continuous_states(&mut self, states: &[f64]) -> Result<(), Fmi3Error>;
286
287 fn get_continuous_state_derivatives(
290 &mut self,
291 derivatives: &mut [f64],
292 ) -> Result<(), Fmi3Error>;
293}
294
295impl ModelGetSetStates for f64 {
296 const NUM_STATES: usize = 1;
297
298 fn get_continuous_states(&self, states: &mut [f64]) -> Result<(), Fmi3Error> {
299 if states.is_empty() {
300 Err(Fmi3Error::Error)
301 } else {
302 states[0] = *self;
303 Ok(())
304 }
305 }
306
307 fn set_continuous_states(&mut self, states: &[f64]) -> Result<(), Fmi3Error> {
308 if states.is_empty() {
309 Err(Fmi3Error::Error)
310 } else {
311 *self = states[0];
312 Ok(())
313 }
314 }
315
316 fn get_continuous_state_derivatives(
317 &mut self,
318 derivatives: &mut [f64],
319 ) -> Result<(), Fmi3Error> {
320 if derivatives.is_empty() {
321 Err(Fmi3Error::Error)
322 } else {
323 derivatives[0] = *self;
324 Ok(())
325 }
326 }
327}
328
329impl<const N: usize> ModelGetSetStates for [f64; N] {
330 const NUM_STATES: usize = N;
331
332 fn get_continuous_states(&self, states: &mut [f64]) -> Result<(), Fmi3Error> {
333 if states.len() < Self::NUM_STATES {
334 Err(Fmi3Error::Error)
335 } else {
336 states[0..N].copy_from_slice(self);
337 Ok(())
338 }
339 }
340
341 fn set_continuous_states(&mut self, states: &[f64]) -> Result<(), Fmi3Error> {
342 if states.len() < Self::NUM_STATES {
343 Err(Fmi3Error::Error)
344 } else {
345 self.copy_from_slice(&states[0..N]);
346 Ok(())
347 }
348 }
349
350 fn get_continuous_state_derivatives(
351 &mut self,
352 derivatives: &mut [f64],
353 ) -> Result<(), Fmi3Error> {
354 if derivatives.len() < Self::NUM_STATES {
355 Err(Fmi3Error::Error)
356 } else {
357 derivatives[0..N].copy_from_slice(self);
358 Ok(())
359 }
360 }
361}