1mod errors;
8pub mod well_known;
9
10pub use errors::*;
11
12use crate::{
13 errors::NetworkParseError,
14 mion::proto::parameter::well_known::{index_from_parameter_name, ValuableParameterDump},
15};
16use bytes::{BufMut, Bytes, BytesMut};
17use std::fmt::{Display, Formatter, Result as FmtResult};
18use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value};
19
20#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Valuable)]
22pub enum PacketType {
23 Read,
25 Write,
27}
28
29impl From<&PacketType> for i32 {
30 fn from(value: &PacketType) -> Self {
31 match *value {
32 PacketType::Read => 0,
33 PacketType::Write => 1,
34 }
35 }
36}
37impl From<PacketType> for i32 {
38 fn from(value: PacketType) -> Self {
39 Self::from(&value)
40 }
41}
42
43impl TryFrom<i32> for PacketType {
44 type Error = MIONParamProtocolError;
45
46 fn try_from(value: i32) -> Result<Self, Self::Error> {
47 match value {
48 0 => Ok(Self::Read),
49 1 => Ok(Self::Write),
50 _ => Err(MIONParamProtocolError::PacketType(value)),
51 }
52 }
53}
54
55#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Valuable)]
57pub struct MionDumpParameters;
58
59impl MionDumpParameters {
60 #[must_use]
63 pub const fn new() -> Self {
64 Self {}
65 }
66}
67
68impl Default for MionDumpParameters {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl Display for MionDumpParameters {
75 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
76 write!(fmt, "MionDumpParameters")
77 }
78}
79
80impl TryFrom<Bytes> for MionDumpParameters {
81 type Error = NetworkParseError;
82
83 fn try_from(packet: Bytes) -> Result<Self, Self::Error> {
84 if packet.len() < 8 {
85 return Err(NetworkParseError::NotEnoughData(
86 "MionDumpParameters",
87 8,
88 packet.len(),
89 packet,
90 ));
91 }
92 if packet.len() > 8 {
93 return Err(NetworkParseError::UnexpectedTrailer(
94 "MionDumpParameters",
95 packet.slice(8..),
96 ));
97 }
98
99 let static_bytes: &'static [u8] = &[0_u8, 0, 0, 0, 0, 0, 0, 0];
102 if packet != static_bytes {
103 return Err(NetworkParseError::DoesntMatchStaticPayload(
104 "MionDumpParameters",
105 static_bytes,
106 packet,
107 ));
108 }
109
110 Ok(Self)
111 }
112}
113
114impl From<&MionDumpParameters> for Bytes {
115 fn from(_: &MionDumpParameters) -> Self {
116 BytesMut::zeroed(8).freeze()
117 }
118}
119impl From<MionDumpParameters> for Bytes {
120 fn from(value: MionDumpParameters) -> Self {
121 Self::from(&value)
122 }
123}
124
125const DUMPED_MION_PARAMETERS_FIELDS: &[NamedField<'static>] = &[NamedField::new("parameters")];
126#[derive(Clone, Debug, Hash, PartialEq, Eq)]
128pub struct DumpedMionParameters {
129 parameters: Bytes,
131}
132
133impl DumpedMionParameters {
134 #[must_use]
136 pub const fn get_raw_parameters(&self) -> &Bytes {
137 &self.parameters
138 }
139
140 pub fn get_parameter_by_name(&self, name: &str) -> Result<u8, MIONParameterAPIError> {
146 index_from_parameter_name(name)
147 .map(|index| self.parameters[index])
148 .ok_or_else(|| MIONParameterAPIError::NameNotKnown(name.to_owned()))
149 }
150
151 pub fn get_parameter_by_index(&self, index: usize) -> Result<u8, MIONParameterAPIError> {
157 if index > 511 {
158 return Err(MIONParameterAPIError::NotInRange(index));
159 }
160 Ok(self.parameters[index])
161 }
162}
163
164impl TryFrom<Bytes> for DumpedMionParameters {
165 type Error = NetworkParseError;
166
167 fn try_from(packet: Bytes) -> Result<Self, Self::Error> {
168 if packet.len() < 520 {
169 return Err(NetworkParseError::NotEnoughData(
170 "DumpedMionParameters",
171 520,
172 packet.len(),
173 packet,
174 ));
175 }
176 if packet.len() > 520 {
177 return Err(NetworkParseError::UnexpectedTrailer(
178 "DumpedMionParameters",
179 packet.slice(520..),
180 ));
181 }
182
183 let header = packet.slice(..8);
184 let packet_type = PacketType::try_from(i32::from_le_bytes([
185 header[0], header[1], header[2], header[3],
186 ]))?;
187 if packet_type != PacketType::Read {
188 return Err(MIONParamProtocolError::PacketType(i32::from(packet_type)).into());
189 }
190 let size_or_error = i32::from_le_bytes([header[4], header[5], header[6], header[7]]);
191 if size_or_error != 512 {
192 return Err(MIONParamProtocolError::ErrorCode(size_or_error).into());
193 }
194 let parameters = packet.slice(8..);
195
196 Ok(Self { parameters })
197 }
198}
199
200impl From<&DumpedMionParameters> for Bytes {
201 fn from(value: &DumpedMionParameters) -> Self {
202 let mut buff = BytesMut::with_capacity(520);
203 buff.put_i32_le(i32::from(PacketType::Read));
204 buff.put_i32_le(512);
206 buff.extend_from_slice(&value.parameters);
207 buff.freeze()
208 }
209}
210impl From<DumpedMionParameters> for Bytes {
211 fn from(value: DumpedMionParameters) -> Self {
212 Self::from(&value)
213 }
214}
215
216impl Structable for DumpedMionParameters {
217 fn definition(&self) -> StructDef<'_> {
218 StructDef::new_static(
219 "DumpedMionParameters",
220 Fields::Named(DUMPED_MION_PARAMETERS_FIELDS),
221 )
222 }
223}
224impl Valuable for DumpedMionParameters {
225 fn as_value(&self) -> Value<'_> {
226 Value::Structable(self)
227 }
228
229 fn visit(&self, visitor: &mut dyn valuable::Visit) {
230 let dump = ValuableParameterDump(&self.parameters);
231
232 visitor.visit_named_fields(&NamedValues::new(
233 DUMPED_MION_PARAMETERS_FIELDS,
234 &[Valuable::as_value(&dump)],
235 ));
236 }
237}
238
239#[derive(Clone, Debug, Hash, PartialEq, Eq)]
243pub struct SetMionParameters {
244 parameters: Bytes,
245}
246
247impl SetMionParameters {
248 pub fn new(parameters: Bytes) -> Result<Self, MIONParameterAPIError> {
258 if parameters.len() != 512 {
259 return Err(MIONParameterAPIError::BodyNotCorrectLength(
260 parameters.len(),
261 ));
262 }
263
264 Ok(Self { parameters })
265 }
266
267 #[must_use]
269 pub const fn get_raw_parameters(&self) -> &Bytes {
270 &self.parameters
271 }
272
273 pub fn get_parameter_by_name(&self, name: &str) -> Result<u8, MIONParameterAPIError> {
279 index_from_parameter_name(name)
280 .map(|index| self.parameters[index])
281 .ok_or_else(|| MIONParameterAPIError::NameNotKnown(name.to_owned()))
282 }
283
284 pub fn get_parameter_by_index(&self, index: usize) -> Result<u8, MIONParameterAPIError> {
290 if index > 511 {
291 return Err(MIONParameterAPIError::NotInRange(index));
292 }
293 Ok(self.parameters[index])
294 }
295}
296
297impl TryFrom<Bytes> for SetMionParameters {
298 type Error = NetworkParseError;
299
300 fn try_from(packet: Bytes) -> Result<Self, Self::Error> {
301 if packet.len() < 520 {
302 return Err(NetworkParseError::NotEnoughData(
303 "SetMionParameters",
304 520,
305 packet.len(),
306 packet,
307 ));
308 }
309 if packet.len() > 520 {
310 return Err(NetworkParseError::UnexpectedTrailer(
311 "SetMionParameters",
312 packet.slice(520..),
313 ));
314 }
315
316 let header = packet.slice(..8);
317 let packet_type = PacketType::try_from(i32::from_le_bytes([
318 header[0], header[1], header[2], header[3],
319 ]))?;
320 if packet_type != PacketType::Write {
321 return Err(MIONParamProtocolError::PacketType(i32::from(packet_type)).into());
322 }
323 let size_or_error_code = i32::from_le_bytes([header[4], header[5], header[6], header[7]]);
324 if size_or_error_code != 512 {
325 return Err(MIONParamProtocolError::ErrorCode(size_or_error_code).into());
326 }
327 let parameters = packet.slice(8..);
328
329 Ok(Self { parameters })
330 }
331}
332
333impl From<&SetMionParameters> for Bytes {
334 fn from(value: &SetMionParameters) -> Self {
335 let mut buff = BytesMut::with_capacity(520);
336 buff.put_i32_le(i32::from(PacketType::Write));
337 buff.put_i32_le(512);
339 buff.extend_from_slice(&value.parameters);
340 buff.freeze()
341 }
342}
343impl From<SetMionParameters> for Bytes {
344 fn from(value: SetMionParameters) -> Self {
345 Self::from(&value)
346 }
347}
348
349#[derive(Clone, Debug, Hash, PartialEq, Eq)]
351pub struct SetMionParametersResponse {
352 return_code: i32,
354}
355
356impl SetMionParametersResponse {
357 #[must_use]
361 pub const fn get_return_code(&self) -> i32 {
362 self.return_code
363 }
364
365 #[must_use]
367 pub const fn is_success(&self) -> bool {
368 self.return_code == 0
369 }
370
371 #[must_use]
373 pub const fn is_error(&self) -> bool {
374 self.return_code != 0
375 }
376}
377
378impl TryFrom<Bytes> for SetMionParametersResponse {
379 type Error = NetworkParseError;
380
381 fn try_from(packet: Bytes) -> Result<Self, Self::Error> {
382 if packet.len() < 12 {
383 return Err(NetworkParseError::NotEnoughData(
384 "SetMionParametersResponse",
385 12,
386 packet.len(),
387 packet,
388 ));
389 }
390 if packet.len() > 12 {
391 return Err(NetworkParseError::UnexpectedTrailer(
392 "SetMionParametersResponse",
393 packet.slice(12..),
394 ));
395 }
396
397 let header = packet.slice(..8);
398 let packet_type = PacketType::try_from(i32::from_le_bytes([
399 header[0], header[1], header[2], header[3],
400 ]))?;
401 if packet_type != PacketType::Write {
402 return Err(MIONParamProtocolError::PacketType(i32::from(packet_type)).into());
403 }
404 let size_or_status = i32::from_le_bytes([header[4], header[5], header[6], header[7]]);
405 if size_or_status != 4 {
406 return Err(MIONParamProtocolError::ErrorCode(size_or_status).into());
407 }
408
409 let body = packet.slice(8..);
410 let return_code = i32::from_le_bytes([body[0], body[1], body[2], body[3]]);
411
412 Ok(Self { return_code })
413 }
414}
415
416impl From<&SetMionParametersResponse> for Bytes {
417 fn from(value: &SetMionParametersResponse) -> Self {
418 let mut buff = BytesMut::with_capacity(12);
419 buff.put_i32_le(i32::from(PacketType::Write));
420 buff.put_i32_le(4);
422 buff.put_i32_le(value.return_code);
423 buff.freeze()
424 }
425}
426impl From<SetMionParametersResponse> for Bytes {
427 fn from(value: SetMionParametersResponse) -> Self {
428 Self::from(&value)
429 }
430}
431
432#[cfg(test)]
433mod unit_tests {
434 use super::*;
435 use bytes::Bytes;
436 use std::sync::LazyLock;
437
438 static REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET: LazyLock<Vec<u8>> = LazyLock::new(|| {
439 vec![
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x0c, 0x0d,
441 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
442 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
443 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
444 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
446 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
447 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
448 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
449 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
452 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
454 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
457 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
458 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
459 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
460 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
461 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
462 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
463 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
464 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
465 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
466 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
467 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
468 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
469 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
470 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
471 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
472 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
473 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
474 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
475 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
476 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
477 0xff, 0xff,
478 ]
479 });
480 static REAL_LIFE_SET_MION_PARAMETERS_PACKET: LazyLock<Vec<u8>> = LazyLock::new(|| {
481 vec![
482 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x0c, 0x0d,
483 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
484 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
485 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
486 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
487 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
488 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
489 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
490 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
491 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
492 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
493 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
494 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
495 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
496 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
497 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
498 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
499 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
500 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
501 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
502 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
503 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
504 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
505 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
506 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
507 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
508 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
509 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
510 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
511 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
512 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
513 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
514 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
515 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
516 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
517 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
518 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
519 0xff, 0x45,
520 ]
521 });
522
523 #[test]
524 pub fn deser_mion_dump_parameters() {
525 {
527 assert!(
528 MionDumpParameters::try_from(Bytes::from(MionDumpParameters)).is_ok(),
529 "Deserializing a serialized MionDumpParameters was not a success!",
530 );
531 }
532
533 {
535 let short_data = vec![0x0; 4];
536 let too_much_data = vec![0x0; 16];
537
538 assert_eq!(
539 MionDumpParameters::try_from(Bytes::from(short_data.clone())),
540 Err(NetworkParseError::NotEnoughData(
541 "MionDumpParameters",
542 8,
543 short_data.len(),
544 Bytes::from(short_data),
545 )),
546 );
547
548 assert_eq!(
549 MionDumpParameters::try_from(Bytes::from(too_much_data.clone())),
550 Err(NetworkParseError::UnexpectedTrailer(
551 "MionDumpParameters",
552 Bytes::from(too_much_data).slice(8..),
553 )),
554 );
555 }
556
557 {
559 let invalid_static_packet = vec![0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0];
560 assert_eq!(
561 MionDumpParameters::try_from(Bytes::from(invalid_static_packet.clone())),
562 Err(NetworkParseError::DoesntMatchStaticPayload(
563 "MionDumpParameters",
564 &[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
565 Bytes::from(invalid_static_packet),
566 )),
567 );
568 }
569 }
570
571 #[test]
572 pub fn deser_dumped_mion_parameters() {
573 {
575 let short_data = vec![0x0; 519];
576 let too_long_data = vec![0x0; 521];
577
578 assert_eq!(
579 DumpedMionParameters::try_from(Bytes::from(short_data.clone())),
580 Err(NetworkParseError::NotEnoughData(
581 "DumpedMionParameters",
582 520,
583 short_data.len(),
584 Bytes::from(short_data),
585 )),
586 );
587
588 assert_eq!(
589 DumpedMionParameters::try_from(Bytes::from(too_long_data.clone())),
590 Err(NetworkParseError::UnexpectedTrailer(
591 "DumpedMionParameters",
592 Bytes::from(too_long_data).slice(520..),
593 )),
594 );
595 }
596
597 {
599 let mut data = vec![0x0; 520];
601 data[0] = 11;
602 let packet_with_bad_data = Bytes::from(data);
603
604 assert_eq!(
605 DumpedMionParameters::try_from(packet_with_bad_data),
606 Err(MIONParamProtocolError::PacketType(11).into()),
607 );
608
609 let mut data = vec![0x0; 520];
611 data[0] = 1;
612 let packet_with_bad_data = Bytes::from(data);
613
614 assert_eq!(
615 DumpedMionParameters::try_from(packet_with_bad_data),
616 Err(MIONParamProtocolError::PacketType(1).into()),
617 );
618 }
619
620 {
622 let result = DumpedMionParameters::try_from(Bytes::from(
623 REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET.clone(),
624 ));
625 assert!(
626 result.is_ok(),
627 "Failed to parse a real life DumpedMionParameters packet:\n\n {result:?}",
628 );
629 let result_two = DumpedMionParameters::try_from(Bytes::from(result.unwrap()));
630 assert!(
631 result_two.is_ok(),
632 "Failed to round-trip real life DumpedMionParameters:\n\n {result_two:?}",
633 );
634 }
635 }
636
637 #[test]
638 pub fn dumped_mion_parameters_api() {
639 let parsed_packet = DumpedMionParameters::try_from(Bytes::from(
640 REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET.clone(),
641 ))
642 .expect("Failed to parse real life dumped mion parmaeters packet!");
643
644 assert_eq!(
645 parsed_packet.get_raw_parameters(),
646 &REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET[8..],
647 ".get_raw_parameters() for DumpedMionParameters did not return the correct body!",
648 );
649
650 assert_eq!(
651 parsed_packet.get_parameter_by_name("major-version"),
652 Ok(0x02),
653 );
654 assert_eq!(
655 parsed_packet.get_parameter_by_name("minor version"),
656 Ok(0x0C),
657 );
658 assert_eq!(
659 parsed_packet.get_parameter_by_name("5"),
661 Ok(0x0D),
662 );
663 assert_eq!(
664 parsed_packet.get_parameter_by_name("512"),
665 Err(MIONParameterAPIError::NameNotKnown("512".to_owned())),
666 );
667
668 assert_eq!(parsed_packet.get_parameter_by_index(511), Ok(0xFF));
669 assert_eq!(
670 parsed_packet.get_parameter_by_index(512),
672 Err(MIONParameterAPIError::NotInRange(512)),
673 );
674 }
675
676 #[test]
677 pub fn deser_set_mion_parameters() {
678 {
680 let short_data = vec![0x0; 519];
681 let too_long_data = vec![0x0; 521];
682
683 assert_eq!(
684 SetMionParameters::try_from(Bytes::from(short_data.clone())),
685 Err(NetworkParseError::NotEnoughData(
686 "SetMionParameters",
687 520,
688 short_data.len(),
689 Bytes::from(short_data),
690 )),
691 );
692
693 assert_eq!(
694 SetMionParameters::try_from(Bytes::from(too_long_data.clone())),
695 Err(NetworkParseError::UnexpectedTrailer(
696 "SetMionParameters",
697 Bytes::from(too_long_data).slice(520..),
698 )),
699 );
700 }
701
702 {
704 let mut data = vec![0x0; 520];
706 data[0] = 11;
707 let packet_with_bad_data = Bytes::from(data);
708
709 assert_eq!(
710 SetMionParameters::try_from(packet_with_bad_data),
711 Err(MIONParamProtocolError::PacketType(11).into()),
712 );
713
714 let mut data = vec![0x0; 520];
716 data[0] = 0;
717 let packet_with_bad_data = Bytes::from(data);
718
719 assert_eq!(
720 SetMionParameters::try_from(packet_with_bad_data),
721 Err(MIONParamProtocolError::PacketType(0).into()),
722 );
723 }
724
725 {
727 let result = SetMionParameters::try_from(Bytes::from(
728 REAL_LIFE_SET_MION_PARAMETERS_PACKET.clone(),
729 ));
730 assert!(
731 result.is_ok(),
732 "Failed to parse a real life SetMionParameters packet:\n\n {result:?}",
733 );
734 let result_two = SetMionParameters::try_from(Bytes::from(result.unwrap()));
735 assert!(
736 result_two.is_ok(),
737 "Failed to round-trip real life SetMionParameters:\n\n {result_two:?}",
738 );
739 }
740 }
741
742 #[test]
743 pub fn set_mion_parameters_api() {
744 {
746 assert!(
749 SetMionParameters::new(Bytes::from(&REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET[8..]))
750 .is_ok(),
751 "Failed to construct `SetMionParameters` from a valid dumped parameters set!",
752 );
753
754 assert_eq!(
756 SetMionParameters::new(Bytes::from(&REAL_LIFE_DUMPED_MION_PARAMETERS_PACKET[7..])),
757 Err(MIONParameterAPIError::BodyNotCorrectLength(513)),
758 );
759 }
760
761 {
763 let parsed_packet = SetMionParameters::try_from(Bytes::from(
764 REAL_LIFE_SET_MION_PARAMETERS_PACKET.clone(),
765 ))
766 .expect("Failed to parse real life set mion parameters packet!");
767
768 assert_eq!(
769 parsed_packet.get_raw_parameters(),
770 &REAL_LIFE_SET_MION_PARAMETERS_PACKET[8..],
771 ".get_raw_parameters() for SetMionParameters did not return the correct body!",
772 );
773
774 assert_eq!(
775 parsed_packet.get_parameter_by_name("major-version"),
776 Ok(0x02),
777 );
778 assert_eq!(
779 parsed_packet.get_parameter_by_name("minor version"),
780 Ok(0x0C),
781 );
782 assert_eq!(
783 parsed_packet.get_parameter_by_name("5"),
785 Ok(0x0D),
786 );
787 assert_eq!(
788 parsed_packet.get_parameter_by_name("512"),
789 Err(MIONParameterAPIError::NameNotKnown("512".to_owned())),
790 );
791
792 assert_eq!(parsed_packet.get_parameter_by_index(511), Ok(69));
793 assert_eq!(
794 parsed_packet.get_parameter_by_index(512),
796 Err(MIONParameterAPIError::NotInRange(512)),
797 );
798 }
799 }
800
801 #[test]
802 pub fn deser_set_mion_parameters_response() {
803 {
805 let short_data = vec![0x0; 11];
806 let too_long_data = vec![0x0; 13];
807
808 assert_eq!(
809 SetMionParametersResponse::try_from(Bytes::from(short_data.clone())),
810 Err(NetworkParseError::NotEnoughData(
811 "SetMionParametersResponse",
812 12,
813 short_data.len(),
814 Bytes::from(short_data),
815 )),
816 );
817
818 assert_eq!(
819 SetMionParametersResponse::try_from(Bytes::from(too_long_data.clone())),
820 Err(NetworkParseError::UnexpectedTrailer(
821 "SetMionParametersResponse",
822 Bytes::from(too_long_data).slice(12..),
823 )),
824 );
825 }
826
827 {
829 assert_eq!(
831 SetMionParametersResponse::try_from(Bytes::from(vec![
832 0x11, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
836 ])),
837 Err(MIONParamProtocolError::PacketType(0x11).into()),
838 );
839
840 assert_eq!(
842 SetMionParametersResponse::try_from(Bytes::from(vec![
843 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
847 ])),
848 Err(MIONParamProtocolError::PacketType(0).into()),
849 );
850 }
851
852 {
854 assert_eq!(
855 SetMionParametersResponse::try_from(Bytes::from(vec![
856 0x1, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
860 ])),
861 Err(MIONParamProtocolError::ErrorCode(5).into()),
862 );
863 }
864
865 {
867 let result = SetMionParametersResponse::try_from(Bytes::from(vec![
868 0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
872 ]));
873 assert!(
874 result.is_ok(),
875 "Failed to respond to real life SetMionParametersResponse success!"
876 );
877 assert!(
878 SetMionParametersResponse::try_from(Bytes::from(result.unwrap())).is_ok(),
879 "Failed to round-trip real-life SetMionParametersResponse success!",
880 );
881 }
882 }
883}