ichen-openprotocol 0.5.0

iChen Open Protocol access library.
Documentation
use super::{JobMode, OpMode, TextName, ID};
use serde::{Deserialize, Serialize};
use std::convert::TryInto;

/// A data structure containing a snapshot of the current known states of the controller.
///
#[derive(Debug, Eq, PartialEq, Clone, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StateValues<'a> {
    /// Current operating mold of the controller.
    #[serde(skip_serializing_if = "OpMode::is_unknown")]
    #[serde(default)]
    op_mode: OpMode,
    //
    /// Current job mode of the controller.
    #[serde(skip_serializing_if = "JobMode::is_unknown")]
    #[serde(default)]
    job_mode: JobMode,
    //
    /// Unique ID of the current logged-in user (if any) on the controller.
    #[serde(skip_serializing_if = "Option::is_none")]
    operator_id: Option<ID>,
    //
    /// Current active job ID (if any) on the controller.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(borrow)]
    job_card_id: Option<Box<TextName<'a>>>,
    //
    /// Unique ID of the set of mold data currently loaded (if any) on the controller.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(borrow)]
    mold_id: Option<Box<TextName<'a>>>,
}

impl<'a> StateValues<'a> {
    /// Get the op-mode.
    ///
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     None,
    ///     Some("M001")
    /// )?;
    ///
    /// assert_eq!(OpMode::Automatic, state.op_mode());
    /// # Ok(())
    /// # }
    /// ~~~
    pub fn op_mode(&self) -> OpMode {
        self.op_mode
    }

    /// Get the job mode.
    ///
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     None,
    ///     Some("M001")
    /// )?;
    ///
    /// assert_eq!(JobMode::ID02, state.job_mode());
    /// # Ok(())
    /// # }
    /// ~~~
    pub fn job_mode(&self) -> JobMode {
        self.job_mode
    }

    /// Get the operator ID, if any.
    ///
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     None,
    ///     Some("M001")
    /// )?;
    ///
    /// assert_eq!(123, state.operator_id().unwrap());
    /// # Ok(())
    /// # }
    /// ~~~
    pub fn operator_id(&self) -> Option<ID> {
        self.operator_id
    }

    /// Get the job card ID, if any.
    ///
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     Some("JC001"),
    ///     None
    /// )?;
    ///
    /// assert_eq!(Some("JC001"), state.job_card_id());
    /// # Ok(())
    /// # }
    /// ~~~
    #[allow(clippy::borrowed_box)]
    pub fn job_card_id(&self) -> Option<&str> {
        self.job_card_id.as_ref().map(|jc| jc.get())
    }

    /// Get the mold ID, if any.
    ///
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     None,
    ///     Some("M001")
    /// )?;
    ///
    /// assert_eq!(Some("M001"), state.mold_id());
    /// # Ok(())
    /// # }
    /// ~~~
    #[allow(clippy::borrowed_box)]
    pub fn mold_id(&self) -> Option<&str> {
        self.mold_id.as_ref().map(|m| m.get())
    }

    /// Create a new `StateValues` wth no operator ID, job card ID and mold ID.
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// let state = StateValues::new(OpMode::Automatic, JobMode::ID02);
    /// assert_eq!(OpMode::Automatic, state.op_mode());
    /// assert_eq!(JobMode::ID02, state.job_mode());
    /// assert_eq!(None, state.operator_id());
    /// assert_eq!(None, state.job_card_id());
    /// assert_eq!(None, state.mold_id());
    /// ~~~
    pub fn new(op: OpMode, job: JobMode) -> Self {
        Self { op_mode: op, job_mode: job, operator_id: None, job_card_id: None, mold_id: None }
    }

    /// Create a new `StateValues` with all fields set.
    ///
    /// # Errors
    ///
    /// Returns `Err(String)` if `job_card_id` or `mold_id` is set to an empty string
    /// or is all whitespace.
    ///
    /// ## Error Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// let sv = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     Some(""),    // <-- Notice empty string for job_Card_id which is not allowed
    ///     None
    /// );
    /// assert_eq!(Err("invalid value: a non-empty, non-whitespace string required for job card ID".into()), sv);
    /// ~~~
    ///
    /// # Examples
    ///
    /// ~~~
    /// # use ichen_openprotocol::*;
    /// # use std::borrow::Cow;
    /// # fn main() -> std::result::Result<(), String> {
    /// let state = StateValues::try_new_with_all(
    ///     OpMode::Automatic,
    ///     JobMode::ID02,
    ///     Some(ID::from_u32(123)),
    ///     None,
    ///     Some("M001")
    /// )?;
    ///
    /// assert_eq!(OpMode::Automatic, state.op_mode());
    /// assert_eq!(JobMode::ID02, state.job_mode());
    /// assert_eq!(123, state.operator_id().unwrap());
    /// assert_eq!(None, state.job_card_id());
    /// assert_eq!(Some("M001"), state.mold_id());
    /// # Ok(())
    /// # }
    /// ~~~
    ///
    /// [`OpenProtocolError::EmptyField`]: enum.OpenProtocolError.html#variant.EmptyField
    ///
    pub fn try_new_with_all(
        op: OpMode,
        job: JobMode,
        operator_id: Option<ID>,
        job_card_id: Option<&'a str>,
        mold_id: Option<&'a str>,
    ) -> std::result::Result<Self, String> {
        let job_card_id = if let Some(jc) = job_card_id {
            Some(jc.try_into().map(Box::new).map_err(|e| format!("{} for job card ID", e))?)
        } else {
            None
        };

        let mold_id = if let Some(m) = mold_id {
            Some(m.try_into().map(Box::new).map_err(|e| format!("{} for mold ID", e))?)
        } else {
            None
        };

        Ok(Self { operator_id, job_card_id, mold_id, ..Self::new(op, job) })
    }
}

impl Default for StateValues<'_> {
    /// Default value of `StateValues`.
    ///
    fn default() -> Self {
        Self {
            op_mode: OpMode::Unknown,
            job_mode: JobMode::Unknown,
            operator_id: None,
            job_card_id: None,
            mold_id: None,
        }
    }
}