1use crate::{HsesPayload, commands::Command, error::ProtocolError};
4use std::marker::PhantomData;
5
6pub trait VariableCommandId {
8 fn command_id() -> u16;
9}
10
11impl VariableCommandId for u8 {
12 fn command_id() -> u16 {
13 0x7a
14 }
15}
16
17impl VariableCommandId for i16 {
18 fn command_id() -> u16 {
19 0x7b
20 }
21}
22
23impl VariableCommandId for i32 {
24 fn command_id() -> u16 {
25 0x7c
26 }
27}
28
29impl VariableCommandId for f32 {
30 fn command_id() -> u16 {
31 0x7d
32 }
33}
34
35impl VariableCommandId for String {
36 fn command_id() -> u16 {
37 0x7e
38 }
39}
40
41pub trait MultipleVariableCommandId {
43 fn multiple_command_id() -> u16;
45
46 fn element_size() -> usize;
48
49 fn max_count() -> u32;
51
52 fn validate_count(count: u32) -> Result<(), ProtocolError>;
57}
58
59impl MultipleVariableCommandId for u8 {
60 fn multiple_command_id() -> u16 {
61 0x302
62 }
63 fn element_size() -> usize {
64 1
65 }
66 fn max_count() -> u32 {
67 474
68 }
69 fn validate_count(count: u32) -> Result<(), ProtocolError> {
70 if count == 0 || count > Self::max_count() {
71 return Err(ProtocolError::InvalidMessage(format!(
72 "Invalid count: {count} (must be 1-{})",
73 Self::max_count()
74 )));
75 }
76 if !count.is_multiple_of(2) {
77 return Err(ProtocolError::InvalidMessage(format!(
78 "Count must be multiple of 2: {count}"
79 )));
80 }
81 Ok(())
82 }
83}
84
85impl MultipleVariableCommandId for i16 {
86 fn multiple_command_id() -> u16 {
87 0x303
88 }
89 fn element_size() -> usize {
90 2
91 }
92 fn max_count() -> u32 {
93 237
94 }
95 fn validate_count(count: u32) -> Result<(), ProtocolError> {
96 if count == 0 || count > Self::max_count() {
97 return Err(ProtocolError::InvalidMessage(format!(
98 "Invalid count: {count} (must be 1-{})",
99 Self::max_count()
100 )));
101 }
102 Ok(())
103 }
104}
105
106impl MultipleVariableCommandId for i32 {
107 fn multiple_command_id() -> u16 {
108 0x304
109 }
110 fn element_size() -> usize {
111 4
112 }
113 fn max_count() -> u32 {
114 118
115 }
116 fn validate_count(count: u32) -> Result<(), ProtocolError> {
117 if count == 0 || count > Self::max_count() {
118 return Err(ProtocolError::InvalidMessage(format!(
119 "Invalid count: {count} (must be 1-{})",
120 Self::max_count()
121 )));
122 }
123 Ok(())
124 }
125}
126
127impl MultipleVariableCommandId for f32 {
128 fn multiple_command_id() -> u16 {
129 0x305
130 }
131 fn element_size() -> usize {
132 4
133 }
134 fn max_count() -> u32 {
135 118
136 }
137 fn validate_count(count: u32) -> Result<(), ProtocolError> {
138 if count == 0 || count > Self::max_count() {
139 return Err(ProtocolError::InvalidMessage(format!(
140 "Invalid count: {count} (must be 1-{})",
141 Self::max_count()
142 )));
143 }
144 Ok(())
145 }
146}
147
148impl MultipleVariableCommandId for String {
150 fn multiple_command_id() -> u16 {
151 0x306
152 }
153 fn element_size() -> usize {
154 16
155 }
156 fn max_count() -> u32 {
157 29
158 }
159 fn validate_count(count: u32) -> Result<(), ProtocolError> {
160 if count == 0 || count > Self::max_count() {
161 return Err(ProtocolError::InvalidMessage(format!(
162 "Invalid count: {count} (must be 1-{})",
163 Self::max_count()
164 )));
165 }
166 Ok(())
167 }
168}
169
170pub trait MultipleVariableResponse: Sized + MultipleVariableCommandId {
172 fn parse_element(
177 data: &[u8],
178 offset: usize,
179 encoding: crate::encoding::TextEncoding,
180 ) -> Result<Self, ProtocolError>;
181
182 fn deserialize_multiple(
187 data: &[u8],
188 expected_count: u32,
189 encoding: crate::encoding::TextEncoding,
190 ) -> Result<Vec<Self>, ProtocolError> {
191 if data.len() < 4 {
193 return Err(ProtocolError::Deserialization(format!(
194 "Response too short: {} bytes (need at least 4)",
195 data.len()
196 )));
197 }
198
199 let response_count = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
200 if response_count != expected_count {
201 return Err(ProtocolError::Deserialization(format!(
202 "Count mismatch: expected {expected_count}, got {response_count}"
203 )));
204 }
205
206 let element_size = Self::element_size();
207 let expected_len = 4 + (expected_count as usize * element_size);
208 if data.len() != expected_len {
209 return Err(ProtocolError::Deserialization(format!(
210 "Invalid response length: got {} bytes, expected {expected_len}",
211 data.len()
212 )));
213 }
214
215 let mut values = Vec::with_capacity(expected_count as usize);
217 for i in 0..expected_count as usize {
218 let offset = 4 + i * element_size;
219 values.push(Self::parse_element(data, offset, encoding)?);
220 }
221 Ok(values)
222 }
223}
224
225impl MultipleVariableResponse for u8 {
226 fn parse_element(
227 data: &[u8],
228 offset: usize,
229 encoding: crate::encoding::TextEncoding,
230 ) -> Result<Self, ProtocolError> {
231 let byte_slice = &data[offset..=offset];
232 Self::deserialize(byte_slice, encoding)
233 }
234}
235
236impl MultipleVariableResponse for i16 {
237 fn parse_element(
238 data: &[u8],
239 offset: usize,
240 encoding: crate::encoding::TextEncoding,
241 ) -> Result<Self, ProtocolError> {
242 let byte_slice = &data[offset..offset + 2];
243 Self::deserialize(byte_slice, encoding)
244 }
245}
246
247impl MultipleVariableResponse for i32 {
248 fn parse_element(
249 data: &[u8],
250 offset: usize,
251 encoding: crate::encoding::TextEncoding,
252 ) -> Result<Self, ProtocolError> {
253 let byte_slice = &data[offset..offset + 4];
254 Self::deserialize(byte_slice, encoding)
255 }
256}
257
258impl MultipleVariableResponse for f32 {
259 fn parse_element(
260 data: &[u8],
261 offset: usize,
262 encoding: crate::encoding::TextEncoding,
263 ) -> Result<Self, ProtocolError> {
264 let byte_slice = &data[offset..offset + 4];
265 Self::deserialize(byte_slice, encoding)
266 }
267}
268
269impl MultipleVariableResponse for String {
270 fn parse_element(
271 data: &[u8],
272 offset: usize,
273 encoding: crate::encoding::TextEncoding,
274 ) -> Result<Self, ProtocolError> {
275 let byte_array = &data[offset..offset + 16];
276 Self::deserialize(byte_array, encoding)
277 }
278}
279
280#[allow(clippy::derive_partial_eq_without_eq)]
283#[derive(Debug, Clone, PartialEq)]
284pub struct ReadMultipleVariables<T: MultipleVariableCommandId + PartialEq> {
285 pub start_variable_number: u16,
286 pub count: u32,
287 pub _phantom: PhantomData<T>,
288}
289
290impl<T: MultipleVariableCommandId + PartialEq> ReadMultipleVariables<T> {
291 pub fn new(start_variable_number: u16, count: u32) -> Result<Self, ProtocolError> {
296 T::validate_count(count)?;
297 Ok(Self { start_variable_number, count, _phantom: PhantomData })
298 }
299}
300
301impl<T: MultipleVariableCommandId + PartialEq> Command for ReadMultipleVariables<T> {
302 type Response = Vec<T>;
303 fn command_id() -> u16 {
304 T::multiple_command_id()
305 }
306 fn instance(&self) -> u16 {
307 self.start_variable_number
308 }
309 fn attribute(&self) -> u8 {
310 0 }
312 fn service(&self) -> u8 {
313 0x33 }
315 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
316 Ok(self.count.to_le_bytes().to_vec())
317 }
318}
319
320#[allow(clippy::derive_partial_eq_without_eq)]
323#[derive(Debug, Clone, PartialEq)]
324pub struct WriteMultipleVariables<T: MultipleVariableCommandId + PartialEq> {
325 pub start_variable_number: u16,
326 pub values: Vec<T>,
327}
328
329#[derive(Debug, Clone, PartialEq, Eq)]
331pub struct WriteMultipleStringVariables {
332 pub start_variable_number: u16,
333 pub values: Vec<String>,
334 pub text_encoding: crate::encoding::TextEncoding,
335}
336
337impl<T: MultipleVariableCommandId + PartialEq + Clone + HsesPayload> WriteMultipleVariables<T> {
338 pub fn new(start_variable_number: u16, values: Vec<T>) -> Result<Self, ProtocolError> {
343 let count = u32::try_from(values.len()).map_err(|_| {
344 ProtocolError::InvalidMessage(format!("Values count {} exceeds u32::MAX", values.len()))
345 })?;
346 T::validate_count(count)?;
347 Ok(Self { start_variable_number, values })
348 }
349}
350
351impl Command for WriteMultipleVariables<u8> {
353 type Response = ();
354 fn command_id() -> u16 {
355 0x302
356 }
357 fn instance(&self) -> u16 {
358 self.start_variable_number
359 }
360 fn attribute(&self) -> u8 {
361 0
362 }
363 fn service(&self) -> u8 {
364 0x34
365 }
366 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
367 let count = u32::try_from(self.values.len()).map_err(|_| {
368 ProtocolError::InvalidMessage(format!(
369 "Values count {} exceeds u32::MAX",
370 self.values.len()
371 ))
372 })?;
373
374 if count == 0 || count > u8::max_count() {
376 return Err(ProtocolError::InvalidMessage(format!(
377 "Invalid count: {count} (must be 1-{})",
378 u8::max_count()
379 )));
380 }
381
382 let mut payload = count.to_le_bytes().to_vec();
383 let serialized_values = self.values.serialize(crate::encoding::TextEncoding::Utf8)?;
384 payload.extend_from_slice(&serialized_values);
385 Ok(payload)
386 }
387}
388
389impl Command for WriteMultipleVariables<i16> {
390 type Response = ();
391 fn command_id() -> u16 {
392 0x303
393 }
394 fn instance(&self) -> u16 {
395 self.start_variable_number
396 }
397 fn attribute(&self) -> u8 {
398 0
399 }
400 fn service(&self) -> u8 {
401 0x34
402 }
403 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
404 let count = u32::try_from(self.values.len()).map_err(|_| {
405 ProtocolError::InvalidMessage(format!(
406 "Values count {} exceeds u32::MAX",
407 self.values.len()
408 ))
409 })?;
410
411 if count == 0 || count > i16::max_count() {
413 return Err(ProtocolError::InvalidMessage(format!(
414 "Invalid count: {count} (must be 1-{})",
415 i16::max_count()
416 )));
417 }
418
419 let mut payload = count.to_le_bytes().to_vec();
420 let serialized_values = self.values.serialize(crate::encoding::TextEncoding::Utf8)?;
421 payload.extend_from_slice(&serialized_values);
422 Ok(payload)
423 }
424}
425
426impl Command for WriteMultipleVariables<i32> {
427 type Response = ();
428 fn command_id() -> u16 {
429 0x304
430 }
431 fn instance(&self) -> u16 {
432 self.start_variable_number
433 }
434 fn attribute(&self) -> u8 {
435 0
436 }
437 fn service(&self) -> u8 {
438 0x34
439 }
440 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
441 let count = u32::try_from(self.values.len()).map_err(|_| {
442 ProtocolError::InvalidMessage(format!(
443 "Values count {} exceeds u32::MAX",
444 self.values.len()
445 ))
446 })?;
447
448 if count == 0 || count > i32::max_count() {
450 return Err(ProtocolError::InvalidMessage(format!(
451 "Invalid count: {count} (must be 1-{})",
452 i32::max_count()
453 )));
454 }
455
456 let mut payload = count.to_le_bytes().to_vec();
457 let serialized_values = self.values.serialize(crate::encoding::TextEncoding::Utf8)?;
458 payload.extend_from_slice(&serialized_values);
459 Ok(payload)
460 }
461}
462
463impl Command for WriteMultipleVariables<f32> {
464 type Response = ();
465 fn command_id() -> u16 {
466 0x305
467 }
468 fn instance(&self) -> u16 {
469 self.start_variable_number
470 }
471 fn attribute(&self) -> u8 {
472 0
473 }
474 fn service(&self) -> u8 {
475 0x34
476 }
477 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
478 let count = u32::try_from(self.values.len()).map_err(|_| {
479 ProtocolError::InvalidMessage(format!(
480 "Values count {} exceeds u32::MAX",
481 self.values.len()
482 ))
483 })?;
484
485 if count == 0 || count > f32::max_count() {
487 return Err(ProtocolError::InvalidMessage(format!(
488 "Invalid count: {count} (must be 1-{})",
489 f32::max_count()
490 )));
491 }
492
493 let mut payload = count.to_le_bytes().to_vec();
494 let serialized_values = self.values.serialize(crate::encoding::TextEncoding::Utf8)?;
495 payload.extend_from_slice(&serialized_values);
496 Ok(payload)
497 }
498}
499
500impl Command for WriteMultipleStringVariables {
501 type Response = ();
502 fn command_id() -> u16 {
503 0x306
504 }
505 fn instance(&self) -> u16 {
506 self.start_variable_number
507 }
508 fn attribute(&self) -> u8 {
509 0
510 }
511 fn service(&self) -> u8 {
512 0x34
513 }
514 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
515 let count = u32::try_from(self.values.len()).map_err(|_| {
516 ProtocolError::InvalidMessage(format!(
517 "Values count {} exceeds u32::MAX",
518 self.values.len()
519 ))
520 })?;
521
522 if count == 0 || count > String::max_count() {
524 return Err(ProtocolError::InvalidMessage(format!(
525 "Invalid count: {count} (must be 1-{})",
526 String::max_count()
527 )));
528 }
529
530 let mut payload = count.to_le_bytes().to_vec();
531 let serialized_values = self.values.serialize(self.text_encoding)?;
532 payload.extend_from_slice(&serialized_values);
533 Ok(payload)
534 }
535}
536
537#[allow(clippy::derive_partial_eq_without_eq)]
539#[derive(Debug, Clone, PartialEq)]
540pub struct ReadVariable<T: HsesPayload + VariableCommandId + PartialEq> {
541 pub index: u16, pub _phantom: PhantomData<T>,
543}
544
545impl<T: HsesPayload + VariableCommandId + PartialEq> Command for ReadVariable<T> {
546 type Response = T;
547 fn command_id() -> u16 {
548 T::command_id()
549 }
550 fn instance(&self) -> u16 {
551 self.index
552 }
553 fn attribute(&self) -> u8 {
554 0
555 }
556 fn service(&self) -> u8 {
557 0x0E }
559 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
560 Ok(vec![])
561 }
562}
563
564#[allow(clippy::derive_partial_eq_without_eq)]
566#[derive(Debug, Clone, PartialEq)]
567pub struct WriteVariable<T: HsesPayload + VariableCommandId + PartialEq> {
568 pub index: u16, pub value: T,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq)]
574pub struct WriteStringVar {
575 pub index: u16, pub value: String,
577 pub text_encoding: crate::encoding::TextEncoding,
578}
579
580impl<T: HsesPayload + VariableCommandId + PartialEq> Command for WriteVariable<T> {
581 type Response = ();
582 fn command_id() -> u16 {
583 T::command_id()
584 }
585 fn instance(&self) -> u16 {
586 self.index
587 }
588 fn attribute(&self) -> u8 {
589 0
590 }
591 fn service(&self) -> u8 {
592 0x10 }
594 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
595 self.value.serialize(crate::encoding::TextEncoding::Utf8)
596 }
597}
598
599impl Command for WriteStringVar {
600 type Response = ();
601 fn command_id() -> u16 {
602 String::command_id()
603 }
604 fn instance(&self) -> u16 {
605 self.index
606 }
607 fn attribute(&self) -> u8 {
608 0
609 }
610 fn service(&self) -> u8 {
611 0x10 }
613 fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
614 self.value.serialize(self.text_encoding)
615 }
616}
617
618#[cfg(test)]
619mod tests {
620 use super::*;
621
622 #[allow(clippy::expect_used)]
624 #[test]
625 fn test_read_variable_construction() {
626 let cmd = ReadVariable::<u8> { index: 10, _phantom: PhantomData };
627 assert_eq!(cmd.index, 10);
628 }
629
630 #[test]
631 fn test_write_variable_construction() {
632 let cmd = WriteVariable::<u8> { index: 10, value: 42 };
633 assert_eq!(cmd.index, 10);
634 assert_eq!(cmd.value, 42);
635 }
636
637 #[test]
638 fn test_variable_command_ids() {
639 assert_eq!(u8::command_id(), 0x7a);
640 assert_eq!(i16::command_id(), 0x7b);
641 assert_eq!(i32::command_id(), 0x7c);
642 assert_eq!(f32::command_id(), 0x7d);
643 assert_eq!(String::command_id(), 0x7e);
644 }
645
646 #[test]
647 fn test_read_variable_command_trait() {
648 let cmd = ReadVariable::<u8> { index: 5, _phantom: PhantomData };
649 assert_eq!(ReadVariable::<u8>::command_id(), 0x7a);
650 assert_eq!(cmd.instance(), 5);
651 assert_eq!(cmd.attribute(), 0);
652 assert_eq!(cmd.service(), 0x0E);
653 }
654
655 #[test]
656 fn test_write_variable_command_trait() {
657 let cmd = WriteVariable::<u8> { index: 5, value: 100 };
658 assert_eq!(WriteVariable::<u8>::command_id(), 0x7a);
659 assert_eq!(cmd.instance(), 5);
660 assert_eq!(cmd.attribute(), 0);
661 assert_eq!(cmd.service(), 0x10);
662 }
663
664 #[test]
665 #[allow(clippy::expect_used)]
666 fn test_write_variable_serialization() {
667 let cmd = WriteVariable::<u8> { index: 5, value: 100 };
668 let serialized = cmd.serialize().expect("Serialization should not fail");
669 assert_eq!(serialized, vec![100]);
670 }
671
672 #[test]
673 fn test_multiple_variable_command_ids() {
674 assert_eq!(u8::multiple_command_id(), 0x302);
675 assert_eq!(i16::multiple_command_id(), 0x303);
676 assert_eq!(i32::multiple_command_id(), 0x304);
677 assert_eq!(f32::multiple_command_id(), 0x305);
678 assert_eq!(String::multiple_command_id(), 0x306);
679 }
680
681 #[test]
682 fn test_multiple_variable_element_sizes() {
683 assert_eq!(u8::element_size(), 1);
684 assert_eq!(i16::element_size(), 2);
685 assert_eq!(i32::element_size(), 4);
686 assert_eq!(f32::element_size(), 4);
687 assert_eq!(String::element_size(), 16);
688 }
689
690 #[test]
691 fn test_multiple_variable_max_counts() {
692 assert_eq!(u8::max_count(), 474);
693 assert_eq!(i16::max_count(), 237);
694 assert_eq!(i32::max_count(), 118);
695 assert_eq!(f32::max_count(), 118);
696 assert_eq!(String::max_count(), 29);
697 }
698
699 #[test]
700 fn test_multiple_variable_count_validation() {
701 assert!(u8::validate_count(2).is_ok());
703 assert!(i16::validate_count(1).is_ok());
704 assert!(i32::validate_count(1).is_ok());
705 assert!(f32::validate_count(1).is_ok());
706 assert!(String::validate_count(1).is_ok());
707
708 assert!(u8::validate_count(0).is_err());
710 assert!(i16::validate_count(0).is_err());
711 assert!(i32::validate_count(0).is_err());
712 assert!(f32::validate_count(0).is_err());
713 assert!(String::validate_count(0).is_err());
714
715 assert!(u8::validate_count(475).is_err());
717 assert!(i16::validate_count(238).is_err());
718 assert!(i32::validate_count(119).is_err());
719 assert!(f32::validate_count(119).is_err());
720 assert!(String::validate_count(30).is_err());
721
722 assert!(u8::validate_count(3).is_err());
724 }
725
726 #[test]
727 #[allow(clippy::expect_used)]
728 fn test_read_multiple_variables_construction() {
729 let cmd = ReadMultipleVariables::<u8>::new(0, 2).expect("Valid command should not fail");
730 assert_eq!(cmd.start_variable_number, 0);
731 assert_eq!(cmd.count, 2);
732 }
733
734 #[test]
735 fn test_read_multiple_variables_validation() {
736 assert!(ReadMultipleVariables::<u8>::new(0, 2).is_ok());
738
739 assert!(ReadMultipleVariables::<u8>::new(0, 3).is_err());
741 }
742
743 #[test]
744 #[allow(clippy::expect_used)]
745 fn test_read_multiple_variables_command_trait() {
746 let cmd = ReadMultipleVariables::<u8>::new(10, 2).expect("Valid command should not fail");
747 assert_eq!(ReadMultipleVariables::<u8>::command_id(), 0x302);
748 assert_eq!(cmd.instance(), 10);
749 assert_eq!(cmd.attribute(), 0);
750 assert_eq!(cmd.service(), 0x33);
751 }
752
753 #[test]
754 #[allow(clippy::expect_used)]
755 fn test_read_multiple_variables_serialization() {
756 let cmd = ReadMultipleVariables::<u8>::new(5, 2).expect("Valid command should not fail");
757 let serialized = cmd.serialize().expect("Serialization should not fail");
758 assert_eq!(serialized, vec![2, 0, 0, 0]); }
760
761 #[test]
762 #[allow(clippy::expect_used)]
763 fn test_write_multiple_variables_construction() {
764 let values = vec![1u8, 2u8];
765 let cmd = WriteMultipleVariables::<u8>::new(0, values.clone())
766 .expect("Valid command should not fail");
767 assert_eq!(cmd.start_variable_number, 0);
768 assert_eq!(cmd.values, values);
769 }
770
771 #[test]
772 fn test_write_multiple_variables_validation() {
773 let values = vec![1u8, 2u8];
775 assert!(WriteMultipleVariables::<u8>::new(0, values).is_ok());
776
777 let values = vec![1u8, 2u8, 3u8];
779 assert!(WriteMultipleVariables::<u8>::new(0, values).is_err());
780 }
781
782 #[test]
783 #[allow(clippy::expect_used)]
784 fn test_write_multiple_variables_command_trait() {
785 let values = vec![1u8, 2u8];
786 let cmd =
787 WriteMultipleVariables::<u8>::new(10, values).expect("Valid command should not fail");
788 assert_eq!(WriteMultipleVariables::<u8>::command_id(), 0x302);
789 assert_eq!(cmd.instance(), 10);
790 assert_eq!(cmd.attribute(), 0);
791 assert_eq!(cmd.service(), 0x34);
792 }
793
794 #[test]
795 #[allow(clippy::expect_used)]
796 fn test_write_multiple_variables_serialization() {
797 let values = vec![1u8, 2u8];
798 let cmd =
799 WriteMultipleVariables::<u8>::new(5, values).expect("Valid command should not fail");
800 let serialized = cmd.serialize().expect("Serialization should not fail");
801 assert_eq!(serialized, vec![2, 0, 0, 0, 1, 2]); }
803
804 #[test]
805 #[allow(clippy::expect_used, clippy::unwrap_used, clippy::float_cmp)]
806 fn test_multiple_variable_response_parse_element() {
807 let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
808
809 assert_eq!(u8::parse_element(&data, 0, crate::encoding::TextEncoding::Utf8).unwrap(), 1);
811 assert_eq!(u8::parse_element(&data, 1, crate::encoding::TextEncoding::Utf8).unwrap(), 2);
812
813 assert_eq!(
815 i16::parse_element(&data, 0, crate::encoding::TextEncoding::Utf8).unwrap(),
816 0x0201
817 ); assert_eq!(
819 i16::parse_element(&data, 2, crate::encoding::TextEncoding::Utf8).unwrap(),
820 0x0403
821 );
822
823 assert_eq!(
825 i32::parse_element(&data, 0, crate::encoding::TextEncoding::Utf8).unwrap(),
826 0x0403_0201
827 ); assert_eq!(
829 i32::parse_element(&data, 4, crate::encoding::TextEncoding::Utf8).unwrap(),
830 0x0807_0605
831 );
832
833 let f32_data = [0x00, 0x00, 0x80, 0x3f]; assert_eq!(
836 f32::parse_element(&f32_data, 0, crate::encoding::TextEncoding::Utf8).unwrap(),
837 1.0f32
838 );
839
840 let mut array_data = [0u8; 32];
842 array_data[0..5].copy_from_slice(b"Hello");
844 array_data[16..21].copy_from_slice(b"World");
846
847 let result =
848 String::parse_element(&array_data, 0, crate::encoding::TextEncoding::Utf8).unwrap();
849 assert_eq!(result, "Hello");
850
851 let result =
852 String::parse_element(&array_data, 16, crate::encoding::TextEncoding::Utf8).unwrap();
853 assert_eq!(result, "World");
854 }
855
856 #[test]
857 #[allow(clippy::unwrap_used)]
858 fn test_multiple_variable_response_deserialize_multiple() {
859 let mut data = vec![2, 0, 0, 0]; data.extend_from_slice(&[1, 2]); let result =
864 u8::deserialize_multiple(&data, 2, crate::encoding::TextEncoding::Utf8).unwrap();
865 assert_eq!(result, vec![1, 2]);
866
867 let mut data = vec![2, 0, 0, 0]; data.extend_from_slice(&[1, 0, 2, 0]); let result =
872 i16::deserialize_multiple(&data, 2, crate::encoding::TextEncoding::Utf8).unwrap();
873 assert_eq!(result, vec![1, 2]);
874
875 let short_data = vec![1, 0, 0, 0]; assert!(
878 u8::deserialize_multiple(&short_data, 1, crate::encoding::TextEncoding::Utf8).is_err()
879 );
880
881 let wrong_count_data = vec![2, 0, 0, 0, 1]; assert!(
883 u8::deserialize_multiple(&wrong_count_data, 2, crate::encoding::TextEncoding::Utf8)
884 .is_err()
885 );
886 }
887}