nautilus_binance/common/sbe/
error.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Unified SBE decode error type for Binance adapters.
17
18use std::fmt::Display;
19
20/// Maximum allowed group size to prevent DoS from malformed data.
21pub const MAX_GROUP_SIZE: u32 = 10_000;
22
23/// SBE decode error.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum SbeDecodeError {
26    /// Buffer too short to decode expected data.
27    BufferTooShort {
28        /// Expected minimum bytes.
29        expected: usize,
30        /// Actual bytes available.
31        actual: usize,
32    },
33    /// Schema ID mismatch.
34    SchemaMismatch {
35        /// Expected schema ID.
36        expected: u16,
37        /// Actual schema ID.
38        actual: u16,
39    },
40    /// Schema version mismatch.
41    VersionMismatch {
42        /// Expected schema version.
43        expected: u16,
44        /// Actual schema version.
45        actual: u16,
46    },
47    /// Unknown template ID.
48    UnknownTemplateId(u16),
49    /// Group count exceeds safety limit.
50    GroupSizeTooLarge {
51        /// Actual count.
52        count: u32,
53        /// Maximum allowed.
54        max: u32,
55    },
56    /// Invalid block length.
57    InvalidBlockLength {
58        /// Expected block length.
59        expected: u16,
60        /// Actual block length.
61        actual: u16,
62    },
63    /// Invalid UTF-8 in string field.
64    InvalidUtf8,
65}
66
67impl Display for SbeDecodeError {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            Self::BufferTooShort { expected, actual } => {
71                write!(
72                    f,
73                    "Buffer too short: expected {expected} bytes, got {actual}"
74                )
75            }
76            Self::SchemaMismatch { expected, actual } => {
77                write!(f, "Schema ID mismatch: expected {expected}, got {actual}")
78            }
79            Self::VersionMismatch { expected, actual } => {
80                write!(
81                    f,
82                    "Schema version mismatch: expected {expected}, got {actual}"
83                )
84            }
85            Self::UnknownTemplateId(id) => write!(f, "Unknown template ID: {id}"),
86            Self::GroupSizeTooLarge { count, max } => {
87                write!(f, "Group size {count} exceeds maximum {max}")
88            }
89            Self::InvalidBlockLength { expected, actual } => {
90                write!(f, "Invalid block length: expected {expected}, got {actual}")
91            }
92            Self::InvalidUtf8 => write!(f, "Invalid UTF-8 in string field"),
93        }
94    }
95}
96
97impl std::error::Error for SbeDecodeError {}
98
99#[cfg(test)]
100mod tests {
101    use rstest::rstest;
102
103    use super::*;
104
105    #[rstest]
106    fn test_buffer_too_short_display() {
107        let err = SbeDecodeError::BufferTooShort {
108            expected: 100,
109            actual: 50,
110        };
111        assert_eq!(
112            err.to_string(),
113            "Buffer too short: expected 100 bytes, got 50"
114        );
115    }
116
117    #[rstest]
118    fn test_schema_mismatch_display() {
119        let err = SbeDecodeError::SchemaMismatch {
120            expected: 3,
121            actual: 1,
122        };
123        assert_eq!(err.to_string(), "Schema ID mismatch: expected 3, got 1");
124    }
125
126    #[rstest]
127    fn test_group_size_too_large_display() {
128        let err = SbeDecodeError::GroupSizeTooLarge {
129            count: 50000,
130            max: 10000,
131        };
132        assert_eq!(err.to_string(), "Group size 50000 exceeds maximum 10000");
133    }
134
135    #[rstest]
136    fn test_error_equality() {
137        let err1 = SbeDecodeError::InvalidUtf8;
138        let err2 = SbeDecodeError::InvalidUtf8;
139        assert_eq!(err1, err2);
140    }
141}