camel_language_api/
lib.rs1pub mod error;
9pub mod language_limits;
10
11pub use async_trait::async_trait;
12pub use camel_api::Value;
13pub use camel_api::body::Body;
14pub use camel_api::exchange::Exchange;
15pub use camel_api::message::Message;
16pub use error::LanguageError;
17pub use language_limits::{
18 JsEngineConfig, JsLimitsConfig, LanguagesConfig, MinijinjaEngineConfig, MinijinjaLimitsConfig,
19 RhaiEngineConfig, RhaiLimitsConfig,
20};
21
22pub trait Language: Send + Sync {
24 fn name(&self) -> &'static str;
25 fn create_expression(&self, script: &str) -> Result<Box<dyn Expression>, LanguageError>;
26 fn create_predicate(&self, script: &str) -> Result<Box<dyn Predicate>, LanguageError>;
27
28 fn create_mutating_expression(
30 &self,
31 _script: &str,
32 ) -> Result<Box<dyn MutatingExpression>, LanguageError> {
33 Err(LanguageError::NotSupported {
34 feature: "mutating expressions".into(),
35 language: self.name().into(),
36 })
37 }
38
39 fn create_mutating_predicate(
41 &self,
42 _script: &str,
43 ) -> Result<Box<dyn MutatingPredicate>, LanguageError> {
44 Err(LanguageError::NotSupported {
45 feature: "mutating predicates".into(),
46 language: self.name().into(),
47 })
48 }
49}
50
51#[async_trait]
53pub trait Expression: Send + Sync {
54 async fn evaluate(&self, exchange: &Exchange) -> Result<Value, LanguageError>;
55}
56
57#[async_trait]
60pub trait MutatingExpression: Send + Sync {
61 async fn evaluate(&self, exchange: &mut Exchange) -> Result<Value, LanguageError>;
62}
63
64#[async_trait]
66pub trait Predicate: Send + Sync {
67 async fn matches(&self, exchange: &Exchange) -> Result<bool, LanguageError>;
68}
69
70#[async_trait]
75pub trait MutatingPredicate: Send + Sync {
76 async fn matches(&self, exchange: &mut Exchange) -> Result<bool, LanguageError>;
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 struct MockLanguage;
85
86 impl Language for MockLanguage {
87 fn name(&self) -> &'static str {
88 "mock"
89 }
90
91 fn create_expression(&self, _script: &str) -> Result<Box<dyn Expression>, LanguageError> {
92 Ok(Box::new(MockExpression))
93 }
94
95 fn create_predicate(&self, _script: &str) -> Result<Box<dyn Predicate>, LanguageError> {
96 Ok(Box::new(MockPredicate))
97 }
98 }
99
100 struct MockExpression;
101
102 #[async_trait]
103 impl Expression for MockExpression {
104 async fn evaluate(&self, _exchange: &Exchange) -> Result<Value, LanguageError> {
105 Ok(Value::String("mock".into()))
106 }
107 }
108
109 struct MockPredicate;
110
111 #[async_trait]
112 impl Predicate for MockPredicate {
113 async fn matches(&self, _exchange: &Exchange) -> Result<bool, LanguageError> {
114 Ok(true)
115 }
116 }
117
118 #[test]
119 fn mock_language_returns_name() {
120 let lang = MockLanguage;
121 assert_eq!(lang.name(), "mock");
122 }
123
124 #[tokio::test]
125 async fn mock_language_creates_expression_and_evaluates() {
126 let lang = MockLanguage;
127 let expr = lang.create_expression("any").unwrap();
128 let ex = Exchange::new(Message::default());
129 let result = expr.evaluate(&ex).await.unwrap();
130 assert_eq!(result.as_str().unwrap(), "mock");
131 }
132
133 #[tokio::test]
134 async fn mock_language_creates_predicate_and_matches() {
135 let lang = MockLanguage;
136 let pred = lang.create_predicate("any").unwrap();
137 let ex = Exchange::new(Message::default());
138 assert!(pred.matches(&ex).await.unwrap());
139 }
140
141 #[test]
142 fn default_mutating_expression_returns_not_supported() {
143 let lang = MockLanguage;
144 let result = lang.create_mutating_expression("any");
145 assert!(matches!(result, Err(LanguageError::NotSupported { .. })));
146 if let Err(LanguageError::NotSupported { feature, language }) = result {
147 assert_eq!(feature, "mutating expressions");
148 assert_eq!(language, "mock");
149 }
150 }
151
152 #[test]
153 fn default_mutating_predicate_returns_not_supported() {
154 let lang = MockLanguage;
155 let result = lang.create_mutating_predicate("any");
156 assert!(matches!(result, Err(LanguageError::NotSupported { .. })));
157 }
158
159 #[test]
160 fn language_trait_is_send_sync() {
161 fn assert_send_sync<T: Send + Sync>() {}
162 assert_send_sync::<MockLanguage>();
163 }
164}