1use crate::domain::{FieldType, PlanningAnnotation};
2use crate::{FunctionHandle, ObjectHandle, SolverForgeResult, Value};
3
4pub trait LanguageBridge: Send + Sync {
5 fn call_function(&self, func: FunctionHandle, args: &[Value]) -> SolverForgeResult<Value>;
6
7 fn get_field(&self, obj: ObjectHandle, field: &str) -> SolverForgeResult<Value>;
8
9 fn set_field(&self, obj: ObjectHandle, field: &str, value: Value) -> SolverForgeResult<()>;
10
11 fn serialize_object(&self, obj: ObjectHandle) -> SolverForgeResult<String>;
12
13 fn deserialize_object(&self, json: &str, class_name: &str) -> SolverForgeResult<ObjectHandle>;
14
15 fn get_class_info(&self, obj: ObjectHandle) -> SolverForgeResult<ClassInfo>;
16
17 fn register_function(&self, func: ObjectHandle) -> SolverForgeResult<FunctionHandle>;
18
19 fn clone_object(&self, obj: ObjectHandle) -> SolverForgeResult<ObjectHandle>;
20
21 fn get_list_size(&self, obj: ObjectHandle) -> SolverForgeResult<usize>;
22
23 fn get_list_item(&self, obj: ObjectHandle, index: usize) -> SolverForgeResult<Value>;
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct ClassInfo {
28 pub name: String,
29 pub fields: Vec<FieldInfo>,
30 pub annotations: Vec<PlanningAnnotation>,
31}
32
33impl ClassInfo {
34 pub fn new(name: impl Into<String>) -> Self {
35 Self {
36 name: name.into(),
37 fields: Vec::new(),
38 annotations: Vec::new(),
39 }
40 }
41
42 pub fn with_field(mut self, field: FieldInfo) -> Self {
43 self.fields.push(field);
44 self
45 }
46
47 pub fn with_annotation(mut self, annotation: PlanningAnnotation) -> Self {
48 self.annotations.push(annotation);
49 self
50 }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct FieldInfo {
55 pub name: String,
56 pub field_type: FieldType,
57 pub annotations: Vec<PlanningAnnotation>,
58}
59
60impl FieldInfo {
61 pub fn new(name: impl Into<String>, field_type: FieldType) -> Self {
62 Self {
63 name: name.into(),
64 field_type,
65 annotations: Vec::new(),
66 }
67 }
68
69 pub fn with_annotation(mut self, annotation: PlanningAnnotation) -> Self {
70 self.annotations.push(annotation);
71 self
72 }
73}
74
75#[cfg(test)]
76pub mod tests {
77 use super::*;
78 use crate::domain::PrimitiveType;
79 use crate::SolverForgeError;
80 use std::collections::HashMap;
81 use std::sync::{Arc, Mutex};
82
83 pub struct MockBridge {
84 objects: Arc<Mutex<HashMap<u64, Value>>>,
85 next_handle: Arc<Mutex<u64>>,
86 }
87
88 impl MockBridge {
89 pub fn new() -> Self {
90 Self {
91 objects: Arc::new(Mutex::new(HashMap::new())),
92 next_handle: Arc::new(Mutex::new(1)),
93 }
94 }
95
96 pub fn store_object(&self, value: Value) -> ObjectHandle {
97 let mut objects = self.objects.lock().unwrap();
98 let mut next = self.next_handle.lock().unwrap();
99 let handle = *next;
100 *next += 1;
101 objects.insert(handle, value);
102 ObjectHandle::new(handle)
103 }
104
105 pub fn get_object(&self, handle: ObjectHandle) -> Option<Value> {
106 self.objects.lock().unwrap().get(&handle.id()).cloned()
107 }
108 }
109
110 impl LanguageBridge for MockBridge {
111 fn call_function(&self, _func: FunctionHandle, args: &[Value]) -> SolverForgeResult<Value> {
112 Ok(args.first().cloned().unwrap_or(Value::Null))
113 }
114
115 fn get_field(&self, obj: ObjectHandle, field: &str) -> SolverForgeResult<Value> {
116 let value = self
117 .get_object(obj)
118 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
119
120 match value {
121 Value::Object(map) => Ok(map.get(field).cloned().unwrap_or(Value::Null)),
122 _ => Err(SolverForgeError::Bridge("Not an object".to_string())),
123 }
124 }
125
126 fn set_field(&self, obj: ObjectHandle, field: &str, value: Value) -> SolverForgeResult<()> {
127 let mut objects = self.objects.lock().unwrap();
128 let stored = objects
129 .get_mut(&obj.id())
130 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
131
132 match stored {
133 Value::Object(map) => {
134 map.insert(field.to_string(), value);
135 Ok(())
136 }
137 _ => Err(SolverForgeError::Bridge("Not an object".to_string())),
138 }
139 }
140
141 fn serialize_object(&self, obj: ObjectHandle) -> SolverForgeResult<String> {
142 let value = self
143 .get_object(obj)
144 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
145
146 serde_json::to_string(&value)
147 .map_err(|e| SolverForgeError::Serialization(e.to_string()))
148 }
149
150 fn deserialize_object(
151 &self,
152 json: &str,
153 _class_name: &str,
154 ) -> SolverForgeResult<ObjectHandle> {
155 let value: Value = serde_json::from_str(json)
156 .map_err(|e| SolverForgeError::Serialization(e.to_string()))?;
157
158 Ok(self.store_object(value))
159 }
160
161 fn get_class_info(&self, _obj: ObjectHandle) -> SolverForgeResult<ClassInfo> {
162 Ok(ClassInfo::new("MockClass")
163 .with_field(FieldInfo::new(
164 "id",
165 FieldType::Primitive(PrimitiveType::String),
166 ))
167 .with_annotation(PlanningAnnotation::PlanningEntity))
168 }
169
170 fn register_function(&self, func: ObjectHandle) -> SolverForgeResult<FunctionHandle> {
171 Ok(FunctionHandle::new(func.id()))
172 }
173
174 fn clone_object(&self, obj: ObjectHandle) -> SolverForgeResult<ObjectHandle> {
175 let value = self
176 .get_object(obj)
177 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
178
179 Ok(self.store_object(value))
180 }
181
182 fn get_list_size(&self, obj: ObjectHandle) -> SolverForgeResult<usize> {
183 let value = self
184 .get_object(obj)
185 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
186
187 match value {
188 Value::Array(arr) => Ok(arr.len()),
189 _ => Err(SolverForgeError::Bridge("Not an array".to_string())),
190 }
191 }
192
193 fn get_list_item(&self, obj: ObjectHandle, index: usize) -> SolverForgeResult<Value> {
194 let value = self
195 .get_object(obj)
196 .ok_or_else(|| SolverForgeError::Bridge(format!("Object not found: {:?}", obj)))?;
197
198 match value {
199 Value::Array(arr) => arr.get(index).cloned().ok_or_else(|| {
200 SolverForgeError::Bridge(format!("Index out of bounds: {}", index))
201 }),
202 _ => Err(SolverForgeError::Bridge("Not an array".to_string())),
203 }
204 }
205 }
206
207 #[test]
208 fn test_class_info() {
209 let info = ClassInfo::new("Lesson")
210 .with_annotation(PlanningAnnotation::PlanningEntity)
211 .with_field(FieldInfo::new(
212 "id",
213 FieldType::Primitive(PrimitiveType::String),
214 ));
215
216 assert_eq!(info.name, "Lesson");
217 assert_eq!(info.fields.len(), 1);
218 assert_eq!(info.annotations.len(), 1);
219 }
220
221 #[test]
222 fn test_field_info() {
223 let field = FieldInfo::new("room", FieldType::object("Room")).with_annotation(
224 PlanningAnnotation::planning_variable(vec!["rooms".to_string()]),
225 );
226
227 assert_eq!(field.name, "room");
228 assert_eq!(field.annotations.len(), 1);
229 }
230
231 #[test]
232 fn test_mock_bridge_store_and_get() {
233 let bridge = MockBridge::new();
234
235 let mut map = HashMap::new();
236 map.insert("name".to_string(), Value::String("Test".to_string()));
237 let obj = bridge.store_object(Value::Object(map));
238
239 let value = bridge.get_field(obj, "name").unwrap();
240 assert_eq!(value, Value::String("Test".to_string()));
241 }
242
243 #[test]
244 fn test_mock_bridge_set_field() {
245 let bridge = MockBridge::new();
246
247 let mut map = HashMap::new();
248 map.insert("value".to_string(), Value::Int(0));
249 let obj = bridge.store_object(Value::Object(map));
250
251 bridge.set_field(obj, "value", Value::Int(42)).unwrap();
252
253 let value = bridge.get_field(obj, "value").unwrap();
254 assert_eq!(value, Value::Int(42));
255 }
256
257 #[test]
258 fn test_mock_bridge_serialize() {
259 let bridge = MockBridge::new();
260
261 let mut map = HashMap::new();
262 map.insert("x".to_string(), Value::Int(1));
263 let obj = bridge.store_object(Value::Object(map));
264
265 let json = bridge.serialize_object(obj).unwrap();
266 assert!(json.contains("\"x\":1"));
267 }
268
269 #[test]
270 fn test_mock_bridge_deserialize() {
271 let bridge = MockBridge::new();
272
273 let json = r#"{"name":"Test","value":42}"#;
274 let obj = bridge.deserialize_object(json, "TestClass").unwrap();
275
276 let name = bridge.get_field(obj, "name").unwrap();
277 assert_eq!(name, Value::String("Test".to_string()));
278 }
279
280 #[test]
281 fn test_mock_bridge_clone() {
282 let bridge = MockBridge::new();
283
284 let mut map = HashMap::new();
285 map.insert("id".to_string(), Value::Int(1));
286 let obj = bridge.store_object(Value::Object(map));
287
288 let cloned = bridge.clone_object(obj).unwrap();
289 assert_ne!(obj.id(), cloned.id());
290
291 let value = bridge.get_field(cloned, "id").unwrap();
292 assert_eq!(value, Value::Int(1));
293 }
294
295 #[test]
296 fn test_mock_bridge_list_operations() {
297 let bridge = MockBridge::new();
298
299 let arr = Value::Array(vec![Value::Int(1), Value::Int(2), Value::Int(3)]);
300 let obj = bridge.store_object(arr);
301
302 assert_eq!(bridge.get_list_size(obj).unwrap(), 3);
303 assert_eq!(bridge.get_list_item(obj, 0).unwrap(), Value::Int(1));
304 assert_eq!(bridge.get_list_item(obj, 2).unwrap(), Value::Int(3));
305 }
306
307 #[test]
308 fn test_mock_bridge_call_function() {
309 let bridge = MockBridge::new();
310
311 let func = FunctionHandle::new(1);
312 let result = bridge.call_function(func, &[Value::Int(42)]).unwrap();
313 assert_eq!(result, Value::Int(42));
314 }
315}