camel_component_validator/
config.rs1use std::path::{Path, PathBuf};
2
3use camel_component_api::CamelError;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum SchemaType {
7 Xml,
8 Json,
9 Yaml,
10}
11
12#[derive(Debug, Clone)]
13pub struct ValidatorConfig {
14 pub schema_path: PathBuf,
15 pub schema_type: SchemaType,
16}
17
18impl ValidatorConfig {
19 pub fn from_uri(uri: &str) -> Result<Self, CamelError> {
20 let without_scheme = uri.strip_prefix("validator:").ok_or_else(|| {
21 CamelError::EndpointCreationFailed(format!(
22 "invalid validator URI: must start with 'validator:' — got '{uri}'"
23 ))
24 })?;
25
26 let (path_str, query) = match without_scheme.find('?') {
27 Some(idx) => (&without_scheme[..idx], Some(&without_scheme[idx + 1..])),
28 None => (without_scheme, None),
29 };
30
31 if path_str.is_empty() {
32 return Err(CamelError::EndpointCreationFailed(
33 "validator URI must specify a schema path".to_string(),
34 ));
35 }
36
37 let schema_path = PathBuf::from(path_str);
38
39 let schema_type = if let Some(q) = query {
40 let type_val = q.split('&').find_map(|kv| kv.strip_prefix("type="));
41 match type_val {
42 Some("xml") | Some("xml-schema") | Some("xsd") => SchemaType::Xml,
43 Some("json") | Some("json-schema") => SchemaType::Json,
44 Some("yaml") | Some("yaml-schema") => SchemaType::Yaml,
45 Some(other) => {
46 return Err(CamelError::EndpointCreationFailed(format!(
47 "unknown schema type '{other}'; expected xml, json, or yaml"
48 )));
49 }
50 None => detect_type_from_extension(&schema_path)?,
51 }
52 } else {
53 detect_type_from_extension(&schema_path)?
54 };
55
56 Ok(ValidatorConfig {
57 schema_path,
58 schema_type,
59 })
60 }
61}
62
63fn detect_type_from_extension(path: &Path) -> Result<SchemaType, CamelError> {
64 match path.extension().and_then(|e| e.to_str()) {
65 Some("xsd") => Ok(SchemaType::Xml),
66 Some("json") => Ok(SchemaType::Json),
67 Some("yaml") | Some("yml") => Ok(SchemaType::Yaml),
68 ext => Err(CamelError::EndpointCreationFailed(format!(
69 "cannot infer schema type from extension {ext:?}; use ?type=xml|json|yaml"
70 ))),
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn detects_xml_from_xsd_extension() {
80 let cfg = ValidatorConfig::from_uri("validator:schemas/order.xsd").unwrap();
81 assert_eq!(cfg.schema_path, PathBuf::from("schemas/order.xsd"));
82 assert_eq!(cfg.schema_type, SchemaType::Xml);
83 }
84
85 #[test]
86 fn detects_json_from_json_extension() {
87 let cfg = ValidatorConfig::from_uri("validator:schemas/order.json").unwrap();
88 assert_eq!(cfg.schema_type, SchemaType::Json);
89 }
90
91 #[test]
92 fn detects_yaml_from_yaml_extension() {
93 let cfg = ValidatorConfig::from_uri("validator:schemas/order.yaml").unwrap();
94 assert_eq!(cfg.schema_type, SchemaType::Yaml);
95 }
96
97 #[test]
98 fn detects_yaml_from_yml_extension() {
99 let cfg = ValidatorConfig::from_uri("validator:schemas/order.yml").unwrap();
100 assert_eq!(cfg.schema_type, SchemaType::Yaml);
101 }
102
103 #[test]
104 fn type_param_overrides_extension() {
105 let cfg = ValidatorConfig::from_uri("validator:schemas/order.xsd?type=json").unwrap();
106 assert_eq!(cfg.schema_type, SchemaType::Json);
107 }
108
109 #[test]
110 fn wrong_scheme_errors() {
111 assert!(ValidatorConfig::from_uri("timer:tick").is_err());
112 }
113
114 #[test]
115 fn empty_path_errors() {
116 assert!(ValidatorConfig::from_uri("validator:").is_err());
117 }
118
119 #[test]
120 fn unknown_type_param_errors() {
121 assert!(ValidatorConfig::from_uri("validator:schema.xsd?type=csv").is_err());
122 }
123
124 #[test]
125 fn no_extension_no_type_param_errors() {
126 assert!(ValidatorConfig::from_uri("validator:schema").is_err());
127 }
128}