Skip to main content

cqlite_core/parser/
binary.rs

1//! Binary format parsing for backward compatibility
2//!
3//! This module provides parsing support for existing binary formats
4//! used in SSTable parsing, maintaining backward compatibility while
5//! transitioning to the new parser abstraction layer.
6
7use crate::cql::ast::*;
8use crate::cql::config::ParserConfig;
9use crate::cql::traits::{CqlParser, ParserBackendInfo, ParserFeature, PerformanceCharacteristics};
10use crate::error::{Error, Result};
11use async_trait::async_trait;
12
13/// Binary format parser for SSTable compatibility
14#[derive(Debug)]
15pub struct SSTableParser {}
16
17impl SSTableParser {
18    /// Create a new binary parser
19    pub fn new(_config: ParserConfig) -> Result<Self> {
20        Ok(Self {})
21    }
22
23    /// Get backend information
24    pub fn backend_info() -> ParserBackendInfo {
25        ParserBackendInfo {
26            name: "binary".to_string(),
27            version: "1.0.0".to_string(),
28            features: vec![ParserFeature::Streaming],
29            performance: PerformanceCharacteristics {
30                statements_per_second: 50_000,
31                memory_per_statement: 512,
32                startup_time_ms: 1,
33                async_support: true,
34            },
35        }
36    }
37}
38
39#[async_trait]
40impl CqlParser for SSTableParser {
41    async fn parse(&self, _input: &str) -> Result<CqlStatement> {
42        Err(Error::invalid_operation(
43            "Binary parser does not support text parsing".to_string(),
44        ))
45    }
46
47    async fn parse_type(&self, _input: &str) -> Result<CqlDataType> {
48        Err(Error::invalid_operation(
49            "Binary parser does not support text parsing".to_string(),
50        ))
51    }
52
53    async fn parse_expression(&self, _input: &str) -> Result<CqlExpression> {
54        Err(Error::invalid_operation(
55            "Binary parser does not support text parsing".to_string(),
56        ))
57    }
58
59    async fn parse_identifier(&self, _input: &str) -> Result<CqlIdentifier> {
60        Err(Error::invalid_operation(
61            "Binary parser does not support text parsing".to_string(),
62        ))
63    }
64
65    async fn parse_literal(&self, _input: &str) -> Result<CqlLiteral> {
66        Err(Error::invalid_operation(
67            "Binary parser does not support text parsing".to_string(),
68        ))
69    }
70
71    async fn parse_column_definitions(&self, _input: &str) -> Result<Vec<CqlColumnDef>> {
72        Err(Error::invalid_operation(
73            "Binary parser does not support text parsing".to_string(),
74        ))
75    }
76
77    async fn parse_table_options(&self, _input: &str) -> Result<CqlTableOptions> {
78        Err(Error::invalid_operation(
79            "Binary parser does not support text parsing".to_string(),
80        ))
81    }
82
83    fn validate_syntax(&self, _input: &str) -> bool {
84        false // Binary parser doesn't validate text syntax
85    }
86
87    fn backend_info(&self) -> ParserBackendInfo {
88        Self::backend_info()
89    }
90}
91
92/// Legacy error type for backward compatibility
93#[derive(Debug, thiserror::Error)]
94pub enum CQLiteParseError {
95    #[error("Parse error: {0}")]
96    ParseError(String),
97
98    #[error("Invalid format: {0}")]
99    InvalidFormat(String),
100
101    #[error("Unsupported operation: {0}")]
102    Unsupported(String),
103}
104
105impl From<Error> for CQLiteParseError {
106    fn from(err: Error) -> Self {
107        CQLiteParseError::ParseError(err.to_string())
108    }
109}
110
111/// Legacy result type for backward compatibility
112pub type ParseResult<T> = std::result::Result<T, CQLiteParseError>;
113
114/// Parse binary data (placeholder for backward compatibility)
115pub fn parse_binary_data(data: &[u8]) -> ParseResult<Vec<u8>> {
116    if data.is_empty() {
117        return Err(CQLiteParseError::InvalidFormat("Empty input".to_string()));
118    }
119
120    // For now, just return the input data
121    // In a real implementation, this would parse the binary format
122    Ok(data.to_vec())
123}
124
125/// Parse variable-length integer from binary data
126pub fn parse_vint_binary(data: &[u8]) -> ParseResult<(u64, usize)> {
127    if data.is_empty() {
128        return Err(CQLiteParseError::InvalidFormat(
129            "Empty vint data".to_string(),
130        ));
131    }
132
133    // Simple vint parsing - first byte indicates length
134    let first_byte = data[0];
135    if first_byte & 0x80 == 0 {
136        // Single byte
137        Ok((first_byte as u64, 1))
138    } else {
139        // Multi-byte - not fully implemented
140        Err(CQLiteParseError::Unsupported(
141            "Multi-byte vint not implemented".to_string(),
142        ))
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::*;
149
150    #[test]
151    fn test_binary_parser_creation() {
152        let config = ParserConfig::default();
153        let parser = SSTableParser::new(config).unwrap();
154
155        let info = parser.backend_info();
156        assert_eq!(info.name, "binary");
157    }
158
159    #[tokio::test]
160    async fn test_binary_parser_unsupported() {
161        let config = ParserConfig::default();
162        let parser = SSTableParser::new(config).unwrap();
163
164        let result = parser.parse("SELECT * FROM test").await;
165        assert!(result.is_err());
166    }
167
168    #[test]
169    fn test_parse_binary_data() {
170        let data = b"test data";
171        let result = parse_binary_data(data).unwrap();
172        assert_eq!(result, data);
173
174        let empty_result = parse_binary_data(&[]);
175        assert!(empty_result.is_err());
176    }
177
178    #[test]
179    fn test_parse_vint_binary() {
180        let data = &[0x42]; // Single byte vint
181        let (value, consumed) = parse_vint_binary(data).unwrap();
182        assert_eq!(value, 0x42);
183        assert_eq!(consumed, 1);
184
185        let empty_result = parse_vint_binary(&[]);
186        assert!(empty_result.is_err());
187    }
188
189    #[test]
190    fn test_parse_vint_binary_unsupported_multi_byte() {
191        let data = &[0x80, 0x01];
192        let err =
193            parse_vint_binary(data).expect_err("multi-byte vint should return unsupported error");
194        assert!(matches!(err, CQLiteParseError::Unsupported(_)));
195    }
196
197    #[test]
198    fn test_backend_info_and_validate_syntax() {
199        let info = SSTableParser::backend_info();
200        assert_eq!(info.name, "binary");
201        assert!(info.features.contains(&ParserFeature::Streaming));
202
203        let parser = SSTableParser::new(ParserConfig::default()).unwrap();
204        assert!(!parser.validate_syntax("SELECT * FROM ks.table"));
205    }
206}