@@ -5,27 +5,25 @@ mod models;
55
66use crate :: ast:: { ASTExecutionContext , JSONExpression } ;
77use crate :: models:: PassableValue :: Function ;
8- use crate :: models:: { ExecutionContext , PassableMap , PassableValue } ;
98use crate :: models:: PassableValue :: PMap ;
9+ use crate :: models:: { ExecutionContext , PassableMap , PassableValue } ;
1010use crate :: ExecutableType :: { CompiledProgram , AST } ;
11- use async_trait:: async_trait;
1211use cel_interpreter:: extractors:: This ;
1312use cel_interpreter:: objects:: { Key , Map , TryIntoValue } ;
1413use cel_interpreter:: { Context , ExecutionError , Expression , FunctionContext , Program , Value } ;
14+ use cel_parser:: parse;
1515use std:: collections:: HashMap ;
1616use std:: error:: Error ;
1717use std:: fmt;
1818use std:: fmt:: Debug ;
19+ use std:: future:: Future ;
1920use std:: ops:: Deref ;
20- use std:: sync :: { Arc , mpsc , Mutex } ;
21- use std:: thread :: spawn ;
22- use cel_parser :: parse ;
21+ use std:: pin :: Pin ;
22+ use std:: sync :: { Arc , Mutex } ;
23+ use std :: task :: { Poll , Waker } ;
2324
2425#[ cfg( target_arch = "wasm32" ) ]
2526use wasm_bindgen_futures:: spawn_local;
26- #[ cfg( not( target_arch = "wasm32" ) ) ]
27- use futures_lite:: future:: block_on;
28- use uniffi:: deps:: log:: __private_api:: log;
2927
3028
3129/**
@@ -43,11 +41,15 @@ pub trait HostContext: Send + Sync {
4341}
4442
4543#[ cfg( not( target_arch = "wasm32" ) ) ]
46- #[ async_trait]
4744pub trait HostContext : Send + Sync {
48- async fn computed_property ( & self , name : String , args : String ) -> String ;
45+ fn computed_property ( & self , name : String , args : String , callback : Arc < dyn ResultCallback > ) -> String ;
4946
50- async fn device_property ( & self , name : String , args : String ) -> String ;
47+ fn device_property ( & self , name : String , args : String , callback : Arc < dyn ResultCallback > ) -> String ;
48+ }
49+
50+ #[ cfg( not( target_arch = "wasm32" ) ) ]
51+ pub trait ResultCallback : Send + Sync {
52+ fn on_result ( & self , result : String ) ;
5153}
5254
5355/**
@@ -109,9 +111,15 @@ pub fn evaluate_with_context(definition: String, host: Arc<dyn HostContext>) ->
109111 let data: Result < ExecutionContext , _ > = serde_json:: from_str ( definition. as_str ( ) ) ;
110112 let data: ExecutionContext = match data {
111113 Ok ( data) => data,
112- Err ( _) => {
113- let e : Result < ExecutionContext , String > = Err ( "Invalid execution context JSON" . to_string ( ) ) ;
114- return serde_json:: to_string ( & e) . unwrap ( )
114+ Err ( e) => {
115+ let mut error_message = format ! ( "Invalid execution context JSON: {}" , e) ;
116+ // If there's a source (cause), add it
117+ if let Some ( source) = e. source ( ) {
118+ error_message = format ! ( "{}\n Caused by: {}" , error_message, source) ;
119+ }
120+
121+ let error_result: Result < _ , String > = Err :: < ASTExecutionContext , String > ( error_message) ;
122+ return serde_json:: to_string ( & error_result) . unwrap ( )
115123 }
116124 } ;
117125 let compiled = Program :: compile ( data. expression . as_str ( ) )
@@ -208,23 +216,44 @@ fn execute_with(
208216 } else {
209217 serde_json:: to_string :: < Vec < PassableValue > > ( & vec ! [ ] )
210218 } ;
211- match args {
219+ let shared = Arc :: new ( Mutex :: new ( SharedState {
220+ result : None ,
221+ waker : None ,
222+ } ) ) ;
223+ let callback = CallbackFuture {
224+ shared : shared. clone ( ) ,
225+ } ;
226+
227+ let result: Result < _ , String > = match args {
212228 Ok ( args) => {
213229 match prop_type {
214230 PropType :: Computed => Ok ( ctx. computed_property (
215231 name. clone ( ) . to_string ( ) ,
216232 args,
217- ) . await ) ,
233+ Arc :: new ( callback) ,
234+ ) ) ,
218235 PropType :: Device => Ok ( ctx. device_property (
219236 name. clone ( ) . to_string ( ) ,
220237 args,
221- ) . await ) ,
238+ Arc :: new ( callback) ,
239+ ) ) ,
222240 }
223241 }
224242 Err ( e) => {
225243 Err ( ExecutionError :: UndeclaredReference ( name) . to_string ( ) )
226244 }
245+ } ;
246+
247+ match result {
248+ Ok ( _) => {
249+ let future = CallbackFuture { shared } . await ;
250+ Ok ( future)
251+ }
252+ Err ( e) => {
253+ Err ( e)
254+ }
227255 }
256+
228257 } ) ;
229258 // Deserialize the value
230259 let passable: Result < PassableValue , String > =
@@ -451,6 +480,42 @@ impl fmt::Display for DisplayableError {
451480 }
452481}
453482
483+ // We use this to turn the ResultCallback into a future we can await
484+ #[ cfg( not( target_arch = "wasm32" ) ) ]
485+ impl ResultCallback for CallbackFuture {
486+ fn on_result ( & self , result : String ) {
487+ let mut shared = self . shared . lock ( ) . unwrap ( ) ; // Now valid
488+ shared. result = Some ( result) ;
489+ if let Some ( waker) = shared. waker . take ( ) {
490+ waker. wake ( ) ;
491+ }
492+ }
493+ }
494+ #[ cfg( not( target_arch = "wasm32" ) ) ]
495+ pub struct CallbackFuture {
496+ shared : Arc < Mutex < SharedState > > ,
497+ }
498+
499+ #[ cfg( not( target_arch = "wasm32" ) ) ]
500+ struct SharedState {
501+ result : Option < String > ,
502+ waker : Option < Waker > ,
503+ }
504+
505+ #[ cfg( not( target_arch = "wasm32" ) ) ]
506+ impl Future for CallbackFuture {
507+ type Output = String ;
508+
509+ fn poll ( self : Pin < & mut Self > , cx : & mut std:: task:: Context < ' _ > ) -> Poll < Self :: Output > {
510+ let mut shared = self . shared . lock ( ) . unwrap ( ) ;
511+ if let Some ( result) = shared. result . take ( ) {
512+ Poll :: Ready ( result)
513+ } else {
514+ shared. waker = Some ( cx. waker ( ) . clone ( ) ) ;
515+ Poll :: Pending
516+ }
517+ }
518+ }
454519#[ cfg( test) ]
455520mod tests {
456521 use super :: * ;
@@ -459,14 +524,17 @@ mod tests {
459524 map : HashMap < String , String > ,
460525 }
461526
462- #[ async_trait]
463527 impl HostContext for TestContext {
464- async fn computed_property ( & self , name : String , args : String ) -> String {
465- self . map . get ( & name) . unwrap ( ) . to_string ( )
528+ fn computed_property ( & self , name : String , args : String , callback : Arc < dyn ResultCallback > ) -> String {
529+ let result = self . map . get ( & name) . unwrap ( ) . to_string ( ) ;
530+ callback. on_result ( result. clone ( ) ) ;
531+ result
466532 }
467533
468- async fn device_property ( & self , name : String , args : String ) -> String {
469- self . map . get ( & name) . unwrap ( ) . to_string ( )
534+ fn device_property ( & self , name : String , args : String , callback : Arc < dyn ResultCallback > ) -> String {
535+ let result = self . map . get ( & name) . unwrap ( ) . to_string ( ) ;
536+ callback. on_result ( result. clone ( ) ) ;
537+ result
470538 }
471539 }
472540
0 commit comments