1use bit_register::{NumBytes, TryFromBits, TryIntoBits, bit_register};
2
3use crate::{
4 MctpPacketError,
5 buffer_encoding::{EncodingDecoder, EncodingEncoder, PassthroughEncoding},
6 error::MctpPacketResult,
7 medium::{
8 MctpMedium, MctpMediumFrame,
9 util::{One, Zero},
10 },
11};
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct SmbusEspiMedium;
16
17#[derive(Debug, Copy, Clone, PartialEq, Eq)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19pub struct SmbusEspiReplyContext {
20 pub destination_slave_address: u8,
21 pub source_slave_address: u8,
22}
23
24impl MctpMedium for SmbusEspiMedium {
25 type Frame = SmbusEspiMediumFrame;
26 type Error = &'static str;
27 type ReplyContext = SmbusEspiReplyContext;
28 type Encoding = PassthroughEncoding;
29
30 fn deserialize<'buf>(
31 &self,
32 packet: &'buf [u8],
33 ) -> MctpPacketResult<(Self::Frame, EncodingDecoder<'buf, Self::Encoding>), Self> {
34 if packet.len() < 4 {
36 return Err(MctpPacketError::MediumError(
37 "Packet too short to parse smbus header",
38 ));
39 }
40
41 let header_value =
42 u32::from_be_bytes(packet[0..4].try_into().map_err(|_| {
43 MctpPacketError::MediumError("Packet too short to parse smbus header")
44 })?);
45 let packet = &packet[4..];
47 let header = SmbusEspiMediumHeader::try_from(header_value)
48 .map_err(|_| MctpPacketError::MediumError("Invalid smbus header"))?;
49 if header.byte_count as usize + 1 > packet.len() {
50 return Err(MctpPacketError::MediumError(
51 "Packet too short to parse smbus body and PEC",
52 ));
53 }
54 let pec = packet[header.byte_count as usize];
55 let inner = &packet[..header.byte_count as usize];
57 Ok((
58 SmbusEspiMediumFrame { header, pec },
59 EncodingDecoder::new(inner),
60 ))
61 }
62
63 fn serialize<'buf, F>(
64 &self,
65 reply_context: Self::ReplyContext,
66 buffer: &'buf mut [u8],
67 message_writer: F,
68 ) -> MctpPacketResult<&'buf [u8], Self>
69 where
70 F: for<'a> FnOnce(&mut EncodingEncoder<'a, Self::Encoding>) -> MctpPacketResult<(), Self>,
71 {
72 if buffer.len() < 5 {
74 return Err(MctpPacketError::MediumError(
75 "Buffer too small for smbus frame",
76 ));
77 }
78 let buffer_len = buffer.len();
79
80 let body_wire_len = {
83 let body_buf = &mut buffer[4..buffer_len - 1];
84 let mut encoder = EncodingEncoder::<Self::Encoding>::new(body_buf);
85 message_writer(&mut encoder)?;
86 encoder.wire_position()
87 };
88
89 let header = SmbusEspiMediumHeader {
94 destination_slave_address: reply_context.source_slave_address,
95 source_slave_address: reply_context.destination_slave_address,
96 byte_count: body_wire_len as u8,
97 command_code: SmbusCommandCode::Mctp,
98 ..Default::default()
99 };
100 let header_value =
101 TryInto::<u32>::try_into(header).map_err(MctpPacketError::MediumError)?;
102 buffer[0..4].copy_from_slice(&header_value.to_be_bytes());
103
104 let pec_value = smbus_pec::pec(&buffer[0..4 + body_wire_len]);
106 buffer[4 + body_wire_len] = pec_value;
107
108 Ok(&buffer[0..4 + body_wire_len + 1])
110 }
111
112 fn max_message_body_size(&self) -> usize {
114 32
115 }
116}
117
118#[repr(u8)]
119#[derive(
120 Debug, Copy, Clone, PartialEq, Eq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Default,
121)]
122#[cfg_attr(feature = "defmt", derive(defmt::Format))]
123enum SmbusCommandCode {
124 #[default]
125 Mctp = 0x0F,
126}
127impl TryFromBits<u32> for SmbusCommandCode {
128 fn try_from_bits(bits: u32) -> Result<Self, &'static str> {
129 if bits > 0xFF {
130 Err("Command code out of range")
131 } else {
132 SmbusCommandCode::try_from(bits as u8).map_err(|_| "Invalid command code")
133 }
134 }
135}
136impl TryIntoBits<u32> for SmbusCommandCode {
137 fn try_into_bits(self) -> Result<u32, &'static str> {
138 Ok(Into::<u8>::into(self) as u32)
139 }
140}
141impl NumBytes for SmbusCommandCode {
142 const NUM_BYTES: usize = 1;
143}
144
145bit_register! {
149 #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
150 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
151 struct SmbusEspiMediumHeader: little_endian u32 {
152 pub destination_slave_address: u8 => [25:31],
153 pub _reserved1: Zero => [24],
154 pub command_code: SmbusCommandCode => [16:23],
155 pub byte_count: u8 => [8:15],
156 pub source_slave_address: u8 => [1:7],
157 pub _reserved2: One => [0],
158 }
159}
160
161#[derive(Copy, Clone, PartialEq, Eq, Debug)]
162#[cfg_attr(feature = "defmt", derive(defmt::Format))]
163pub struct SmbusEspiMediumFrame {
164 header: SmbusEspiMediumHeader,
165 pec: u8,
166}
167
168impl SmbusEspiReplyContext {
169 fn new(frame: SmbusEspiMediumFrame) -> Self {
170 Self {
171 destination_slave_address: frame.header.destination_slave_address,
172 source_slave_address: frame.header.source_slave_address,
173 }
174 }
175}
176
177impl MctpMediumFrame<SmbusEspiMedium> for SmbusEspiMediumFrame {
178 fn packet_size(&self) -> usize {
179 self.header.byte_count as usize
180 }
181
182 fn reply_context(&self) -> SmbusEspiReplyContext {
183 SmbusEspiReplyContext::new(*self)
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 extern crate std;
190 use std::vec::Vec;
191
192 use super::*;
193 use crate::buffer_encoding::DecodeError;
194
195 fn drain_to_vec(decoder: &mut EncodingDecoder<'_, PassthroughEncoding>) -> Vec<u8> {
198 let mut out = Vec::new();
199 while let Ok(b) = decoder.read() {
200 out.push(b);
201 }
202 out
203 }
204
205 #[test]
206 fn test_deserialize_valid_packet() {
207 let medium = SmbusEspiMedium;
208
209 let header = SmbusEspiMediumHeader {
212 destination_slave_address: 0x20,
213 source_slave_address: 0x10,
214 command_code: SmbusCommandCode::Mctp,
215 byte_count: 4,
216 ..Default::default()
217 };
218 let header_value: u32 = header.try_into().unwrap();
219 let header_bytes = header_value.to_be_bytes();
220
221 let payload = [0xAA, 0xBB, 0xCC, 0xDD]; let mut combined = [0u8; 8];
223 combined[0..4].copy_from_slice(&header_bytes);
224 combined[4..8].copy_from_slice(&payload);
225 let pec = smbus_pec::pec(&combined);
226
227 let mut packet = [0u8; 9];
228 packet[0..4].copy_from_slice(&header_bytes);
229 packet[4..8].copy_from_slice(&payload);
230 packet[8] = pec;
231
232 let result = medium.deserialize(&packet).unwrap();
233 let (frame, mut decoder) = result;
234 let body = drain_to_vec(&mut decoder);
235
236 assert_eq!(frame.header.destination_slave_address, 0x20);
237 assert_eq!(frame.header.source_slave_address, 0x10);
238 assert_eq!(frame.header.command_code, SmbusCommandCode::Mctp);
239 assert_eq!(frame.header.byte_count, 4);
240 assert_eq!(frame.pec, pec);
241 assert_eq!(body, payload);
242 }
243
244 #[test]
245 fn test_deserialize_packet_too_short_header() {
246 let medium = SmbusEspiMedium;
247 let short_packet = [0x01, 0x02]; let err = medium.deserialize(&short_packet).err().unwrap();
250 assert_eq!(
251 err,
252 MctpPacketError::MediumError("Packet too short to parse smbus header")
253 );
254 }
255
256 #[test]
257 fn test_deserialize_packet_too_short_body() {
258 let medium = SmbusEspiMedium;
259
260 let header_bytes = [
262 0x20, 0x0F, 0x0A, 0x21, ];
267
268 let short_payload = [0xAA, 0xBB]; let mut packet = [0u8; 6];
271 packet[0..4].copy_from_slice(&header_bytes);
272 packet[4..6].copy_from_slice(&short_payload);
273
274 let err = medium.deserialize(&packet).err().unwrap();
275 assert_eq!(
276 err,
277 MctpPacketError::MediumError("Packet too short to parse smbus body and PEC")
278 );
279 }
280
281 #[test]
282 fn test_deserialize_invalid_header() {
283 let medium = SmbusEspiMedium;
284
285 let invalid_header_bytes = [
287 0x20, 0xFF, 0x04, 0x20, ];
292
293 let payload = [0xAA, 0xBB, 0xCC, 0xDD];
294 let pec = 0x00; let mut packet = [0u8; 9];
297 packet[0..4].copy_from_slice(&invalid_header_bytes);
298 packet[4..8].copy_from_slice(&payload);
299 packet[8] = pec;
300
301 let err = medium.deserialize(&packet).err().unwrap();
302 assert_eq!(err, MctpPacketError::MediumError("Invalid smbus header"));
303 }
304
305 #[test]
306 fn test_deserialize_zero_byte_count() {
307 let medium = SmbusEspiMedium;
308
309 let header_bytes = [
310 0x20, 0x0F, 0x00, 0x21, ];
315
316 let pec = smbus_pec::pec(&header_bytes);
317
318 let mut packet = [0u8; 5];
319 packet[0..4].copy_from_slice(&header_bytes);
320 packet[4] = pec;
321
322 let result = medium.deserialize(&packet).unwrap();
323 let (frame, mut decoder) = result;
324
325 assert_eq!(frame.header.byte_count, 0);
326 assert_eq!(frame.pec, pec);
327 assert_eq!(decoder.read().unwrap_err(), DecodeError::PrematureEnd);
328 }
329
330 #[test]
331 fn test_serialize_valid_packet() {
332 let medium = SmbusEspiMedium;
333 let reply_context = SmbusEspiReplyContext {
334 destination_slave_address: 0x20,
335 source_slave_address: 0x10,
336 };
337
338 let mut buffer = [0u8; 64];
339 let test_payload = [0xAA, 0xBB, 0xCC, 0xDD];
340
341 let result = medium
342 .serialize(reply_context, &mut buffer, |encoder| {
343 encoder
344 .write_all(&test_payload)
345 .map_err(|_| MctpPacketError::SerializeError("encode error"))
346 })
347 .unwrap();
348
349 assert_eq!(result.len(), 9);
352
353 let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
355 let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
356
357 assert_eq!(header.destination_slave_address, 0x10); assert_eq!(header.source_slave_address, 0x20); assert_eq!(header.command_code, SmbusCommandCode::Mctp);
361 assert_eq!(header.byte_count, 4);
362
363 assert_eq!(&result[4..8], &test_payload);
365
366 let expected_pec = smbus_pec::pec(&result[0..8]);
368 assert_eq!(result[8], expected_pec);
369 }
370
371 #[test]
372 fn test_serialize_buffer_too_small() {
373 let medium = SmbusEspiMedium;
374 let reply_context = SmbusEspiReplyContext {
375 destination_slave_address: 0x20,
376 source_slave_address: 0x10,
377 };
378
379 let mut small_buffer = [0u8; 4]; let err = medium
382 .serialize(reply_context, &mut small_buffer, |_| Ok(()))
383 .err()
384 .unwrap();
385
386 assert_eq!(
387 err,
388 MctpPacketError::MediumError("Buffer too small for smbus frame")
389 );
390 }
391
392 #[test]
393 fn test_serialize_minimal_buffer() {
394 let medium = SmbusEspiMedium;
395 let reply_context = SmbusEspiReplyContext {
396 destination_slave_address: 0x20,
397 source_slave_address: 0x10,
398 };
399
400 let mut minimal_buffer = [0u8; 5]; let result = medium
403 .serialize(
404 reply_context,
405 &mut minimal_buffer,
406 |_| Ok(()), )
408 .unwrap();
409
410 assert_eq!(result.len(), 5);
411
412 let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
414 let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
415 assert_eq!(header.byte_count, 0);
416
417 let expected_pec = smbus_pec::pec(&result[0..4]);
419 assert_eq!(result[4], expected_pec);
420 }
421
422 #[test]
423 fn test_serialize_max_payload() {
424 let medium = SmbusEspiMedium;
425 let reply_context = SmbusEspiReplyContext {
426 destination_slave_address: 0x20,
427 source_slave_address: 0x10,
428 };
429
430 let max_payload = [0x55u8; 255];
432 let mut buffer = [0u8; 260]; let result = medium
435 .serialize(reply_context, &mut buffer, |encoder| {
436 encoder
437 .write_all(&max_payload)
438 .map_err(|_| MctpPacketError::SerializeError("encode error"))
439 })
440 .unwrap();
441
442 assert_eq!(result.len(), 260); let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
446 let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
447 assert_eq!(header.byte_count, 255);
448
449 assert_eq!(&result[4..259], &max_payload[..]);
451
452 let expected_pec = smbus_pec::pec(&result[0..259]);
454 assert_eq!(result[259], expected_pec);
455 }
456
457 #[test]
458 fn test_serialize_message_writer_error() {
459 let medium = SmbusEspiMedium;
460 let reply_context = SmbusEspiReplyContext {
461 destination_slave_address: 0x20,
462 source_slave_address: 0x10,
463 };
464
465 let mut buffer = [0u8; 64];
466
467 let result = medium.serialize(reply_context, &mut buffer, |_| {
468 Err(MctpPacketError::MediumError("Test error"))
469 });
470
471 assert_eq!(result, Err(MctpPacketError::MediumError("Test error")));
472 }
473
474 #[test]
475 fn test_roundtrip_serialization_deserialization() {
476 let medium = SmbusEspiMedium;
477 let original_context = SmbusEspiReplyContext {
478 destination_slave_address: 0x42,
479 source_slave_address: 0x24,
480 };
481
482 let original_payload = [0x11, 0x22, 0x33, 0x44, 0x55];
483 let mut buffer = [0u8; 64];
484
485 let serialized = medium
487 .serialize(original_context, &mut buffer, |encoder| {
488 encoder
489 .write_all(&original_payload)
490 .map_err(|_| MctpPacketError::SerializeError("encode error"))
491 })
492 .unwrap();
493
494 let (frame, mut decoder) = medium.deserialize(serialized).unwrap();
496 let deserialized_payload = drain_to_vec(&mut decoder);
497
498 assert_eq!(deserialized_payload, original_payload);
500 assert_eq!(frame.header.destination_slave_address, 0x24); assert_eq!(frame.header.source_slave_address, 0x42); assert_eq!(frame.header.command_code, SmbusCommandCode::Mctp);
503 assert_eq!(frame.header.byte_count, original_payload.len() as u8);
504
505 let expected_pec = smbus_pec::pec(&serialized[0..serialized.len() - 1]);
507 assert_eq!(frame.pec, expected_pec);
508 }
509
510 #[test]
511 fn test_frame_packet_size() {
512 let frame = SmbusEspiMediumFrame {
513 header: SmbusEspiMediumHeader {
514 byte_count: 42,
515 ..Default::default()
516 },
517 pec: 0,
518 };
519
520 assert_eq!(frame.packet_size(), 42);
521 }
522
523 #[test]
524 fn test_frame_reply_context() {
525 let frame = SmbusEspiMediumFrame {
526 header: SmbusEspiMediumHeader {
527 destination_slave_address: 0x30,
528 source_slave_address: 0x40,
529 ..Default::default()
530 },
531 pec: 0,
532 };
533
534 let context = frame.reply_context();
535 assert_eq!(context.destination_slave_address, 0x30);
536 assert_eq!(context.source_slave_address, 0x40);
537 }
538
539 #[test]
540 fn test_smbus_command_code_conversion() {
541 assert_eq!(
543 SmbusCommandCode::try_from_bits(0x0F).unwrap(),
544 SmbusCommandCode::Mctp
545 );
546
547 assert_eq!(
549 SmbusCommandCode::try_from_bits(0x100),
550 Err("Command code out of range")
551 );
552
553 assert_eq!(
555 SmbusCommandCode::try_from_bits(0x10),
556 Err("Invalid command code")
557 );
558
559 assert_eq!(SmbusCommandCode::Mctp.try_into_bits().unwrap(), 0x0F);
561 }
562
563 #[test]
564 fn test_header_bit_register_edge_cases() {
565 let header = SmbusEspiMediumHeader::default();
567 assert_eq!(header.destination_slave_address, 0);
568 assert_eq!(header.source_slave_address, 0);
569 assert_eq!(header.byte_count, 0);
570 assert_eq!(header.command_code, SmbusCommandCode::Mctp); let header = SmbusEspiMediumHeader {
574 destination_slave_address: 0x7F, source_slave_address: 0x3F, byte_count: 0xFF, command_code: SmbusCommandCode::Mctp,
578 ..Default::default()
579 };
580
581 let header_value: u32 = header.try_into().unwrap();
583 let reconstructed = SmbusEspiMediumHeader::try_from(header_value).unwrap();
584 assert_eq!(reconstructed, header);
585 }
586
587 #[test]
588 fn test_pec_calculation_accuracy() {
589 let medium = SmbusEspiMedium;
590 let reply_context = SmbusEspiReplyContext {
591 destination_slave_address: 0x50,
592 source_slave_address: 0x30,
593 };
594
595 let test_data = [0x01, 0x02, 0x03];
597 let mut buffer = [0u8; 32];
598
599 let result = medium
600 .serialize(reply_context, &mut buffer, |encoder| {
601 encoder
602 .write_all(&test_data)
603 .map_err(|_| MctpPacketError::SerializeError("encode error"))
604 })
605 .unwrap();
606
607 let data_for_pec = &result[0..result.len() - 1];
609 let expected_pec = smbus_pec::pec(data_for_pec);
610 let actual_pec = result[result.len() - 1];
611
612 assert_eq!(actual_pec, expected_pec);
613 }
614
615 #[test]
616 fn test_serialize_with_empty_payload() {
617 let medium = SmbusEspiMedium;
618 let reply_context = SmbusEspiReplyContext {
619 destination_slave_address: 0x60,
620 source_slave_address: 0x70,
621 };
622
623 let mut buffer = [0u8; 16];
624
625 let result = medium
626 .serialize(
627 reply_context,
628 &mut buffer,
629 |_| Ok(()), )
631 .unwrap();
632
633 assert_eq!(result.len(), 5); let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
637 let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
638 assert_eq!(header.byte_count, 0);
639 assert_eq!(header.destination_slave_address, 0x70); assert_eq!(header.source_slave_address, 0x60); let expected_pec = smbus_pec::pec(&result[0..4]);
644 assert_eq!(result[4], expected_pec);
645 }
646
647 #[test]
648 fn test_max_message_body_size() {
649 let medium = SmbusEspiMedium;
650 assert_eq!(medium.max_message_body_size(), 32);
651 }
652
653 #[test]
654 fn test_address_swapping_in_reply_context() {
655 let original_frame = SmbusEspiMediumFrame {
657 header: SmbusEspiMediumHeader {
658 destination_slave_address: 0x2A, source_slave_address: 0x3B, ..Default::default()
661 },
662 pec: 0,
663 };
664
665 let reply_context = SmbusEspiReplyContext::new(original_frame);
666 assert_eq!(reply_context.destination_slave_address, 0x2A);
667 assert_eq!(reply_context.source_slave_address, 0x3B);
668
669 let medium = SmbusEspiMedium;
671 let mut buffer = [0u8; 16];
672
673 let result = medium
674 .serialize(reply_context, &mut buffer, |_| Ok(()))
675 .unwrap();
676
677 let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
678 let response_header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
679
680 assert_eq!(response_header.destination_slave_address, 0x3B);
682 assert_eq!(response_header.source_slave_address, 0x2A);
683 }
684
685 #[test]
686 fn test_deserialize_with_different_byte_counts() {
687 let medium = SmbusEspiMedium;
688
689 for byte_count in [1, 16, 32, 64, 128, 255] {
690 let header_bytes = [
691 0x20, 0x0F, byte_count, 0x21, ];
696
697 let payload = [0x42u8; 255];
698 let payload_slice = &payload[..byte_count as usize];
699
700 let mut combined = [0u8; 259]; combined[0..4].copy_from_slice(&header_bytes);
702 combined[4..4 + byte_count as usize].copy_from_slice(payload_slice);
703 let pec = smbus_pec::pec(&combined[0..4 + byte_count as usize]);
704
705 let mut packet = [0u8; 260]; packet[0..4].copy_from_slice(&header_bytes);
707 packet[4..4 + byte_count as usize].copy_from_slice(payload_slice);
708 packet[4 + byte_count as usize] = pec;
709
710 let packet_slice = &packet[0..4 + byte_count as usize + 1];
711 let result = medium.deserialize(packet_slice).unwrap();
712 let (frame, mut decoder) = result;
713 let body = drain_to_vec(&mut decoder);
714
715 assert_eq!(frame.header.byte_count, byte_count);
716 assert_eq!(body.len(), byte_count as usize);
717 assert_eq!(frame.pec, pec);
718 }
719 }
720
721 #[test]
722 fn test_smbus_buffer_overflow_protection() {
723 let medium = SmbusEspiMedium;
724
725 let header_bytes = [
727 0x20, 0x0F, 0xFF, 0x21, ];
732
733 let short_payload = [0xAA, 0xBB]; let mut packet = [0u8; 7]; packet[0..4].copy_from_slice(&header_bytes);
737 packet[4..6].copy_from_slice(&short_payload);
738 packet[6] = 0x00; let err = medium.deserialize(&packet).err().unwrap();
741 assert_eq!(
742 err,
743 MctpPacketError::MediumError("Packet too short to parse smbus body and PEC")
744 );
745 }
746
747 #[test]
748 fn test_smbus_serialize_buffer_underflow() {
749 let medium = SmbusEspiMedium;
750 let reply_context = SmbusEspiReplyContext {
751 destination_slave_address: 0x20,
752 source_slave_address: 0x10,
753 };
754
755 let mut tiny_buffer = [0u8; 4]; let err = medium
759 .serialize(reply_context, &mut tiny_buffer, |_| {
760 Ok(()) })
762 .err()
763 .unwrap();
764
765 assert_eq!(
766 err,
767 MctpPacketError::MediumError("Buffer too small for smbus frame")
768 );
769 }
770
771 #[test]
772 fn test_smbus_header_bounds_checking() {
773 let medium = SmbusEspiMedium;
774
775 for packet_size in 0..4 {
777 let short_packet = [0u8; 4];
778 let err = medium
779 .deserialize(&short_packet[..packet_size])
780 .err()
781 .unwrap();
782 assert_eq!(
783 err,
784 MctpPacketError::MediumError("Packet too short to parse smbus header")
785 );
786 }
787 }
788
789 #[test]
790 fn test_smbus_pec_bounds_checking() {
791 let medium = SmbusEspiMedium;
792
793 let header_bytes = [
795 0x20, 0x0F, 0x05, 0x21, ];
800
801 let payload = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE]; let mut packet = [0u8; 9]; packet[0..4].copy_from_slice(&header_bytes);
805 packet[4..9].copy_from_slice(&payload);
806
807 let err = medium.deserialize(&packet).err().unwrap();
808 assert_eq!(
809 err,
810 MctpPacketError::MediumError("Packet too short to parse smbus body and PEC")
811 );
812 }
813
814 #[test]
815 fn test_smbus_zero_byte_count_edge_case() {
816 let medium = SmbusEspiMedium;
817
818 let header_bytes = [
820 0x20, 0x0F, 0x00, 0x21, ];
825
826 let mut short_packet = [0u8; 4]; short_packet.copy_from_slice(&header_bytes);
829
830 let err = medium.deserialize(&short_packet).err().unwrap();
831 assert_eq!(
832 err,
833 MctpPacketError::MediumError("Packet too short to parse smbus body and PEC")
834 );
835 }
836
837 #[test]
838 fn test_smbus_maximum_payload_boundary() {
839 let medium = SmbusEspiMedium;
840
841 let reply_context = SmbusEspiReplyContext {
843 destination_slave_address: 0x20,
844 source_slave_address: 0x10,
845 };
846
847 let max_payload = [0x55u8; 255];
848 let mut buffer = [0u8; 260]; let result = medium.serialize(reply_context, &mut buffer, |encoder| {
851 encoder
852 .write_all(&max_payload)
853 .map_err(|_| MctpPacketError::SerializeError("encode error"))
854 });
855
856 assert!(result.is_ok());
857 let serialized = result.unwrap();
858 assert_eq!(serialized.len(), 260); let mut small_buffer = [0u8; 259]; let result_small = medium.serialize(reply_context, &mut small_buffer, |encoder| {
867 encoder
868 .write_all(&max_payload)
869 .map_err(|_| MctpPacketError::SerializeError("encode error"))
870 });
871
872 assert_eq!(
873 result_small.err().unwrap(),
874 MctpPacketError::SerializeError("encode error")
875 );
876 }
877}