Skip to main content

memcache_proto/
error.rs

1//! Error types for Memcache protocol parsing.
2
3/// Error type for Memcache parsing operations.
4#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
5pub enum ParseError {
6    /// Need more data to complete parsing.
7    /// This is not a fatal error - the caller should buffer more data and retry.
8    #[error("incomplete data")]
9    Incomplete,
10
11    /// Invalid protocol format (static message).
12    #[error("protocol error: {0}")]
13    Protocol(&'static str),
14
15    /// Invalid protocol format (dynamic message).
16    #[cfg(feature = "binary")]
17    #[error("protocol error: {0}")]
18    ProtocolDynamic(String),
19
20    /// Invalid number format.
21    #[error("invalid number")]
22    InvalidNumber,
23
24    /// Unknown command.
25    #[error("unknown command")]
26    UnknownCommand,
27
28    /// Unknown opcode in binary protocol.
29    #[cfg(feature = "binary")]
30    #[error("unknown opcode: {0:#04x}")]
31    UnknownOpcode(u8),
32
33    /// Invalid magic byte in binary protocol.
34    #[cfg(feature = "binary")]
35    #[error("invalid magic byte: {0:#04x}")]
36    InvalidMagic(u8),
37}
38
39impl ParseError {
40    /// Returns true if this error indicates more data is needed.
41    #[inline]
42    pub fn is_incomplete(&self) -> bool {
43        matches!(self, ParseError::Incomplete)
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn test_is_incomplete() {
53        assert!(ParseError::Incomplete.is_incomplete());
54        assert!(!ParseError::Protocol("test").is_incomplete());
55        assert!(!ParseError::InvalidNumber.is_incomplete());
56        assert!(!ParseError::UnknownCommand.is_incomplete());
57    }
58
59    #[test]
60    fn test_error_display() {
61        assert_eq!(format!("{}", ParseError::Incomplete), "incomplete data");
62        assert_eq!(
63            format!("{}", ParseError::Protocol("bad format")),
64            "protocol error: bad format"
65        );
66        assert_eq!(format!("{}", ParseError::InvalidNumber), "invalid number");
67        assert_eq!(format!("{}", ParseError::UnknownCommand), "unknown command");
68    }
69
70    #[test]
71    fn test_error_debug() {
72        let err = ParseError::Incomplete;
73        let debug_str = format!("{:?}", err);
74        assert!(debug_str.contains("Incomplete"));
75    }
76
77    #[test]
78    fn test_error_clone() {
79        let err1 = ParseError::Protocol("test");
80        let err2 = err1.clone();
81        assert_eq!(err1, err2);
82    }
83
84    #[test]
85    fn test_error_eq() {
86        assert_eq!(ParseError::Incomplete, ParseError::Incomplete);
87        assert_ne!(ParseError::Incomplete, ParseError::InvalidNumber);
88        assert_eq!(ParseError::Protocol("test"), ParseError::Protocol("test"));
89        assert_ne!(ParseError::Protocol("a"), ParseError::Protocol("b"));
90    }
91
92    #[cfg(feature = "binary")]
93    #[test]
94    fn test_binary_errors() {
95        assert!(!ParseError::ProtocolDynamic("test".to_string()).is_incomplete());
96        assert!(!ParseError::UnknownOpcode(0x42).is_incomplete());
97        assert!(!ParseError::InvalidMagic(0x80).is_incomplete());
98
99        assert_eq!(
100            format!("{}", ParseError::ProtocolDynamic("error".to_string())),
101            "protocol error: error"
102        );
103        assert_eq!(
104            format!("{}", ParseError::UnknownOpcode(0x42)),
105            "unknown opcode: 0x42"
106        );
107        assert_eq!(
108            format!("{}", ParseError::InvalidMagic(0x80)),
109            "invalid magic byte: 0x80"
110        );
111    }
112}