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}