use fmi::fmi3::{Fmi3Error, Fmi3Status, binding};
use crate::fmi3::{
ModelState, UserModel,
traits::{Context, Model},
};
mod common;
pub mod context;
mod get_set;
mod impl_cs;
mod impl_me;
mod impl_se;
pub type LogMessageClosure = Box<dyn Fn(Fmi3Status, &str, std::fmt::Arguments<'_>) + Send + Sync>;
pub type IntermediateUpdateClosure =
Box<dyn Fn(f64, bool, bool, bool, bool) -> Option<f64> + Send + Sync>;
#[repr(C)]
pub struct ModelInstance<M, C>
where
M: UserModel,
C: Context<M>,
{
pub(crate) instance_type: fmi::InterfaceType,
instance_name: String,
context: C,
state: ModelState,
is_dirty_values: bool,
model: M,
}
impl<M, C> ModelInstance<M, C>
where
M: Model + UserModel,
C: Context<M>,
{
pub fn new(
name: String,
instantiation_token: &str,
context: C,
instance_type: fmi::InterfaceType,
) -> Result<Self, Fmi3Error> {
if instantiation_token != M::INSTANTIATION_TOKEN {
eprintln!(
"Instantiation token mismatch. Expected: '{}', got: '{}'",
M::INSTANTIATION_TOKEN,
instantiation_token
);
return Err(Fmi3Error::Error);
}
let mut instance = Self {
instance_name: name,
context,
state: ModelState::Instantiated,
instance_type,
is_dirty_values: true,
model: M::default(),
};
instance.model.set_start_values();
Ok(instance)
}
pub fn instance_name(&self) -> &str {
&self.instance_name
}
pub fn instance_type(&self) -> fmi::InterfaceType {
self.instance_type
}
pub fn context(&self) -> &C {
&self.context
}
#[inline]
pub fn assert_instance_type(&self, expected: fmi::InterfaceType) -> Result<(), Fmi3Error> {
if self.instance_type != expected {
self.context.log(
Fmi3Error::Error.into(),
M::LoggingCategory::default(),
format_args!(
"Instance type mismatch. Expected: {:?}, got: {:?}",
expected, self.instance_type
),
);
return Err(Fmi3Error::Error);
}
Ok(())
}
fn validate_variable_setting(&self, vr: binding::fmi3ValueReference) -> Result<(), Fmi3Error> {
match M::validate_variable_setting(vr, &self.state) {
Ok(()) => Ok(()),
Err(message) => {
self.context.log(
Fmi3Error::Error.into(),
M::LoggingCategory::default(),
format_args!("Variable setting error for VR {vr}: {message}"),
);
Err(Fmi3Error::Error)
}
}
}
}