use std::path::PathBuf;
use fmi_schema::{MajorVersion, traits::FmiModelDescription};
use tempfile::TempDir;
use crate::{
Error,
fmi3::{Fmi3Model, binding, instance, schema},
traits::FmiImport,
};
#[derive(Debug)]
pub struct Fmi3Import {
dir: tempfile::TempDir,
model_description: schema::Fmi3ModelDescription,
}
impl FmiImport for Fmi3Import {
const MAJOR_VERSION: MajorVersion = MajorVersion::FMI3;
type ModelDescription = schema::Fmi3ModelDescription;
type Binding = binding::Fmi3Binding;
type ValueRef = binding::fmi3ValueReference;
fn new(dir: TempDir, schema_xml: &str) -> Result<Self, Error> {
let model_description = schema::Fmi3ModelDescription::deserialize(schema_xml)?;
Ok(Self {
dir,
model_description,
})
}
#[inline]
fn archive_path(&self) -> &std::path::Path {
self.dir.path()
}
fn shared_lib_path(&self, model_identifier: &str) -> Result<PathBuf, Error> {
use std::env::consts::{ARCH, OS};
let folder = super::platform_folder(OS, ARCH)?;
let fname = format!("{model_identifier}{}", std::env::consts::DLL_SUFFIX);
Ok(std::path::PathBuf::from("binaries")
.join(folder)
.join(fname))
}
fn model_description(&self) -> &Self::ModelDescription {
&self.model_description
}
fn binding(&self, model_identifier: &str) -> Result<Self::Binding, Error> {
let lib_path = self
.dir
.path()
.join(self.shared_lib_path(model_identifier)?);
log::debug!("Loading shared library {lib_path:?}");
unsafe { binding::Fmi3Binding::new(lib_path).map_err(Error::from) }
}
fn canonical_resource_path_string(&self) -> String {
std::path::absolute(self.resource_path())
.expect("Invalid resource path")
.to_str()
.expect("Invalid resource path")
.to_owned()
}
}
impl Fmi3Model for Fmi3Import {
type InstanceCS = instance::InstanceCS;
type InstanceME = instance::InstanceME;
type InstanceSE = instance::InstanceSE;
#[cfg(false)]
pub fn model(&self) -> &model::ModelDescription {
&self.model
}
fn instantiate_me(
&self,
instance_name: &str,
visible: bool,
logging_on: bool,
) -> Result<Self::InstanceME, Error> {
instance::InstanceME::new(self, instance_name, visible, logging_on)
}
fn instantiate_cs(
&self,
instance_name: &str,
visible: bool,
logging_on: bool,
event_mode_used: bool,
early_return_allowed: bool,
required_intermediate_variables: &[binding::fmi3ValueReference],
) -> Result<Self::InstanceCS, Error> {
instance::InstanceCS::new(
self,
instance_name,
visible,
logging_on,
event_mode_used,
early_return_allowed,
required_intermediate_variables,
)
}
fn instantiate_se(
&self,
instance_name: &str,
visible: bool,
logging_on: bool,
) -> Result<Self::InstanceSE, Error> {
instance::InstanceSE::new(self, instance_name, visible, logging_on)
}
}