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