dpdu-wrapper 0.2.0

High-level Rust wrapper for D-PDU implementations.
use crate::api::{ApiResult, PduApi};
use crate::types::pdu_status::{PduStatusData, PduStatusTarget};
use crate::vendor_specific::wrap_pdu_call;
use dpdu_api_types::{PDU_HANDLE_UNDEF, PduError, PduStatus};
use std::mem::MaybeUninit;
use tracing::{error, trace};

impl PduApi {
    pub(crate) fn pdu_get_status(&self, target: &PduStatusTarget) -> ApiResult<PduStatusData> {
        impl_defer_clear_suppress_options!(self, get_status);

        const FUNC: &'static str = "PDUGetStatus";
        self.log_api_call(FUNC);

        let h_mod = target.get_module_handle().unwrap_or(PDU_HANDLE_UNDEF);
        let h_cll = target.get_cll_handle().unwrap_or(PDU_HANDLE_UNDEF);
        let h_cop = target.get_cop_handle().unwrap_or(PDU_HANDLE_UNDEF);

        trace!(func = FUNC, h_mod, h_cll, h_cop, "D-PDU API Call Args");

        let mut status_code: MaybeUninit<u32> = MaybeUninit::uninit();
        let mut timestamp: MaybeUninit<u32> = MaybeUninit::uninit();
        let mut extra_info: MaybeUninit<u32> = MaybeUninit::uninit();

        let get_status_fn = self.symbols.get_status;
        let result = wrap_pdu_call(FUNC, || {
            get_status_fn(
                h_mod,
                h_cll,
                h_cop,
                status_code.as_mut_ptr() as _,
                timestamp.as_mut_ptr(),
                extra_info.as_mut_ptr(),
            )
        });

        if !result.is_success() {
            self.log_api_call_fail(
                FUNC,
                result,
                None,
                resolve_level_of_log_api_call_fail!(self, result, get_status),
            );
            return Err(result)?;
        }

        let status_code = unsafe { status_code.assume_init() };
        let timestamp = unsafe { timestamp.assume_init() };
        let extra_info = unsafe { extra_info.assume_init() };

        trace!(
            func = FUNC,
            status_code, timestamp, extra_info, "D-PDU API Call Return"
        );

        let status_code = match PduStatus::try_from(status_code) {
            Ok(v) => v,
            Err(_) => {
                error!(
                    func = FUNC,
                    "Received out-of-bounds PduStatus value: {:#x}. Emulation of PduError::FctFailed...",
                    status_code,
                );
                return Err(PduError::FctFailed)?;
            }
        };

        Ok(PduStatusData {
            target: target.clone(),
            status_code,
            timestamp,
            extra_info,
        })
    }
}