fmi 0.7.0

A Rust interface to FMUs (Functional Mockup Units) that follow the FMI Standard. See http://www.fmi-standard.org/
Documentation
use std::ffi::CString;

use crate::schema::traits::FmiInterfaceType;

use crate::{
    Error,
    fmi3::{Fmi3Error, Fmi3Res, Fmi3Status, ScheduledExecution, binding, import, logger},
    traits::{FmiImport, FmiStatus},
};

use super::{Instance, SE};

unsafe extern "C" fn clock_update(_instance_environment: binding::fmi3InstanceEnvironment) {
    todo!();
}
unsafe extern "C" fn lock_preemption() {
    todo!();
}
unsafe extern "C" fn unlock_preemption() {
    todo!();
}

impl Instance<SE> {
    pub fn new(
        import: &import::Fmi3Import,
        instance_name: &str,
        visible: bool,
        logging_on: bool,
    ) -> Result<Self, Error> {
        let schema = import.model_description();

        let name = instance_name.to_owned();

        let scheduled_execution = schema
            .scheduled_execution
            .as_ref()
            .ok_or(Error::UnsupportedFmuType("ScheduledExecution".to_owned()))?;

        log::debug!(
            "Instantiating ME: {} '{name}'",
            scheduled_execution.model_identifier()
        );

        let binding = import.binding(scheduled_execution.model_identifier())?;

        let instance_name = CString::new(instance_name).expect("Invalid instance name");
        let instantiation_token = CString::new(schema.instantiation_token.as_bytes())
            .expect("Invalid instantiation token");
        let resource_path =
            CString::new(import.canonical_resource_path_string()).expect("Invalid resource path");

        let instance = unsafe {
            binding.fmi3InstantiateScheduledExecution(
                instance_name.as_ptr(),
                instantiation_token.as_ptr(),
                resource_path.as_ptr() as binding::fmi3String,
                visible,
                logging_on,
                std::ptr::null_mut() as binding::fmi3InstanceEnvironment,
                Some(logger::callback_log),
                Some(clock_update),
                Some(lock_preemption),
                Some(unlock_preemption),
            )
        };

        if instance.is_null() {
            return Err(Error::Instantiation);
        }

        Ok(Self {
            binding,
            ptr: instance,
            name,
            _tag: std::marker::PhantomData,
        })
    }
}

impl ScheduledExecution for Instance<SE> {
    fn activate_model_partition(
        &mut self,
        clock_reference: binding::fmi3ValueReference,
        activation_time: f64,
    ) -> Result<Fmi3Res, Fmi3Error> {
        Fmi3Status::from(unsafe {
            self.binding
                .fmi3ActivateModelPartition(self.ptr, clock_reference, activation_time)
        })
        .ok()
    }
}