1use bit_register::{NumBytes, TryFromBits, TryIntoBits, bit_register};
2
3use crate::{
4    MctpPacketError,
5    error::MctpPacketResult,
6    medium::{MctpMedium, MctpMediumFrame, util::Zero},
7};
8
9#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub struct SmbusEspiMedium;
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct SmbusEspiReplyContext {
16    pub destination_slave_address: u8,
17    pub source_slave_address: u8,
18}
19
20impl MctpMedium for SmbusEspiMedium {
21    type Frame = SmbusEspiMediumFrame;
22    type Error = &'static str;
23    type ReplyContext = SmbusEspiReplyContext;
24
25    fn deserialize<'buf>(
26        &self,
27        packet: &'buf [u8],
28    ) -> MctpPacketResult<(Self::Frame, &'buf [u8]), Self> {
29        if packet.len() < 4 {
31            return Err(MctpPacketError::MediumError(
32                "Packet too short to parse smbus header",
33            ));
34        }
35
36        let header_value =
37            u32::from_be_bytes(packet[0..4].try_into().map_err(|_| {
38                MctpPacketError::MediumError("Packet too short to parse smbus header")
39            })?);
40        let packet = &packet[4..];
42        let header = SmbusEspiMediumHeader::try_from(header_value)
43            .map_err(|_| MctpPacketError::MediumError("Invalid smbus header"))?;
44        if header.byte_count as usize + 1 > packet.len() {
45            return Err(MctpPacketError::MediumError(
46                "Packet too short to parse smbus body and PEC",
47            ));
48        }
49        let pec = packet[header.byte_count as usize];
50        let packet = &packet[..header.byte_count as usize];
52        Ok((SmbusEspiMediumFrame { header, pec }, packet))
53    }
54
55    fn serialize<'buf, F>(
56        &self,
57        reply_context: Self::ReplyContext,
58        buffer: &'buf mut [u8],
59        message_writer: F,
60    ) -> MctpPacketResult<&'buf [u8], Self>
61    where
62        F: for<'a> FnOnce(&'a mut [u8]) -> MctpPacketResult<usize, Self>,
63    {
64        if buffer.len() < 5 {
66            return Err(MctpPacketError::MediumError(
67                "Buffer too small for smbus frame",
68            ));
69        }
70
71        let (header_slice, body) = buffer.split_at_mut(4);
73
74        if body.is_empty() {
76            return Err(MctpPacketError::MediumError("No space for PEC byte"));
77        }
78        let available_body_len = body.len() - 1; let body_len = message_writer(&mut body[..available_body_len])?;
80
81        let header = SmbusEspiMediumHeader {
83            destination_slave_address: reply_context.source_slave_address,
84            source_slave_address: reply_context.destination_slave_address,
85            byte_count: body_len as u8,
86            command_code: SmbusCommandCode::Mctp,
87            ..Default::default()
88        };
89        let header_value =
90            TryInto::<u32>::try_into(header).map_err(MctpPacketError::MediumError)?;
91        header_slice.copy_from_slice(&header_value.to_be_bytes());
92
93        let pec_value = smbus_pec::pec(&buffer[0..4 + body_len]);
95        buffer[4 + body_len] = pec_value;
96
97        Ok(&buffer[0..4 + body_len + 1])
99    }
100
101    fn max_message_body_size(&self) -> usize {
103        32
104    }
105}
106
107#[repr(u8)]
108#[derive(
109    Debug, Copy, Clone, PartialEq, Eq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Default,
110)]
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
112enum SmbusCommandCode {
113    #[default]
114    Mctp = 0x0F,
115}
116impl TryFromBits<u32> for SmbusCommandCode {
117    fn try_from_bits(bits: u32) -> Result<Self, &'static str> {
118        if bits > 0xFF {
119            Err("Command code out of range")
120        } else {
121            SmbusCommandCode::try_from(bits as u8).map_err(|_| "Invalid command code")
122        }
123    }
124}
125impl TryIntoBits<u32> for SmbusCommandCode {
126    fn try_into_bits(self) -> Result<u32, &'static str> {
127        Ok(Into::<u8>::into(self) as u32)
128    }
129}
130impl NumBytes for SmbusCommandCode {
131    const NUM_BYTES: usize = 1;
132}
133
134bit_register! {
135    #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
136    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
137    struct SmbusEspiMediumHeader: little_endian u32 {
138        pub destination_slave_address: u8 => [25:31],
139        pub _reserved1: Zero => [24],
140        pub command_code: SmbusCommandCode => [16:24],
141        pub byte_count: u8 => [8:15],
142        pub source_slave_address: u8 => [1:7],
143        pub _reserved2: Zero => [0],
144    }
145}
146
147#[derive(Copy, Clone, PartialEq, Eq, Debug)]
148#[cfg_attr(feature = "defmt", derive(defmt::Format))]
149pub struct SmbusEspiMediumFrame {
150    header: SmbusEspiMediumHeader,
151    pec: u8,
152}
153
154impl SmbusEspiReplyContext {
155    fn new(frame: SmbusEspiMediumFrame) -> Self {
156        Self {
157            destination_slave_address: frame.header.destination_slave_address,
158            source_slave_address: frame.header.source_slave_address,
159        }
160    }
161}
162
163impl MctpMediumFrame<SmbusEspiMedium> for SmbusEspiMediumFrame {
164    fn packet_size(&self) -> usize {
165        self.header.byte_count as usize
166    }
167
168    fn reply_context(&self) -> SmbusEspiReplyContext {
169        SmbusEspiReplyContext::new(*self)
170    }
171}
172
173#[cfg(test)]
174mod tests {
175    extern crate std;
176    use super::*;
177
178    #[test]
179    fn test_deserialize_valid_packet() {
180        let medium = SmbusEspiMedium;
181
182        let header = SmbusEspiMediumHeader {
185            destination_slave_address: 0x20,
186            source_slave_address: 0x10,
187            command_code: SmbusCommandCode::Mctp,
188            byte_count: 4,
189            ..Default::default()
190        };
191        let header_value: u32 = header.try_into().unwrap();
192        let header_bytes = header_value.to_be_bytes();
193
194        let payload = [0xAA, 0xBB, 0xCC, 0xDD]; let mut combined = [0u8; 8];
196        combined[0..4].copy_from_slice(&header_bytes);
197        combined[4..8].copy_from_slice(&payload);
198        let pec = smbus_pec::pec(&combined);
199
200        let mut packet = [0u8; 9];
201        packet[0..4].copy_from_slice(&header_bytes);
202        packet[4..8].copy_from_slice(&payload);
203        packet[8] = pec;
204
205        let result = medium.deserialize(&packet).unwrap();
206        let (frame, body) = result;
207
208        assert_eq!(frame.header.destination_slave_address, 0x20);
209        assert_eq!(frame.header.source_slave_address, 0x10);
210        assert_eq!(frame.header.command_code, SmbusCommandCode::Mctp);
211        assert_eq!(frame.header.byte_count, 4);
212        assert_eq!(frame.pec, pec);
213        assert_eq!(body, &payload);
214    }
215
216    #[test]
217    fn test_deserialize_packet_too_short_header() {
218        let medium = SmbusEspiMedium;
219        let short_packet = [0x01, 0x02]; let result = medium.deserialize(&short_packet);
222        assert_eq!(
223            result,
224            Err(MctpPacketError::MediumError(
225                "Packet too short to parse smbus header"
226            ))
227        );
228    }
229
230    #[test]
231    fn test_deserialize_packet_too_short_body() {
232        let medium = SmbusEspiMedium;
233
234        let header_bytes = [
236            0x20, 0x0F, 0x0A, 0x20, ];
241
242        let short_payload = [0xAA, 0xBB]; let mut packet = [0u8; 6];
245        packet[0..4].copy_from_slice(&header_bytes);
246        packet[4..6].copy_from_slice(&short_payload);
247
248        let result = medium.deserialize(&packet);
249        assert_eq!(
250            result,
251            Err(MctpPacketError::MediumError(
252                "Packet too short to parse smbus body and PEC"
253            ))
254        );
255    }
256
257    #[test]
258    fn test_deserialize_invalid_header() {
259        let medium = SmbusEspiMedium;
260
261        let invalid_header_bytes = [
263            0x20, 0xFF, 0x04, 0x20, ];
268
269        let payload = [0xAA, 0xBB, 0xCC, 0xDD];
270        let pec = 0x00; let mut packet = [0u8; 9];
273        packet[0..4].copy_from_slice(&invalid_header_bytes);
274        packet[4..8].copy_from_slice(&payload);
275        packet[8] = pec;
276
277        let result = medium.deserialize(&packet);
278        assert_eq!(
279            result,
280            Err(MctpPacketError::MediumError("Invalid smbus header"))
281        );
282    }
283
284    #[test]
285    fn test_deserialize_zero_byte_count() {
286        let medium = SmbusEspiMedium;
287
288        let header_bytes = [
289            0x20, 0x0F, 0x00, 0x20, ];
294
295        let pec = smbus_pec::pec(&header_bytes);
296
297        let mut packet = [0u8; 5];
298        packet[0..4].copy_from_slice(&header_bytes);
299        packet[4] = pec;
300
301        let result = medium.deserialize(&packet).unwrap();
302        let (frame, body) = result;
303
304        assert_eq!(frame.header.byte_count, 0);
305        assert_eq!(frame.pec, pec);
306        assert_eq!(body.len(), 0);
307    }
308
309    #[test]
310    fn test_serialize_valid_packet() {
311        let medium = SmbusEspiMedium;
312        let reply_context = SmbusEspiReplyContext {
313            destination_slave_address: 0x20,
314            source_slave_address: 0x10,
315        };
316
317        let mut buffer = [0u8; 64];
318        let test_payload = [0xAA, 0xBB, 0xCC, 0xDD];
319
320        let result = medium
321            .serialize(reply_context, &mut buffer, |buf| {
322                buf[..test_payload.len()].copy_from_slice(&test_payload);
323                Ok(test_payload.len())
324            })
325            .unwrap();
326
327        assert_eq!(result.len(), 9);
330
331        let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
333        let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
334
335        assert_eq!(header.destination_slave_address, 0x10); assert_eq!(header.source_slave_address, 0x20); assert_eq!(header.command_code, SmbusCommandCode::Mctp);
339        assert_eq!(header.byte_count, 4);
340
341        assert_eq!(&result[4..8], &test_payload);
343
344        let expected_pec = smbus_pec::pec(&result[0..8]);
346        assert_eq!(result[8], expected_pec);
347    }
348
349    #[test]
350    fn test_serialize_buffer_too_small() {
351        let medium = SmbusEspiMedium;
352        let reply_context = SmbusEspiReplyContext {
353            destination_slave_address: 0x20,
354            source_slave_address: 0x10,
355        };
356
357        let mut small_buffer = [0u8; 4]; let result = medium.serialize(reply_context, &mut small_buffer, |_| Ok(0));
360
361        assert_eq!(
362            result,
363            Err(MctpPacketError::MediumError(
364                "Buffer too small for smbus frame"
365            ))
366        );
367    }
368
369    #[test]
370    fn test_serialize_minimal_buffer() {
371        let medium = SmbusEspiMedium;
372        let reply_context = SmbusEspiReplyContext {
373            destination_slave_address: 0x20,
374            source_slave_address: 0x10,
375        };
376
377        let mut minimal_buffer = [0u8; 5]; let result = medium
380            .serialize(
381                reply_context,
382                &mut minimal_buffer,
383                |_| Ok(0), )
385            .unwrap();
386
387        assert_eq!(result.len(), 5);
388
389        let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
391        let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
392        assert_eq!(header.byte_count, 0);
393
394        let expected_pec = smbus_pec::pec(&result[0..4]);
396        assert_eq!(result[4], expected_pec);
397    }
398
399    #[test]
400    fn test_serialize_max_payload() {
401        let medium = SmbusEspiMedium;
402        let reply_context = SmbusEspiReplyContext {
403            destination_slave_address: 0x20,
404            source_slave_address: 0x10,
405        };
406
407        let max_payload = [0x55u8; 255];
409        let mut buffer = [0u8; 260]; let result = medium
412            .serialize(reply_context, &mut buffer, |buf| {
413                let copy_len = max_payload.len().min(buf.len());
414                buf[..copy_len].copy_from_slice(&max_payload[..copy_len]);
415                Ok(copy_len)
416            })
417            .unwrap();
418
419        assert_eq!(result.len(), 260); let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
423        let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
424        assert_eq!(header.byte_count, 255);
425
426        assert_eq!(&result[4..259], &max_payload[..]);
428
429        let expected_pec = smbus_pec::pec(&result[0..259]);
431        assert_eq!(result[259], expected_pec);
432    }
433
434    #[test]
435    fn test_serialize_message_writer_error() {
436        let medium = SmbusEspiMedium;
437        let reply_context = SmbusEspiReplyContext {
438            destination_slave_address: 0x20,
439            source_slave_address: 0x10,
440        };
441
442        let mut buffer = [0u8; 64];
443
444        let result = medium.serialize(reply_context, &mut buffer, |_| {
445            Err(MctpPacketError::MediumError("Test error"))
446        });
447
448        assert_eq!(result, Err(MctpPacketError::MediumError("Test error")));
449    }
450
451    #[test]
452    fn test_roundtrip_serialization_deserialization() {
453        let medium = SmbusEspiMedium;
454        let original_context = SmbusEspiReplyContext {
455            destination_slave_address: 0x42,
456            source_slave_address: 0x24,
457        };
458
459        let original_payload = [0x11, 0x22, 0x33, 0x44, 0x55];
460        let mut buffer = [0u8; 64];
461
462        let serialized = medium
464            .serialize(original_context, &mut buffer, |buf| {
465                buf[..original_payload.len()].copy_from_slice(&original_payload);
466                Ok(original_payload.len())
467            })
468            .unwrap();
469
470        let (frame, deserialized_payload) = medium.deserialize(serialized).unwrap();
472
473        assert_eq!(deserialized_payload, &original_payload);
475        assert_eq!(frame.header.destination_slave_address, 0x24); assert_eq!(frame.header.source_slave_address, 0x42); assert_eq!(frame.header.command_code, SmbusCommandCode::Mctp);
478        assert_eq!(frame.header.byte_count, original_payload.len() as u8);
479
480        let expected_pec = smbus_pec::pec(&serialized[0..serialized.len() - 1]);
482        assert_eq!(frame.pec, expected_pec);
483    }
484
485    #[test]
486    fn test_frame_packet_size() {
487        let frame = SmbusEspiMediumFrame {
488            header: SmbusEspiMediumHeader {
489                byte_count: 42,
490                ..Default::default()
491            },
492            pec: 0,
493        };
494
495        assert_eq!(frame.packet_size(), 42);
496    }
497
498    #[test]
499    fn test_frame_reply_context() {
500        let frame = SmbusEspiMediumFrame {
501            header: SmbusEspiMediumHeader {
502                destination_slave_address: 0x30,
503                source_slave_address: 0x40,
504                ..Default::default()
505            },
506            pec: 0,
507        };
508
509        let context = frame.reply_context();
510        assert_eq!(context.destination_slave_address, 0x30);
511        assert_eq!(context.source_slave_address, 0x40);
512    }
513
514    #[test]
515    fn test_smbus_command_code_conversion() {
516        assert_eq!(
518            SmbusCommandCode::try_from_bits(0x0F).unwrap(),
519            SmbusCommandCode::Mctp
520        );
521
522        assert_eq!(
524            SmbusCommandCode::try_from_bits(0x100),
525            Err("Command code out of range")
526        );
527
528        assert_eq!(
530            SmbusCommandCode::try_from_bits(0x10),
531            Err("Invalid command code")
532        );
533
534        assert_eq!(SmbusCommandCode::Mctp.try_into_bits().unwrap(), 0x0F);
536    }
537
538    #[test]
539    fn test_header_bit_register_edge_cases() {
540        let header = SmbusEspiMediumHeader::default();
542        assert_eq!(header.destination_slave_address, 0);
543        assert_eq!(header.source_slave_address, 0);
544        assert_eq!(header.byte_count, 0);
545        assert_eq!(header.command_code, SmbusCommandCode::Mctp); let header = SmbusEspiMediumHeader {
549            destination_slave_address: 0x7F, source_slave_address: 0x3F,      byte_count: 0xFF,                command_code: SmbusCommandCode::Mctp,
553            ..Default::default()
554        };
555
556        let header_value: u32 = header.try_into().unwrap();
558        let reconstructed = SmbusEspiMediumHeader::try_from(header_value).unwrap();
559        assert_eq!(reconstructed, header);
560    }
561
562    #[test]
563    fn test_pec_calculation_accuracy() {
564        let medium = SmbusEspiMedium;
565        let reply_context = SmbusEspiReplyContext {
566            destination_slave_address: 0x50,
567            source_slave_address: 0x30,
568        };
569
570        let test_data = [0x01, 0x02, 0x03];
572        let mut buffer = [0u8; 32];
573
574        let result = medium
575            .serialize(reply_context, &mut buffer, |buf| {
576                buf[..test_data.len()].copy_from_slice(&test_data);
577                Ok(test_data.len())
578            })
579            .unwrap();
580
581        let data_for_pec = &result[0..result.len() - 1];
583        let expected_pec = smbus_pec::pec(data_for_pec);
584        let actual_pec = result[result.len() - 1];
585
586        assert_eq!(actual_pec, expected_pec);
587    }
588
589    #[test]
590    fn test_serialize_with_empty_payload() {
591        let medium = SmbusEspiMedium;
592        let reply_context = SmbusEspiReplyContext {
593            destination_slave_address: 0x60,
594            source_slave_address: 0x70,
595        };
596
597        let mut buffer = [0u8; 16];
598
599        let result = medium
600            .serialize(
601                reply_context,
602                &mut buffer,
603                |_| Ok(0), )
605            .unwrap();
606
607        assert_eq!(result.len(), 5); let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
611        let header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
612        assert_eq!(header.byte_count, 0);
613        assert_eq!(header.destination_slave_address, 0x70); assert_eq!(header.source_slave_address, 0x60); let expected_pec = smbus_pec::pec(&result[0..4]);
618        assert_eq!(result[4], expected_pec);
619    }
620
621    #[test]
622    fn test_max_message_body_size() {
623        let medium = SmbusEspiMedium;
624        assert_eq!(medium.max_message_body_size(), 32);
625    }
626
627    #[test]
628    fn test_address_swapping_in_reply_context() {
629        let original_frame = SmbusEspiMediumFrame {
631            header: SmbusEspiMediumHeader {
632                destination_slave_address: 0x2A, source_slave_address: 0x3B,      ..Default::default()
635            },
636            pec: 0,
637        };
638
639        let reply_context = SmbusEspiReplyContext::new(original_frame);
640        assert_eq!(reply_context.destination_slave_address, 0x2A);
641        assert_eq!(reply_context.source_slave_address, 0x3B);
642
643        let medium = SmbusEspiMedium;
645        let mut buffer = [0u8; 16];
646
647        let result = medium
648            .serialize(reply_context, &mut buffer, |_| Ok(0))
649            .unwrap();
650
651        let header_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
652        let response_header = SmbusEspiMediumHeader::try_from(header_value).unwrap();
653
654        assert_eq!(response_header.destination_slave_address, 0x3B);
656        assert_eq!(response_header.source_slave_address, 0x2A);
657    }
658
659    #[test]
660    fn test_deserialize_with_different_byte_counts() {
661        let medium = SmbusEspiMedium;
662
663        for byte_count in [1, 16, 32, 64, 128, 255] {
664            let header_bytes = [
665                0x20,       0x0F,       byte_count, 0x20,       ];
670
671            let payload = [0x42u8; 255];
672            let payload_slice = &payload[..byte_count as usize];
673
674            let mut combined = [0u8; 259]; combined[0..4].copy_from_slice(&header_bytes);
676            combined[4..4 + byte_count as usize].copy_from_slice(payload_slice);
677            let pec = smbus_pec::pec(&combined[0..4 + byte_count as usize]);
678
679            let mut packet = [0u8; 260]; packet[0..4].copy_from_slice(&header_bytes);
681            packet[4..4 + byte_count as usize].copy_from_slice(payload_slice);
682            packet[4 + byte_count as usize] = pec;
683
684            let packet_slice = &packet[0..4 + byte_count as usize + 1];
685            let result = medium.deserialize(packet_slice).unwrap();
686            let (frame, body) = result;
687
688            assert_eq!(frame.header.byte_count, byte_count);
689            assert_eq!(body.len(), byte_count as usize);
690            assert_eq!(frame.pec, pec);
691        }
692    }
693
694    #[test]
695    fn test_smbus_buffer_overflow_protection() {
696        let medium = SmbusEspiMedium;
697
698        let header_bytes = [
700            0x20, 0x0F, 0xFF, 0x20, ];
705
706        let short_payload = [0xAA, 0xBB]; let mut packet = [0u8; 7]; packet[0..4].copy_from_slice(&header_bytes);
710        packet[4..6].copy_from_slice(&short_payload);
711        packet[6] = 0x00; let result = medium.deserialize(&packet);
714        assert_eq!(
715            result,
716            Err(MctpPacketError::MediumError(
717                "Packet too short to parse smbus body and PEC"
718            ))
719        );
720    }
721
722    #[test]
723    fn test_smbus_serialize_buffer_underflow() {
724        let medium = SmbusEspiMedium;
725        let reply_context = SmbusEspiReplyContext {
726            destination_slave_address: 0x20,
727            source_slave_address: 0x10,
728        };
729
730        let mut tiny_buffer = [0u8; 4]; let result = medium.serialize(reply_context, &mut tiny_buffer, |_| {
734            Ok(0) });
736
737        assert_eq!(
738            result,
739            Err(MctpPacketError::MediumError(
740                "Buffer too small for smbus frame"
741            ))
742        );
743    }
744
745    #[test]
746    fn test_smbus_header_bounds_checking() {
747        let medium = SmbusEspiMedium;
748
749        for packet_size in 0..4 {
751            let short_packet = [0u8; 4];
752            let result = medium.deserialize(&short_packet[..packet_size]);
753            assert_eq!(
754                result,
755                Err(MctpPacketError::MediumError(
756                    "Packet too short to parse smbus header"
757                ))
758            );
759        }
760    }
761
762    #[test]
763    fn test_smbus_pec_bounds_checking() {
764        let medium = SmbusEspiMedium;
765
766        let header_bytes = [
768            0x20, 0x0F, 0x05, 0x20, ];
773
774        let payload = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE]; let mut packet = [0u8; 9]; packet[0..4].copy_from_slice(&header_bytes);
778        packet[4..9].copy_from_slice(&payload);
779
780        let result = medium.deserialize(&packet);
781        assert_eq!(
782            result,
783            Err(MctpPacketError::MediumError(
784                "Packet too short to parse smbus body and PEC"
785            ))
786        );
787    }
788
789    #[test]
790    fn test_smbus_zero_byte_count_edge_case() {
791        let medium = SmbusEspiMedium;
792
793        let header_bytes = [
795            0x20, 0x0F, 0x00, 0x20, ];
800
801        let mut short_packet = [0u8; 4]; short_packet.copy_from_slice(&header_bytes);
804
805        let result = medium.deserialize(&short_packet);
806        assert_eq!(
807            result,
808            Err(MctpPacketError::MediumError(
809                "Packet too short to parse smbus body and PEC"
810            ))
811        );
812    }
813
814    #[test]
815    fn test_smbus_maximum_payload_boundary() {
816        let medium = SmbusEspiMedium;
817
818        let reply_context = SmbusEspiReplyContext {
820            destination_slave_address: 0x20,
821            source_slave_address: 0x10,
822        };
823
824        let max_payload = [0x55u8; 255];
825        let mut buffer = [0u8; 260]; let result = medium.serialize(reply_context, &mut buffer, |buf| {
828            let copy_len = max_payload.len().min(buf.len());
829            buf[..copy_len].copy_from_slice(&max_payload[..copy_len]);
830            Ok(copy_len)
831        });
832
833        assert!(result.is_ok());
834        let serialized = result.unwrap();
835        assert_eq!(serialized.len(), 260); let mut small_buffer = [0u8; 259]; let result_small = medium.serialize(reply_context, &mut small_buffer, |buf| {
840            let copy_len = max_payload.len().min(buf.len());
842            buf[..copy_len].copy_from_slice(&max_payload[..copy_len]);
843            Ok(copy_len)
844        });
845
846        assert!(result_small.is_ok());
848        let serialized_small = result_small.unwrap();
849        assert_eq!(serialized_small.len(), 259); }
851}