piper_sdk/protocol/
mod.rs

1//! Piper 协议层模块
2//!
3//! 负责将 CAN 帧的原始字节数据解析为类型安全的 Rust 结构体,
4//! 以及将 Rust 结构体编码为 CAN 帧数据。
5
6pub mod config;
7pub mod control;
8pub mod feedback;
9pub mod ids;
10
11pub use config::*;
12pub use control::*;
13pub use feedback::*;
14pub use ids::*;
15
16use thiserror::Error;
17
18/// 协议解析错误类型
19#[derive(Error, Debug)]
20pub enum ProtocolError {
21    #[error("Invalid frame length: expected {expected}, got {actual}")]
22    InvalidLength { expected: usize, actual: usize },
23
24    #[error("Invalid CAN ID: 0x{id:X}")]
25    InvalidCanId { id: u32 },
26
27    #[error("Parse error: {0}")]
28    ParseError(String),
29
30    #[error("Invalid value for field {field}: {value}")]
31    InvalidValue { field: String, value: u8 },
32}
33
34/// 字节序转换工具函数
35///
36/// 协议使用 Motorola (MSB) 高位在前(大端字节序),
37/// 这些函数用于在协议层进行字节序转换。
38/// 大端字节序转 i32
39pub fn bytes_to_i32_be(bytes: [u8; 4]) -> i32 {
40    i32::from_be_bytes(bytes)
41}
42
43/// 大端字节序转 i16
44pub fn bytes_to_i16_be(bytes: [u8; 2]) -> i16 {
45    i16::from_be_bytes(bytes)
46}
47
48/// i32 转大端字节序
49pub fn i32_to_bytes_be(value: i32) -> [u8; 4] {
50    value.to_be_bytes()
51}
52
53/// i16 转大端字节序
54pub fn i16_to_bytes_be(value: i16) -> [u8; 2] {
55    value.to_be_bytes()
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_bytes_to_i32_be() {
64        let bytes = [0x12, 0x34, 0x56, 0x78];
65        let value = bytes_to_i32_be(bytes);
66        assert_eq!(value, 0x12345678);
67    }
68
69    #[test]
70    fn test_bytes_to_i32_be_negative() {
71        let bytes = [0xFF, 0xFF, 0xFF, 0xFF];
72        let value = bytes_to_i32_be(bytes);
73        assert_eq!(value, -1);
74    }
75
76    #[test]
77    fn test_bytes_to_i16_be() {
78        let bytes = [0x12, 0x34];
79        let value = bytes_to_i16_be(bytes);
80        assert_eq!(value, 0x1234);
81    }
82
83    #[test]
84    fn test_bytes_to_i16_be_negative() {
85        let bytes = [0xFF, 0xFF];
86        let value = bytes_to_i16_be(bytes);
87        assert_eq!(value, -1);
88    }
89
90    #[test]
91    fn test_i32_to_bytes_be() {
92        let value = 0x12345678;
93        let bytes = i32_to_bytes_be(value);
94        assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
95    }
96
97    #[test]
98    fn test_i32_to_bytes_be_negative() {
99        let value = -1;
100        let bytes = i32_to_bytes_be(value);
101        assert_eq!(bytes, [0xFF, 0xFF, 0xFF, 0xFF]);
102    }
103
104    #[test]
105    fn test_i16_to_bytes_be() {
106        let value = 0x1234;
107        let bytes = i16_to_bytes_be(value);
108        assert_eq!(bytes, [0x12, 0x34]);
109    }
110
111    #[test]
112    fn test_i16_to_bytes_be_negative() {
113        let value = -1;
114        let bytes = i16_to_bytes_be(value);
115        assert_eq!(bytes, [0xFF, 0xFF]);
116    }
117
118    #[test]
119    fn test_roundtrip_i32() {
120        let original = 0x12345678;
121        let bytes = i32_to_bytes_be(original);
122        let decoded = bytes_to_i32_be(bytes);
123        assert_eq!(original, decoded);
124    }
125
126    #[test]
127    fn test_roundtrip_i16() {
128        let original = 0x1234;
129        let bytes = i16_to_bytes_be(original);
130        let decoded = bytes_to_i16_be(bytes);
131        assert_eq!(original, decoded);
132    }
133}