1use crate::error::{EventError, EventResult};
4use crate::traits::{Event, EventParser, ParserInfo};
5use crate::types::{EventKind, EventMetadata, GenericEvent};
6use async_trait::async_trait;
7use regex::Regex;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct ParsingConfig {
15 pub name: String,
17 pub version: String,
19 pub format: String,
21 pub field_mappings: HashMap<String, String>,
23 pub defaults: HashMap<String, serde_json::Value>,
25 pub validation: ValidationConfig,
27}
28
29impl ParsingConfig {
30 pub fn new(name: String, version: String, format: String) -> Self {
32 Self {
33 name,
34 version,
35 format,
36 field_mappings: HashMap::new(),
37 defaults: HashMap::new(),
38 validation: ValidationConfig::default(),
39 }
40 }
41
42 pub fn with_mapping(mut self, field: String, source_path: String) -> Self {
44 self.field_mappings.insert(field, source_path);
45 self
46 }
47
48 pub fn with_default<T: Serialize>(mut self, field: String, value: T) -> Self {
50 if let Ok(json_value) = serde_json::to_value(value) {
51 self.defaults.insert(field, json_value);
52 }
53 self
54 }
55
56 pub fn with_validation(mut self, validation: ValidationConfig) -> Self {
58 self.validation = validation;
59 self
60 }
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, Default)]
65pub struct ValidationConfig {
66 pub required_fields: Vec<String>,
68 pub field_types: HashMap<String, String>,
70 pub min_values: HashMap<String, f64>,
72 pub max_values: HashMap<String, f64>,
74 pub patterns: HashMap<String, String>,
76}
77
78impl ValidationConfig {
79 pub fn with_required(mut self, field: String) -> Self {
81 self.required_fields.push(field);
82 self
83 }
84
85 pub fn with_type(mut self, field: String, type_name: String) -> Self {
87 self.field_types.insert(field, type_name);
88 self
89 }
90
91 pub fn with_range(mut self, field: String, min: f64, max: f64) -> Self {
93 self.min_values.insert(field.clone(), min);
94 self.max_values.insert(field, max);
95 self
96 }
97
98 pub fn with_pattern(mut self, field: String, pattern: String) -> Self {
100 self.patterns.insert(field, pattern);
101 self
102 }
103}
104
105pub struct JsonEventParser {
107 config: ParsingConfig,
108 event_kind: EventKind,
109 source_name: String,
110}
111
112impl JsonEventParser {
113 pub fn new(config: ParsingConfig, event_kind: EventKind, source_name: String) -> Self {
115 Self {
116 config,
117 event_kind,
118 source_name,
119 }
120 }
121
122 fn extract_field(&self, data: &serde_json::Value, path: &str) -> Option<serde_json::Value> {
124 let parts: Vec<&str> = path.split('.').collect();
125 let mut current = data;
126
127 for part in parts {
128 match current {
129 serde_json::Value::Object(obj) => {
130 current = obj.get(part)?;
131 }
132 serde_json::Value::Array(arr) => {
133 if let Ok(index) = part.parse::<usize>() {
134 current = arr.get(index)?;
135 } else {
136 return None;
137 }
138 }
139 _ => return None,
140 }
141 }
142
143 Some(current.clone())
144 }
145
146 fn apply_mappings(&self, data: &serde_json::Value) -> EventResult<serde_json::Value> {
148 let mut result = serde_json::Map::new();
149
150 for (field, source_path) in &self.config.field_mappings {
152 if let Some(value) = self.extract_field(data, source_path) {
153 result.insert(field.clone(), value);
154 }
155 }
156
157 for (field, default_value) in &self.config.defaults {
159 if !result.contains_key(field) {
160 result.insert(field.clone(), default_value.clone());
161 }
162 }
163
164 Ok(serde_json::Value::Object(result))
165 }
166
167 fn validate(&self, data: &serde_json::Value) -> EventResult<()> {
169 let obj = data.as_object().ok_or_else(|| {
170 EventError::parse_error(
171 std::io::Error::new(std::io::ErrorKind::InvalidData, "Expected object"),
172 "Data is not a JSON object",
173 )
174 })?;
175
176 self.validate_required_fields(obj)?;
177 self.validate_field_types(obj)?;
178 self.validate_numeric_ranges(obj)?;
179 self.validate_string_patterns(obj)?;
180
181 Ok(())
182 }
183
184 fn validate_required_fields(
186 &self,
187 obj: &serde_json::Map<String, serde_json::Value>,
188 ) -> EventResult<()> {
189 for required_field in &self.config.validation.required_fields {
190 if !obj.contains_key(required_field) {
191 return Err(EventError::parse_error(
192 std::io::Error::new(
193 std::io::ErrorKind::InvalidData,
194 format!("Missing required field: {}", required_field),
195 ),
196 format!("Required field '{}' is missing", required_field),
197 ));
198 }
199 }
200 Ok(())
201 }
202
203 fn validate_field_types(
205 &self,
206 obj: &serde_json::Map<String, serde_json::Value>,
207 ) -> EventResult<()> {
208 for (field, expected_type) in &self.config.validation.field_types {
209 if let Some(value) = obj.get(field) {
210 let actual_type = self.get_json_type(value);
211 if actual_type != expected_type {
212 return Err(EventError::parse_error(
213 std::io::Error::new(
214 std::io::ErrorKind::InvalidData,
215 format!(
216 "Type mismatch for field '{}': expected {}, got {}",
217 field, expected_type, actual_type
218 ),
219 ),
220 format!("Field '{}' has wrong type", field),
221 ));
222 }
223 }
224 }
225 Ok(())
226 }
227
228 fn get_json_type(&self, value: &serde_json::Value) -> &'static str {
230 match value {
231 serde_json::Value::String(_) => "string",
232 serde_json::Value::Number(_) => "number",
233 serde_json::Value::Bool(_) => "boolean",
234 serde_json::Value::Array(_) => "array",
235 serde_json::Value::Object(_) => "object",
236 serde_json::Value::Null => "null",
237 }
238 }
239
240 fn validate_numeric_ranges(
242 &self,
243 obj: &serde_json::Map<String, serde_json::Value>,
244 ) -> EventResult<()> {
245 self.validate_minimum_values(obj)?;
246 self.validate_maximum_values(obj)?;
247 Ok(())
248 }
249
250 fn validate_minimum_values(
252 &self,
253 obj: &serde_json::Map<String, serde_json::Value>,
254 ) -> EventResult<()> {
255 for (field, min_value) in &self.config.validation.min_values {
256 if let Some(value) = obj.get(field) {
257 if let Some(num) = value.as_f64() {
258 if num < *min_value {
259 return Err(EventError::parse_error(
260 std::io::Error::new(
261 std::io::ErrorKind::InvalidData,
262 format!(
263 "Value {} for field '{}' is below minimum {}",
264 num, field, min_value
265 ),
266 ),
267 format!("Field '{}' value too small", field),
268 ));
269 }
270 }
271 }
272 }
273 Ok(())
274 }
275
276 fn validate_maximum_values(
278 &self,
279 obj: &serde_json::Map<String, serde_json::Value>,
280 ) -> EventResult<()> {
281 for (field, max_value) in &self.config.validation.max_values {
282 if let Some(value) = obj.get(field) {
283 if let Some(num) = value.as_f64() {
284 if num > *max_value {
285 return Err(EventError::parse_error(
286 std::io::Error::new(
287 std::io::ErrorKind::InvalidData,
288 format!(
289 "Value {} for field '{}' is above maximum {}",
290 num, field, max_value
291 ),
292 ),
293 format!("Field '{}' value too large", field),
294 ));
295 }
296 }
297 }
298 }
299 Ok(())
300 }
301
302 fn validate_string_patterns(
304 &self,
305 obj: &serde_json::Map<String, serde_json::Value>,
306 ) -> EventResult<()> {
307 for (field, pattern) in &self.config.validation.patterns {
308 if let Some(value) = obj.get(field) {
309 if let Some(string_value) = value.as_str() {
310 self.validate_regex_pattern(field, string_value, pattern)?;
311 }
312 }
313 }
314 Ok(())
315 }
316
317 fn validate_regex_pattern(
319 &self,
320 field: &str,
321 string_value: &str,
322 pattern: &str,
323 ) -> EventResult<()> {
324 match Regex::new(pattern) {
325 Ok(regex) => {
326 if !regex.is_match(string_value) {
327 return Err(EventError::parse_error(
328 std::io::Error::new(
329 std::io::ErrorKind::InvalidData,
330 format!(
331 "String '{}' for field '{}' doesn't match pattern '{}'",
332 string_value, field, pattern
333 ),
334 ),
335 format!("Field '{}' doesn't match pattern", field),
336 ));
337 }
338 }
339 Err(regex_error) => {
340 return Err(EventError::parse_error(
341 std::io::Error::new(
342 std::io::ErrorKind::InvalidData,
343 format!(
344 "Invalid regex pattern '{}' for field '{}': {}",
345 pattern, field, regex_error
346 ),
347 ),
348 format!("Invalid regex pattern for field '{}'", field),
349 ));
350 }
351 }
352 Ok(())
353 }
354}
355
356#[async_trait]
357impl EventParser for JsonEventParser {
358 type Input = serde_json::Value;
359
360 async fn parse(&self, input: Self::Input) -> EventResult<Vec<Box<dyn Event>>> {
361 let mapped_data = self.apply_mappings(&input)?;
363
364 self.validate(&mapped_data)?;
366
367 let event_id = mapped_data
369 .get("id")
370 .and_then(|v| v.as_str())
371 .map(|s| s.to_string())
372 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
373
374 let metadata =
375 EventMetadata::new(event_id, self.event_kind.clone(), self.source_name.clone());
376
377 let event = GenericEvent::with_metadata(metadata, mapped_data);
379
380 Ok(vec![Box::new(event)])
381 }
382
383 fn can_parse(&self, input: &Self::Input) -> bool {
384 for source_path in self.config.field_mappings.values() {
386 if self.extract_field(input, source_path).is_none() {
387 return false;
388 }
389 }
390 true
391 }
392
393 fn info(&self) -> ParserInfo {
394 ParserInfo::new(self.config.name.clone(), self.config.version.clone())
395 .with_kind(self.event_kind.clone())
396 .with_format(self.config.format.clone())
397 }
398}
399
400pub struct MultiFormatParser {
402 parsers: HashMap<String, Arc<dyn EventParser<Input = Vec<u8>> + Send + Sync>>,
403 default_format: String,
404}
405
406impl MultiFormatParser {
407 pub fn new(default_format: String) -> Self {
409 Self {
410 parsers: HashMap::new(),
411 default_format,
412 }
413 }
414
415 pub fn with_parser<P>(mut self, format: String, parser: P) -> Self
417 where
418 P: EventParser<Input = Vec<u8>> + Send + Sync + 'static,
419 {
420 self.parsers.insert(format, Arc::new(parser));
421 self
422 }
423
424 fn detect_format(&self, data: &[u8]) -> String {
426 if data.starts_with(b"{") || data.starts_with(b"[") {
428 "json".to_string()
429 } else if data.starts_with(b"<") {
430 "xml".to_string()
431 } else {
432 self.default_format.clone()
433 }
434 }
435}
436
437#[async_trait]
438impl EventParser for MultiFormatParser {
439 type Input = Vec<u8>;
440
441 async fn parse(&self, input: Self::Input) -> EventResult<Vec<Box<dyn Event>>> {
442 let format = self.detect_format(&input);
443
444 if let Some(parser) = self.parsers.get(&format) {
445 parser.parse(input).await
446 } else {
447 Err(EventError::parse_error(
448 std::io::Error::new(std::io::ErrorKind::NotFound, "Parser not found"),
449 format!("No parser available for format: {}", format),
450 ))
451 }
452 }
453
454 fn can_parse(&self, input: &Self::Input) -> bool {
455 let format = self.detect_format(input);
456 self.parsers
457 .get(&format)
458 .is_some_and(|p| p.can_parse(input))
459 }
460
461 fn info(&self) -> ParserInfo {
462 ParserInfo::new("multi-format".to_string(), "1.0.0".to_string())
463 .with_format("json".to_string())
464 .with_format("xml".to_string())
465 .with_format("binary".to_string())
466 }
467}
468
469pub struct BinaryEventParser {
471 name: String,
472 version: String,
473 event_kind: EventKind,
474 source_name: String,
475}
476
477impl BinaryEventParser {
478 pub fn new(name: String, version: String, event_kind: EventKind, source_name: String) -> Self {
480 Self {
481 name,
482 version,
483 event_kind,
484 source_name,
485 }
486 }
487}
488
489#[async_trait]
490impl EventParser for BinaryEventParser {
491 type Input = Vec<u8>;
492
493 async fn parse(&self, input: Self::Input) -> EventResult<Vec<Box<dyn Event>>> {
494 let event_id = format!("binary_{}", uuid::Uuid::new_v4());
496 let metadata =
497 EventMetadata::new(event_id, self.event_kind.clone(), self.source_name.clone());
498
499 let hex_data = hex::encode(&input);
501 let data = serde_json::json!({
502 "format": "binary",
503 "hex": hex_data,
504 "length": input.len()
505 });
506
507 let event = GenericEvent::with_metadata(metadata, data);
508 Ok(vec![Box::new(event)])
509 }
510
511 fn can_parse(&self, _input: &Self::Input) -> bool {
512 true }
514
515 fn info(&self) -> ParserInfo {
516 ParserInfo::new(self.name.clone(), self.version.clone())
517 .with_kind(self.event_kind.clone())
518 .with_format("binary".to_string())
519 }
520}
521
522#[cfg(test)]
523mod tests {
524 use super::*;
525 use crate::types::EventKind;
526 use serde_json::json;
527
528 #[tokio::test]
529 async fn test_json_parser_basic() {
530 let config = ParsingConfig::new(
531 "test-parser".to_string(),
532 "1.0.0".to_string(),
533 "json".to_string(),
534 )
535 .with_mapping("amount".to_string(), "transaction.amount".to_string())
536 .with_mapping("token".to_string(), "transaction.token".to_string())
537 .with_default("fee".to_string(), 0.01);
538
539 let parser =
540 JsonEventParser::new(config, EventKind::Transaction, "test-source".to_string());
541
542 let input = json!({
543 "transaction": {
544 "amount": 100,
545 "token": "USDC"
546 }
547 });
548
549 let events = parser.parse(input).await.unwrap();
550 assert_eq!(events.len(), 1);
551
552 let event = &events[0];
553 assert_eq!(event.kind(), &EventKind::Transaction);
554 assert_eq!(event.source(), "test-source");
555 }
556
557 #[tokio::test]
558 async fn test_json_parser_validation() {
559 let config = ParsingConfig::new(
560 "test-parser".to_string(),
561 "1.0.0".to_string(),
562 "json".to_string(),
563 )
564 .with_mapping("amount".to_string(), "amount".to_string())
565 .with_validation(
566 ValidationConfig::default()
567 .with_required("amount".to_string())
568 .with_range("amount".to_string(), 0.0, 1000.0),
569 );
570
571 let parser =
572 JsonEventParser::new(config, EventKind::Transaction, "test-source".to_string());
573
574 let input = json!({"other": "value"});
576 let result = parser.parse(input).await;
577 assert!(result.is_err());
578
579 let input = json!({"amount": 100});
581 let result = parser.parse(input).await;
582 assert!(result.is_ok());
583
584 let input = json!({"amount": 2000});
586 let result = parser.parse(input).await;
587 assert!(result.is_err());
588 }
589
590 #[tokio::test]
591 async fn test_binary_parser() {
592 let parser = BinaryEventParser::new(
593 "binary-parser".to_string(),
594 "1.0.0".to_string(),
595 EventKind::Contract,
596 "binary-source".to_string(),
597 );
598
599 let input = vec![0x01, 0x02, 0x03, 0x04];
600 let events = parser.parse(input.clone()).await.unwrap();
601
602 assert_eq!(events.len(), 1);
603 let event = &events[0];
604 assert_eq!(event.kind(), &EventKind::Contract);
605 assert_eq!(event.source(), "binary-source");
606 }
607
608 #[test]
609 fn test_parsing_config_builder() {
610 let config =
611 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
612 .with_mapping("field1".to_string(), "source.field1".to_string())
613 .with_default("field2".to_string(), "default_value")
614 .with_validation(
615 ValidationConfig::default()
616 .with_required("field1".to_string())
617 .with_type("field1".to_string(), "string".to_string()),
618 );
619
620 assert_eq!(config.field_mappings.len(), 1);
621 assert_eq!(config.defaults.len(), 1);
622 assert_eq!(config.validation.required_fields.len(), 1);
623 assert_eq!(config.validation.field_types.len(), 1);
624 }
625
626 #[test]
627 fn test_validation_config_builder() {
628 let validation = ValidationConfig::default()
629 .with_required("amount".to_string())
630 .with_type("amount".to_string(), "number".to_string())
631 .with_range("amount".to_string(), 0.0, 1000.0)
632 .with_pattern("token".to_string(), "^[A-Z]+$".to_string());
633
634 assert_eq!(validation.required_fields.len(), 1);
635 assert_eq!(validation.field_types.len(), 1);
636 assert_eq!(validation.min_values.len(), 1);
637 assert_eq!(validation.max_values.len(), 1);
638 assert_eq!(validation.patterns.len(), 1);
639 }
640
641 #[test]
644 fn test_parsing_config_with_default_serialization_error() {
645 let config =
647 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
648 let config = config.with_default("field".to_string(), "valid_string");
651 assert_eq!(config.defaults.len(), 1);
652 }
653
654 #[test]
655 fn test_json_parser_extract_field_nested_object() {
656 let config =
657 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
658 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
659
660 let data = json!({
661 "level1": {
662 "level2": {
663 "value": "found"
664 }
665 }
666 });
667
668 let result = parser.extract_field(&data, "level1.level2.value");
669 assert_eq!(result, Some(json!("found")));
670 }
671
672 #[test]
673 fn test_json_parser_extract_field_array_access() {
674 let config =
675 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
676 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
677
678 let data = json!({
679 "items": [
680 {"name": "first"},
681 {"name": "second"}
682 ]
683 });
684
685 let result = parser.extract_field(&data, "items.0.name");
686 assert_eq!(result, Some(json!("first")));
687
688 let result = parser.extract_field(&data, "items.1.name");
689 assert_eq!(result, Some(json!("second")));
690 }
691
692 #[test]
693 fn test_json_parser_extract_field_array_invalid_index() {
694 let config =
695 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
696 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
697
698 let data = json!({
699 "items": [{"name": "first"}]
700 });
701
702 let result = parser.extract_field(&data, "items.5.name");
704 assert_eq!(result, None);
705
706 let result = parser.extract_field(&data, "items.invalid.name");
708 assert_eq!(result, None);
709 }
710
711 #[test]
712 fn test_json_parser_extract_field_invalid_path() {
713 let config =
714 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
715 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
716
717 let data = json!({
718 "value": "string"
719 });
720
721 let result = parser.extract_field(&data, "value.nonexistent");
723 assert_eq!(result, None);
724
725 let result = parser.extract_field(&data, "nonexistent.path");
727 assert_eq!(result, None);
728 }
729
730 #[test]
731 fn test_json_parser_extract_field_empty_path() {
732 let config =
733 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
734 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
735
736 let data = json!({"key": "value"});
737
738 let result = parser.extract_field(&data, "key");
740 assert_eq!(result, Some(json!("value")));
741 }
742
743 #[tokio::test]
744 async fn test_json_parser_validation_missing_required() {
745 let config =
746 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
747 .with_validation(
748 ValidationConfig::default().with_required("required_field".to_string()),
749 );
750
751 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
752 let input = json!({"other_field": "value"});
753
754 let result = parser.parse(input).await;
755 assert!(result.is_err());
756
757 if let Err(EventError::ParseError { context, .. }) = result {
758 assert!(context.contains("Required field 'required_field' is missing"));
759 } else {
760 panic!("Expected ParseError");
761 }
762 }
763
764 #[tokio::test]
765 async fn test_json_parser_validation_type_mismatch() {
766 let config =
767 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
768 .with_mapping("field".to_string(), "field".to_string())
769 .with_validation(
770 ValidationConfig::default()
771 .with_type("field".to_string(), "string".to_string()),
772 );
773
774 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
775 let input = json!({"field": 123}); let result = parser.parse(input).await;
778 assert!(result.is_err());
779
780 if let Err(EventError::ParseError { context, .. }) = result {
781 assert!(context.contains("Field 'field' has wrong type"));
782 } else {
783 panic!("Expected ParseError");
784 }
785 }
786
787 #[tokio::test]
788 async fn test_json_parser_validation_all_types() {
789 let config =
790 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
791 .with_mapping("str_field".to_string(), "str_field".to_string())
792 .with_mapping("num_field".to_string(), "num_field".to_string())
793 .with_mapping("bool_field".to_string(), "bool_field".to_string())
794 .with_mapping("arr_field".to_string(), "arr_field".to_string())
795 .with_mapping("obj_field".to_string(), "obj_field".to_string())
796 .with_mapping("null_field".to_string(), "null_field".to_string())
797 .with_validation(
798 ValidationConfig::default()
799 .with_type("str_field".to_string(), "string".to_string())
800 .with_type("num_field".to_string(), "number".to_string())
801 .with_type("bool_field".to_string(), "boolean".to_string())
802 .with_type("arr_field".to_string(), "array".to_string())
803 .with_type("obj_field".to_string(), "object".to_string())
804 .with_type("null_field".to_string(), "null".to_string()),
805 );
806
807 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
808 let input = json!({
809 "str_field": "string",
810 "num_field": 123,
811 "bool_field": true,
812 "arr_field": [1, 2, 3],
813 "obj_field": {"key": "value"},
814 "null_field": null
815 });
816
817 let result = parser.parse(input).await;
818 assert!(result.is_ok());
819 }
820
821 #[tokio::test]
822 async fn test_json_parser_validation_numeric_range_below_min() {
823 let config =
824 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
825 .with_mapping("amount".to_string(), "amount".to_string())
826 .with_validation(ValidationConfig::default().with_range(
827 "amount".to_string(),
828 10.0,
829 100.0,
830 ));
831
832 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
833 let input = json!({"amount": 5.0});
834
835 let result = parser.parse(input).await;
836 assert!(result.is_err());
837
838 if let Err(EventError::ParseError { context, .. }) = result {
839 assert!(context.contains("Field 'amount' value too small"));
840 } else {
841 panic!("Expected ParseError");
842 }
843 }
844
845 #[tokio::test]
846 async fn test_json_parser_validation_numeric_range_above_max() {
847 let config =
848 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
849 .with_mapping("amount".to_string(), "amount".to_string())
850 .with_validation(ValidationConfig::default().with_range(
851 "amount".to_string(),
852 10.0,
853 100.0,
854 ));
855
856 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
857 let input = json!({"amount": 150.0});
858
859 let result = parser.parse(input).await;
860 assert!(result.is_err());
861
862 if let Err(EventError::ParseError { context, .. }) = result {
863 assert!(context.contains("Field 'amount' value too large"));
864 } else {
865 panic!("Expected ParseError");
866 }
867 }
868
869 #[tokio::test]
870 async fn test_json_parser_validation_string_pattern_mismatch() {
871 let config =
872 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
873 .with_mapping("token".to_string(), "token".to_string())
874 .with_validation(
875 ValidationConfig::default()
876 .with_pattern("token".to_string(), "^USD[C|T]$".to_string()),
877 );
878
879 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
880 let input = json!({"token": "BTC"});
881
882 let result = parser.parse(input).await;
883 assert!(result.is_err());
884
885 if let Err(EventError::ParseError { context, .. }) = result {
886 assert!(context.contains("Field 'token' doesn't match pattern"));
887 } else {
888 panic!("Expected ParseError");
889 }
890 }
891
892 #[tokio::test]
893 async fn test_json_parser_validation_string_pattern_match() {
894 let config =
895 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
896 .with_mapping("token".to_string(), "token".to_string())
897 .with_validation(
898 ValidationConfig::default()
899 .with_pattern("token".to_string(), "^USD[C|T]$".to_string()),
900 );
901
902 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
903 let input = json!({"token": "USDC"});
904
905 let result = parser.parse(input).await;
906 assert!(result.is_ok());
907 }
908
909 #[tokio::test]
910 async fn test_json_parser_validation_invalid_regex_pattern() {
911 let config =
912 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
913 .with_mapping("token".to_string(), "token".to_string())
914 .with_validation(
915 ValidationConfig::default()
916 .with_pattern("token".to_string(), "[invalid".to_string()),
917 );
918
919 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
920 let input = json!({"token": "USDC"});
921
922 let result = parser.parse(input).await;
923 assert!(result.is_err());
924
925 if let Err(EventError::ParseError { context, .. }) = result {
926 assert!(context.contains("Invalid regex pattern for field 'token'"));
927 } else {
928 panic!("Expected ParseError");
929 }
930 }
931
932 #[tokio::test]
933 async fn test_json_parser_validation_non_object_input() {
934 let config =
935 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
936 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
937
938 let input = json!("not an object");
939 let result = parser.parse(input).await;
940 assert!(result.is_err());
941
942 if let Err(EventError::ParseError { context, .. }) = result {
943 assert!(context.contains("Data is not a JSON object"));
944 } else {
945 panic!("Expected ParseError");
946 }
947 }
948
949 #[tokio::test]
950 async fn test_json_parser_with_custom_id() {
951 let config =
952 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
953 .with_mapping("id".to_string(), "custom_id".to_string());
954
955 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
956 let input = json!({"custom_id": "my-custom-id"});
957
958 let events = parser.parse(input).await.unwrap();
959 assert_eq!(events.len(), 1);
960 assert_eq!(events[0].id(), "my-custom-id");
961 }
962
963 #[test]
964 fn test_json_parser_can_parse_valid() {
965 let config =
966 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
967 .with_mapping("field".to_string(), "nested.field".to_string());
968
969 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
970 let input = json!({"nested": {"field": "value"}});
971
972 assert!(parser.can_parse(&input));
973 }
974
975 #[test]
976 fn test_json_parser_can_parse_invalid() {
977 let config =
978 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
979 .with_mapping("field".to_string(), "nested.field".to_string());
980
981 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
982 let input = json!({"other": "value"});
983
984 assert!(!parser.can_parse(&input));
985 }
986
987 #[test]
988 fn test_json_parser_can_parse_empty_mappings() {
989 let config =
990 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string());
991 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
992 let input = json!({"any": "value"});
993
994 assert!(parser.can_parse(&input)); }
996
997 #[test]
998 fn test_json_parser_info() {
999 let config = ParsingConfig::new(
1000 "test-parser".to_string(),
1001 "2.0.0".to_string(),
1002 "json".to_string(),
1003 );
1004 let parser = JsonEventParser::new(config, EventKind::Contract, "test".to_string());
1005
1006 let info = parser.info();
1007 assert_eq!(info.name, "test-parser");
1008 assert_eq!(info.version, "2.0.0");
1009 assert!(info.supported_kinds.contains(&EventKind::Contract));
1010 assert!(info.supported_formats.contains(&"json".to_string()));
1011 }
1012
1013 #[test]
1014 fn test_multi_format_parser_new() {
1015 let parser = MultiFormatParser::new("binary".to_string());
1016 assert_eq!(parser.default_format, "binary");
1017 assert_eq!(parser.parsers.len(), 0);
1018 }
1019
1020 #[test]
1021 fn test_multi_format_parser_detect_format_json() {
1022 let parser = MultiFormatParser::new("binary".to_string());
1023
1024 assert_eq!(parser.detect_format(b"{\"key\": \"value\"}"), "json");
1025 assert_eq!(parser.detect_format(b"[1, 2, 3]"), "json");
1026 }
1027
1028 #[test]
1029 fn test_multi_format_parser_detect_format_xml() {
1030 let parser = MultiFormatParser::new("binary".to_string());
1031
1032 assert_eq!(parser.detect_format(b"<xml>content</xml>"), "xml");
1033 }
1034
1035 #[test]
1036 fn test_multi_format_parser_detect_format_default() {
1037 let parser = MultiFormatParser::new("custom".to_string());
1038
1039 assert_eq!(parser.detect_format(b"random binary data"), "custom");
1040 }
1041
1042 #[tokio::test]
1043 async fn test_multi_format_parser_parse_no_parser() {
1044 let parser = MultiFormatParser::new("unknown".to_string());
1045 let input = b"some data".to_vec();
1046
1047 let result = parser.parse(input).await;
1048 assert!(result.is_err());
1049
1050 if let Err(EventError::ParseError { context, .. }) = result {
1051 assert!(context.contains("No parser available for format: unknown"));
1052 } else {
1053 panic!("Expected ParseError");
1054 }
1055 }
1056
1057 #[test]
1058 fn test_multi_format_parser_can_parse_no_parser() {
1059 let parser = MultiFormatParser::new("unknown".to_string());
1060 let input = b"some data".to_vec();
1061
1062 assert!(!parser.can_parse(&input));
1063 }
1064
1065 #[test]
1066 fn test_multi_format_parser_info() {
1067 let parser = MultiFormatParser::new("default".to_string());
1068 let info = parser.info();
1069
1070 assert_eq!(info.name, "multi-format");
1071 assert_eq!(info.version, "1.0.0");
1072 assert!(!info.supported_formats.is_empty());
1074 }
1075
1076 #[test]
1077 fn test_binary_parser_new() {
1078 let parser = BinaryEventParser::new(
1079 "bin-parser".to_string(),
1080 "1.5.0".to_string(),
1081 EventKind::Contract,
1082 "bin-source".to_string(),
1083 );
1084
1085 assert_eq!(parser.name, "bin-parser");
1086 assert_eq!(parser.version, "1.5.0");
1087 assert_eq!(parser.event_kind, EventKind::Contract);
1088 assert_eq!(parser.source_name, "bin-source");
1089 }
1090
1091 #[tokio::test]
1092 async fn test_binary_parser_parse_empty() {
1093 let parser = BinaryEventParser::new(
1094 "test".to_string(),
1095 "1.0.0".to_string(),
1096 EventKind::Transaction,
1097 "test".to_string(),
1098 );
1099
1100 let input = vec![];
1101 let events = parser.parse(input).await.unwrap();
1102
1103 assert_eq!(events.len(), 1);
1104 let event = &events[0];
1105 assert_eq!(event.kind(), &EventKind::Transaction);
1106 assert_eq!(event.source(), "test");
1107
1108 let generic_event = event
1110 .as_any()
1111 .downcast_ref::<crate::types::GenericEvent>()
1112 .unwrap();
1113 assert_eq!(generic_event.data["format"], "binary");
1114 assert_eq!(generic_event.data["hex"], "");
1115 assert_eq!(generic_event.data["length"], 0);
1116 }
1117
1118 #[tokio::test]
1119 async fn test_binary_parser_parse_with_data() {
1120 let parser = BinaryEventParser::new(
1121 "test".to_string(),
1122 "1.0.0".to_string(),
1123 EventKind::Transaction,
1124 "test".to_string(),
1125 );
1126
1127 let input = vec![0xde, 0xad, 0xbe, 0xef];
1128 let events = parser.parse(input.clone()).await.unwrap();
1129
1130 assert_eq!(events.len(), 1);
1131 let event = &events[0];
1132
1133 let generic_event = event
1134 .as_any()
1135 .downcast_ref::<crate::types::GenericEvent>()
1136 .unwrap();
1137 assert_eq!(generic_event.data["format"], "binary");
1138 assert_eq!(generic_event.data["hex"], "deadbeef");
1139 assert_eq!(generic_event.data["length"], 4);
1140 assert_eq!(
1141 generic_event.data["raw"],
1142 serde_json::Value::Array(vec![
1143 serde_json::Value::Number(serde_json::Number::from(0xde)),
1144 serde_json::Value::Number(serde_json::Number::from(0xad)),
1145 serde_json::Value::Number(serde_json::Number::from(0xbe)),
1146 serde_json::Value::Number(serde_json::Number::from(0xef)),
1147 ])
1148 );
1149 }
1150
1151 #[test]
1152 fn test_binary_parser_can_parse() {
1153 let parser = BinaryEventParser::new(
1154 "test".to_string(),
1155 "1.0.0".to_string(),
1156 EventKind::Transaction,
1157 "test".to_string(),
1158 );
1159
1160 assert!(parser.can_parse(&vec![]));
1161 assert!(parser.can_parse(&vec![1, 2, 3]));
1162 assert!(parser.can_parse(&vec![0; 1000]));
1163 }
1164
1165 #[test]
1166 fn test_binary_parser_info() {
1167 let parser = BinaryEventParser::new(
1168 "binary-test".to_string(),
1169 "2.1.0".to_string(),
1170 EventKind::External,
1171 "test".to_string(),
1172 );
1173
1174 let info = parser.info();
1175 assert_eq!(info.name, "binary-test");
1176 assert_eq!(info.version, "2.1.0");
1177 assert!(info.supported_kinds.contains(&EventKind::External));
1178 assert!(info.supported_formats.contains(&"binary".to_string()));
1179 }
1180
1181 #[test]
1182 fn test_validation_config_default() {
1183 let validation = ValidationConfig::default();
1184
1185 assert!(validation.required_fields.is_empty());
1186 assert!(validation.field_types.is_empty());
1187 assert!(validation.min_values.is_empty());
1188 assert!(validation.max_values.is_empty());
1189 assert!(validation.patterns.is_empty());
1190 }
1191
1192 #[test]
1193 fn test_validation_config_multiple_required() {
1194 let validation = ValidationConfig::default()
1195 .with_required("field1".to_string())
1196 .with_required("field2".to_string());
1197
1198 assert_eq!(validation.required_fields.len(), 2);
1199 assert!(validation.required_fields.contains(&"field1".to_string()));
1200 assert!(validation.required_fields.contains(&"field2".to_string()));
1201 }
1202
1203 #[test]
1204 fn test_validation_config_multiple_types() {
1205 let validation = ValidationConfig::default()
1206 .with_type("field1".to_string(), "string".to_string())
1207 .with_type("field2".to_string(), "number".to_string());
1208
1209 assert_eq!(validation.field_types.len(), 2);
1210 assert_eq!(
1211 validation.field_types.get("field1"),
1212 Some(&"string".to_string())
1213 );
1214 assert_eq!(
1215 validation.field_types.get("field2"),
1216 Some(&"number".to_string())
1217 );
1218 }
1219
1220 #[test]
1221 fn test_validation_config_range_sets_both_min_max() {
1222 let validation = ValidationConfig::default().with_range("amount".to_string(), 5.0, 10.0);
1223
1224 assert_eq!(validation.min_values.get("amount"), Some(&5.0));
1225 assert_eq!(validation.max_values.get("amount"), Some(&10.0));
1226 }
1227
1228 #[tokio::test]
1229 async fn test_json_parser_validation_non_numeric_range_field() {
1230 let config =
1231 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
1232 .with_mapping("field".to_string(), "field".to_string())
1233 .with_validation(ValidationConfig::default().with_range(
1234 "field".to_string(),
1235 0.0,
1236 100.0,
1237 ));
1238
1239 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
1240 let input = json!({"field": "not a number"});
1241
1242 let result = parser.parse(input).await;
1244 assert!(result.is_ok());
1245 }
1246
1247 #[tokio::test]
1248 async fn test_json_parser_validation_non_string_pattern_field() {
1249 let config =
1250 ParsingConfig::new("test".to_string(), "1.0.0".to_string(), "json".to_string())
1251 .with_mapping("field".to_string(), "field".to_string())
1252 .with_validation(
1253 ValidationConfig::default()
1254 .with_pattern("field".to_string(), "pattern".to_string()),
1255 );
1256
1257 let parser = JsonEventParser::new(config, EventKind::Transaction, "test".to_string());
1258 let input = json!({"field": 123});
1259
1260 let result = parser.parse(input).await;
1262 assert!(result.is_ok());
1263 }
1264
1265 #[tokio::test]
1266 async fn test_multi_format_parser_with_parser() {
1267 let binary_parser = BinaryEventParser::new(
1268 "test-binary".to_string(),
1269 "1.0.0".to_string(),
1270 EventKind::Transaction,
1271 "test".to_string(),
1272 );
1273
1274 let multi_parser = MultiFormatParser::new("default".to_string())
1275 .with_parser("binary".to_string(), binary_parser);
1276
1277 let input = b"random binary data".to_vec(); let result = multi_parser.parse(input).await;
1280
1281 assert!(result.is_err());
1283
1284 let json_input = b"{\"test\": \"data\"}".to_vec();
1286 let result = multi_parser.parse(json_input).await;
1287 assert!(result.is_err());
1289 }
1290
1291 #[tokio::test]
1292 async fn test_multi_format_parser_with_json_format() {
1293 let binary_parser = BinaryEventParser::new(
1294 "test-binary".to_string(),
1295 "1.0.0".to_string(),
1296 EventKind::Transaction,
1297 "test".to_string(),
1298 );
1299
1300 let multi_parser = MultiFormatParser::new("binary".to_string())
1301 .with_parser("binary".to_string(), binary_parser);
1302
1303 let json_input = b"{\"test\": \"data\"}".to_vec();
1305 let result = multi_parser.parse(json_input).await;
1306 assert!(result.is_err());
1307
1308 let binary_input = b"some binary data".to_vec();
1310 let result = multi_parser.parse(binary_input).await;
1311 assert!(result.is_ok());
1312
1313 let events = result.unwrap();
1314 assert_eq!(events.len(), 1);
1315 }
1316
1317 #[test]
1318 fn test_multi_format_parser_can_parse_with_registered_parser() {
1319 let binary_parser = BinaryEventParser::new(
1320 "test-binary".to_string(),
1321 "1.0.0".to_string(),
1322 EventKind::Transaction,
1323 "test".to_string(),
1324 );
1325
1326 let multi_parser = MultiFormatParser::new("binary".to_string())
1327 .with_parser("binary".to_string(), binary_parser);
1328
1329 let input = b"random data".to_vec();
1331 assert!(multi_parser.can_parse(&input));
1332
1333 let json_input = b"{\"test\": \"data\"}".to_vec();
1335 assert!(!multi_parser.can_parse(&json_input));
1336 }
1337}