Skip to main content

framing_sv2/
error.rs

1//! # Error Handling
2//!
3//! This module defines error types and utilities for handling errors in the `framing_sv2` module.
4
5use core::fmt;
6
7use crate::SV2_FRAME_HEADER_SIZE;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum Error {
11    /// Binary Sv2 data format error.
12    BinarySv2Error(binary_sv2::Error),
13
14    /// The buffer passed to [`crate::framing::EncodableFrame::encode_into`] is not exactly as
15    /// long as the frame.
16    UnexpectedDestinationLength {
17        /// Length the encoded frame takes.
18        expected: usize,
19        /// Length of the buffer that was passed.
20        actual: usize,
21    },
22
23    /// The message serialized to a different number of bytes than the
24    /// [`crate::header::Header`] declares, i.e. than its `GetSize` reported.
25    PayloadLengthMismatch {
26        /// Payload length the header declares.
27        declared: usize,
28        /// Number of bytes the message serialized to.
29        written: usize,
30    },
31
32    /// The buffer is too short to hold a [`crate::header::Header`].
33    UnexpectedHeaderLength(usize),
34
35    /// A message of the given serialized length does not fit the 24-bit `msg_length` field of a
36    /// [`crate::header::Header`].
37    PayloadTooLong(usize),
38}
39
40impl fmt::Display for Error {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        use Error::*;
43        match self {
44            BinarySv2Error(ref e) => {
45                write!(f, "BinarySv2Error: `{e}`")
46            }
47            UnexpectedDestinationLength { expected, actual } => {
48                write!(
49                    f,
50                    "Destination buffer is `{actual}` bytes long, the encoded frame takes `{expected}`"
51                )
52            }
53            PayloadLengthMismatch { declared, written } => {
54                write!(
55                    f,
56                    "Message serialized to `{written}` bytes, its `Header` declares `{declared}`"
57                )
58            }
59            UnexpectedHeaderLength(actual_size) => {
60                write!(
61                    f,
62                    "Unexpected `Header` length: `{actual_size}`, should be equal or more to {SV2_FRAME_HEADER_SIZE}"
63                )
64            }
65            PayloadTooLong(len) => {
66                write!(
67                    f,
68                    "Payload of `{len}` bytes does not fit the 24-bit `msg_length` of a `Header`"
69                )
70            }
71        }
72    }
73}
74
75impl From<binary_sv2::Error> for Error {
76    fn from(e: binary_sv2::Error) -> Self {
77        Error::BinarySv2Error(e)
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::Error;
84    use alloc::{string::ToString, vec};
85
86    // `ValueExceedsMaxSize` carries a peer-derived sample and this error is logged, so no
87    // formatting path may write that sample out.
88    #[test]
89    fn binary_error_display_does_not_dump_embedded_payload() {
90        let sample = vec![0xAB_u8; 64 * 1024];
91        let err = Error::BinarySv2Error(binary_sv2::Error::ValueExceedsMaxSize(
92            false,
93            1,
94            1,
95            32,
96            sample,
97            64 * 1024,
98        ));
99
100        let rendered = err.to_string();
101
102        assert!(
103            !rendered.contains("171"),
104            "Display leaked sample bytes: {rendered}"
105        );
106        assert!(
107            rendered.len() < 128,
108            "Display grew with the sample: {} bytes",
109            rendered.len()
110        );
111    }
112}