camel_processor/data_format/
mod.rs1mod csv;
2mod json;
3mod xml;
4mod zip;
5
6pub use csv::{CAMEL_CSV_HEADER_RECORD, CsvConfig, CsvDataFormat, QuoteMode, RecordSeparator};
7pub use json::{JsonConfig, JsonDataFormat};
8pub use xml::{XmlConfig, XmlDataFormat};
9pub use zip::{ZipConfig, ZipDataFormat};
10
11use camel_api::DataFormat;
12use camel_api::error::CamelError;
13use std::sync::Arc;
14
15pub fn builtin_data_format_with_config(
19 name: &str,
20 config: &serde_json::Value,
21) -> Result<Option<Arc<dyn DataFormat>>, CamelError> {
22 let df: Arc<dyn DataFormat> = match name {
23 "json" => Arc::new(JsonDataFormat::new(parse_cfg::<JsonConfig>(name, config)?)),
24 "csv" => Arc::new(CsvDataFormat::new(parse_cfg::<CsvConfig>(name, config)?)),
25 "xml" => Arc::new(XmlDataFormat::new(parse_cfg::<XmlConfig>(name, config)?)),
26 "zip" => Arc::new(ZipDataFormat::new(parse_cfg::<ZipConfig>(name, config)?)),
27 _ => return Ok(None),
28 };
29 Ok(Some(df))
30}
31
32pub fn builtin_data_format(name: &str) -> Option<Arc<dyn DataFormat>> {
34 builtin_data_format_with_config(name, &serde_json::Value::Null)
35 .ok()
36 .flatten()
37}
38
39fn parse_cfg<T>(name: &str, v: &serde_json::Value) -> Result<T, CamelError>
40where
41 T: serde::de::DeserializeOwned + Default,
42{
43 if v.is_null() {
44 return Ok(T::default());
45 }
46 serde_json::from_value::<T>(v.clone()).map_err(|e| {
47 CamelError::RouteError(format!("invalid config for data format '{name}': {e}"))
48 })
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_builtin_json() {
57 let df = builtin_data_format("json").unwrap();
58 assert_eq!(df.name(), "json");
59 }
60
61 #[test]
62 fn test_builtin_xml() {
63 let df = builtin_data_format("xml").unwrap();
64 assert_eq!(df.name(), "xml");
65 }
66
67 #[test]
68 fn test_builtin_csv() {
69 let csv_df = builtin_data_format("csv").unwrap();
70 assert_eq!(csv_df.name(), "csv");
71 }
72
73 #[test]
74 fn test_builtin_unknown_returns_none() {
75 assert!(builtin_data_format("protobuf").is_none());
76 assert!(builtin_data_format("").is_none());
77 }
78
79 #[test]
80 fn test_builtin_json_with_config() {
81 let config = serde_json::json!({"max_bytes": 67108864});
82 let df = builtin_data_format_with_config("json", &config)
83 .unwrap()
84 .unwrap();
85 assert_eq!(df.name(), "json");
86 }
87
88 #[test]
89 fn test_builtin_json_with_null_config_returns_default() {
90 let df = builtin_data_format_with_config("json", &serde_json::Value::Null)
91 .unwrap()
92 .unwrap();
93 assert_eq!(df.name(), "json");
94 }
95
96 #[test]
97 fn test_builtin_json_with_unknown_key_fails() {
98 let config = serde_json::json!({"max_byte": 100});
99 let result = builtin_data_format_with_config("json", &config);
100 match result {
101 Err(CamelError::RouteError(msg)) => {
102 assert!(msg.contains("invalid config"), "msg: {msg}");
103 }
104 Err(other) => panic!("expected RouteError, got: {other:?}"),
105 Ok(_) => panic!("typo should fail closed"),
106 }
107 }
108
109 #[test]
110 fn test_builtin_shim_still_works() {
111 let df = builtin_data_format("json").unwrap();
112 assert_eq!(df.name(), "json");
113 }
114}