ichen_openprotocol/
state_values.rs

1use super::{JobMode, OpMode, TextName, ID};
2use serde::{Deserialize, Serialize};
3use std::convert::TryInto;
4
5/// A data structure containing a snapshot of the current known states of the controller.
6///
7#[derive(Debug, Eq, PartialEq, Clone, Hash, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct StateValues<'a> {
10    /// Current operating mold of the controller.
11    #[serde(skip_serializing_if = "OpMode::is_unknown")]
12    #[serde(default)]
13    op_mode: OpMode,
14    //
15    /// Current job mode of the controller.
16    #[serde(skip_serializing_if = "JobMode::is_unknown")]
17    #[serde(default)]
18    job_mode: JobMode,
19    //
20    /// Unique ID of the current logged-in user (if any) on the controller.
21    #[serde(skip_serializing_if = "Option::is_none")]
22    operator_id: Option<ID>,
23    //
24    /// Current active job ID (if any) on the controller.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    #[serde(borrow)]
27    job_card_id: Option<Box<TextName<'a>>>,
28    //
29    /// Unique ID of the set of mold data currently loaded (if any) on the controller.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    #[serde(borrow)]
32    mold_id: Option<Box<TextName<'a>>>,
33}
34
35impl<'a> StateValues<'a> {
36    /// Get the op-mode.
37    ///
38    ///
39    /// # Examples
40    ///
41    /// ~~~
42    /// # use ichen_openprotocol::*;
43    /// # use std::borrow::Cow;
44    /// # fn main() -> std::result::Result<(), String> {
45    /// let state = StateValues::try_new_with_all(
46    ///     OpMode::Automatic,
47    ///     JobMode::ID02,
48    ///     Some(ID::from_u32(123)),
49    ///     None,
50    ///     Some("M001")
51    /// )?;
52    ///
53    /// assert_eq!(OpMode::Automatic, state.op_mode());
54    /// # Ok(())
55    /// # }
56    /// ~~~
57    pub fn op_mode(&self) -> OpMode {
58        self.op_mode
59    }
60
61    /// Get the job mode.
62    ///
63    ///
64    /// # Examples
65    ///
66    /// ~~~
67    /// # use ichen_openprotocol::*;
68    /// # use std::borrow::Cow;
69    /// # fn main() -> std::result::Result<(), String> {
70    /// let state = StateValues::try_new_with_all(
71    ///     OpMode::Automatic,
72    ///     JobMode::ID02,
73    ///     Some(ID::from_u32(123)),
74    ///     None,
75    ///     Some("M001")
76    /// )?;
77    ///
78    /// assert_eq!(JobMode::ID02, state.job_mode());
79    /// # Ok(())
80    /// # }
81    /// ~~~
82    pub fn job_mode(&self) -> JobMode {
83        self.job_mode
84    }
85
86    /// Get the operator ID, if any.
87    ///
88    ///
89    /// # Examples
90    ///
91    /// ~~~
92    /// # use ichen_openprotocol::*;
93    /// # use std::borrow::Cow;
94    /// # fn main() -> std::result::Result<(), String> {
95    /// let state = StateValues::try_new_with_all(
96    ///     OpMode::Automatic,
97    ///     JobMode::ID02,
98    ///     Some(ID::from_u32(123)),
99    ///     None,
100    ///     Some("M001")
101    /// )?;
102    ///
103    /// assert_eq!(123, state.operator_id().unwrap());
104    /// # Ok(())
105    /// # }
106    /// ~~~
107    pub fn operator_id(&self) -> Option<ID> {
108        self.operator_id
109    }
110
111    /// Get the job card ID, if any.
112    ///
113    ///
114    /// # Examples
115    ///
116    /// ~~~
117    /// # use ichen_openprotocol::*;
118    /// # use std::borrow::Cow;
119    /// # fn main() -> std::result::Result<(), String> {
120    /// let state = StateValues::try_new_with_all(
121    ///     OpMode::Automatic,
122    ///     JobMode::ID02,
123    ///     Some(ID::from_u32(123)),
124    ///     Some("JC001"),
125    ///     None
126    /// )?;
127    ///
128    /// assert_eq!(Some("JC001"), state.job_card_id());
129    /// # Ok(())
130    /// # }
131    /// ~~~
132    #[allow(clippy::borrowed_box)]
133    pub fn job_card_id(&self) -> Option<&str> {
134        self.job_card_id.as_ref().map(|jc| jc.get())
135    }
136
137    /// Get the mold ID, if any.
138    ///
139    ///
140    /// # Examples
141    ///
142    /// ~~~
143    /// # use ichen_openprotocol::*;
144    /// # use std::borrow::Cow;
145    /// # fn main() -> std::result::Result<(), String> {
146    /// let state = StateValues::try_new_with_all(
147    ///     OpMode::Automatic,
148    ///     JobMode::ID02,
149    ///     Some(ID::from_u32(123)),
150    ///     None,
151    ///     Some("M001")
152    /// )?;
153    ///
154    /// assert_eq!(Some("M001"), state.mold_id());
155    /// # Ok(())
156    /// # }
157    /// ~~~
158    #[allow(clippy::borrowed_box)]
159    pub fn mold_id(&self) -> Option<&str> {
160        self.mold_id.as_ref().map(|m| m.get())
161    }
162
163    /// Create a new `StateValues` wth no operator ID, job card ID and mold ID.
164    ///
165    /// # Examples
166    ///
167    /// ~~~
168    /// # use ichen_openprotocol::*;
169    /// let state = StateValues::new(OpMode::Automatic, JobMode::ID02);
170    /// assert_eq!(OpMode::Automatic, state.op_mode());
171    /// assert_eq!(JobMode::ID02, state.job_mode());
172    /// assert_eq!(None, state.operator_id());
173    /// assert_eq!(None, state.job_card_id());
174    /// assert_eq!(None, state.mold_id());
175    /// ~~~
176    pub fn new(op: OpMode, job: JobMode) -> Self {
177        Self { op_mode: op, job_mode: job, operator_id: None, job_card_id: None, mold_id: None }
178    }
179
180    /// Create a new `StateValues` with all fields set.
181    ///
182    /// # Errors
183    ///
184    /// Returns `Err(String)` if `job_card_id` or `mold_id` is set to an empty string
185    /// or is all whitespace.
186    ///
187    /// ## Error Examples
188    ///
189    /// ~~~
190    /// # use ichen_openprotocol::*;
191    /// let sv = StateValues::try_new_with_all(
192    ///     OpMode::Automatic,
193    ///     JobMode::ID02,
194    ///     Some(ID::from_u32(123)),
195    ///     Some(""),    // <-- Notice empty string for job_Card_id which is not allowed
196    ///     None
197    /// );
198    /// assert_eq!(Err("invalid value: a non-empty, non-whitespace string required for job card ID".into()), sv);
199    /// ~~~
200    ///
201    /// # Examples
202    ///
203    /// ~~~
204    /// # use ichen_openprotocol::*;
205    /// # use std::borrow::Cow;
206    /// # fn main() -> std::result::Result<(), String> {
207    /// let state = StateValues::try_new_with_all(
208    ///     OpMode::Automatic,
209    ///     JobMode::ID02,
210    ///     Some(ID::from_u32(123)),
211    ///     None,
212    ///     Some("M001")
213    /// )?;
214    ///
215    /// assert_eq!(OpMode::Automatic, state.op_mode());
216    /// assert_eq!(JobMode::ID02, state.job_mode());
217    /// assert_eq!(123, state.operator_id().unwrap());
218    /// assert_eq!(None, state.job_card_id());
219    /// assert_eq!(Some("M001"), state.mold_id());
220    /// # Ok(())
221    /// # }
222    /// ~~~
223    ///
224    /// [`OpenProtocolError::EmptyField`]: enum.OpenProtocolError.html#variant.EmptyField
225    ///
226    pub fn try_new_with_all(
227        op: OpMode,
228        job: JobMode,
229        operator_id: Option<ID>,
230        job_card_id: Option<&'a str>,
231        mold_id: Option<&'a str>,
232    ) -> std::result::Result<Self, String> {
233        let job_card_id = if let Some(jc) = job_card_id {
234            Some(jc.try_into().map(Box::new).map_err(|e| format!("{} for job card ID", e))?)
235        } else {
236            None
237        };
238
239        let mold_id = if let Some(m) = mold_id {
240            Some(m.try_into().map(Box::new).map_err(|e| format!("{} for mold ID", e))?)
241        } else {
242            None
243        };
244
245        Ok(Self { operator_id, job_card_id, mold_id, ..Self::new(op, job) })
246    }
247}
248
249impl Default for StateValues<'_> {
250    /// Default value of `StateValues`.
251    ///
252    fn default() -> Self {
253        Self {
254            op_mode: OpMode::Unknown,
255            job_mode: JobMode::Unknown,
256            operator_id: None,
257            job_card_id: None,
258            mold_id: None,
259        }
260    }
261}