@@ -3,12 +3,12 @@ use std::{any::TypeId, borrow::Cow, ops::Deref, sync::Arc};
33use bevy:: reflect:: {
44 func:: {
55 args:: { Arg , ArgInfo , Ownership } ,
6- ArgList , ArgValue , DynamicFunction , FunctionResult , Return ,
6+ ArgList , ArgValue , DynamicFunction , FunctionInfo , FunctionResult , Return ,
77 } ,
88 PartialReflect ,
99} ;
1010
11- use crate :: error:: { ScriptError , ScriptResult , ValueConversionError } ;
11+ use crate :: error:: { InteropError , ScriptError , ScriptResult } ;
1212
1313use super :: {
1414 access_map:: ReflectAccessId ,
@@ -26,19 +26,13 @@ pub trait CallableWithAccess {
2626 args : I ,
2727 world : Arc < WorldAccessGuard > ,
2828 f : F ,
29- ) -> ScriptResult < O > ;
29+ ) -> Result < O , InteropError > ;
3030
3131 fn dynamic_call < I : IntoIterator < Item = ScriptValue > > (
3232 & self ,
3333 args : I ,
3434 world : Arc < WorldAccessGuard > ,
35- ) -> ScriptResult < ScriptValue > {
36- self . with_call ( args, world. clone ( ) , |r| match r {
37- Return :: Owned ( partial_reflect) => partial_reflect. as_ref ( ) . into_script_value ( world) ,
38- Return :: Ref ( ref_) => ref_. into_script_value ( world) ,
39- Return :: Mut ( mut_ref) => mut_ref. into_script_value ( world) ,
40- } ) ?
41- }
35+ ) -> Result < ScriptValue , InteropError > ;
4236}
4337
4438impl CallableWithAccess for DynamicFunction < ' _ > {
@@ -47,7 +41,7 @@ impl CallableWithAccess for DynamicFunction<'_> {
4741 args : I ,
4842 world : Arc < WorldAccessGuard > ,
4943 f : F ,
50- ) -> ScriptResult < O > {
44+ ) -> Result < O , InteropError > {
5145 let info = self . info ( ) . args ( ) ;
5246
5347 // We need to:
@@ -68,9 +62,9 @@ impl CallableWithAccess for DynamicFunction<'_> {
6862 {
6963 std:: iter:: once ( ScriptValue :: World )
7064 . chain ( arg_iter)
71- . into_args_list_with_access ( info, world. clone ( ) ) ?
65+ . into_args_list_with_access ( self . info ( ) , world. clone ( ) ) ?
7266 } else {
73- arg_iter. into_args_list_with_access ( info, world. clone ( ) ) ?
67+ arg_iter. into_args_list_with_access ( self . info ( ) , world. clone ( ) ) ?
7468 } ;
7569
7670 let mut final_args_list = ArgList :: default ( ) ;
@@ -101,7 +95,7 @@ impl CallableWithAccess for DynamicFunction<'_> {
10195 unsafe { world. release_access ( id) } ;
10296 } ) ;
10397
104- return Err ( e . into ( ) ) ;
98+ return Err ( InteropError :: function_call_error ( e ) ) ;
10599 }
106100 } ;
107101
@@ -114,6 +108,19 @@ impl CallableWithAccess for DynamicFunction<'_> {
114108
115109 Ok ( out)
116110 }
111+
112+ fn dynamic_call < I : IntoIterator < Item = ScriptValue > > (
113+ & self ,
114+ args : I ,
115+ world : Arc < WorldAccessGuard > ,
116+ ) -> Result < ScriptValue , InteropError > {
117+ self . with_call ( args, world. clone ( ) , |r| match r {
118+ Return :: Owned ( partial_reflect) => partial_reflect. as_ref ( ) . into_script_value ( world) ,
119+ Return :: Ref ( ref_) => ref_. into_script_value ( world) ,
120+ Return :: Mut ( mut_ref) => mut_ref. into_script_value ( world) ,
121+ } ) ?
122+ . map_err ( |e| InteropError :: function_interop_error ( self . info ( ) , None , e) . into ( ) )
123+ }
117124}
118125
119126/// Trait implementable by lists of things representing arguments which can be converted into an `ArgList`.
@@ -122,9 +129,9 @@ impl CallableWithAccess for DynamicFunction<'_> {
122129pub trait IntoArgsListWithAccess {
123130 fn into_args_list_with_access < ' w > (
124131 self ,
125- arg_info : & [ ArgInfo ] ,
132+ function_info : & FunctionInfo ,
126133 world : WorldGuard < ' w > ,
127- ) -> ScriptResult < ( Vec < ArgValue < ' w > > , Vec < ( ReflectAccessId , Ownership ) > ) > ;
134+ ) -> Result < ( Vec < ArgValue < ' w > > , Vec < ( ReflectAccessId , Ownership ) > ) , InteropError > ;
128135}
129136
130137impl < I : Iterator < Item = ScriptValue > > IntoArgsListWithAccess for I {
@@ -134,9 +141,10 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
134141 /// Meaning that only after releasing access is it possible to create unsafe aliases
135142 fn into_args_list_with_access < ' w > (
136143 self ,
137- arg_info : & [ ArgInfo ] ,
144+ function_info : & FunctionInfo ,
138145 world : WorldGuard < ' w > ,
139- ) -> ScriptResult < ( Vec < ArgValue < ' w > > , Vec < ( ReflectAccessId , Ownership ) > ) > {
146+ ) -> Result < ( Vec < ArgValue < ' w > > , Vec < ( ReflectAccessId , Ownership ) > ) , InteropError > {
147+ let arg_info = function_info. args ( ) ;
140148 let mut accesses = Vec :: default ( ) ;
141149 let mut arg_list = Vec :: default ( ) ;
142150
@@ -147,23 +155,23 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
147155 } ) ;
148156 } ;
149157
150- for ( value, arg_info ) in self . zip ( arg_info. iter ( ) ) {
158+ for ( value, argument_info ) in self . zip ( arg_info. iter ( ) ) {
151159 match value {
152160 // TODO: I'd see the logic be a bit cleaner, this if is needed to support 'Raw' ScriptValue arguments
153161 // as we do not want to claim any access since we're not using the value yet
154162 ScriptValue :: Reference ( arg_ref)
155- if arg_info . type_id ( ) != TypeId :: of :: < ScriptValue > ( ) =>
163+ if argument_info . type_id ( ) != TypeId :: of :: < ScriptValue > ( ) =>
156164 {
157- let access_id =
158- ReflectAccessId :: for_reference ( arg_ref . base . base_id . clone ( ) ) . ok_or_else ( || {
159- ScriptError :: new_reflection_error ( format ! (
160- "Could not call function, argument: {:?}, with type: {} is not a valid reference. Have you registered the type?" ,
161- arg_info . name ( ) . map ( str :: to_owned ) . unwrap_or_else ( || arg_info . index ( ) . to_string ( ) ) ,
162- arg_ref. display_with_world ( world . clone( ) )
163- ) )
164- } ) ?;
165+ let access_id = ReflectAccessId :: for_reference ( arg_ref . base . base_id . clone ( ) )
166+ . ok_or_else ( || {
167+ InteropError :: function_interop_error (
168+ function_info ,
169+ Some ( argument_info ) ,
170+ InteropError :: unregistered_base ( arg_ref. base . clone ( ) ) ,
171+ )
172+ } ) ?;
165173
166- let is_write = matches ! ( arg_info . ownership( ) , Ownership :: Mut ) ;
174+ let is_write = matches ! ( argument_info . ownership( ) , Ownership :: Mut ) ;
167175
168176 let success = if is_write {
169177 world. claim_write_access ( access_id)
@@ -173,20 +181,27 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
173181
174182 if !success {
175183 release_accesses ( & mut accesses) ;
176- return Err ( ScriptError :: new_reflection_error ( format ! (
177- "Could not claim access for argument {}" ,
178- arg_ref. display_with_world( world. clone( ) )
179- ) ) ) ;
184+ return Err ( InteropError :: function_interop_error (
185+ function_info,
186+ Some ( argument_info) ,
187+ InteropError :: cannot_claim_access ( arg_ref. base . clone ( ) ) ,
188+ )
189+ . into ( ) ) ;
180190 }
181191
182- accesses. push ( ( access_id, arg_info . ownership ( ) ) ) ;
192+ accesses. push ( ( access_id, argument_info . ownership ( ) ) ) ;
183193
184- let val = unsafe { arg_ref. clone ( ) . into_arg_value ( world. clone ( ) , arg_info) } ;
194+ let val =
195+ unsafe { arg_ref. clone ( ) . into_arg_value ( world. clone ( ) , argument_info) } ;
185196 let val = match val {
186197 Ok ( v) => v,
187198 Err ( e) => {
188199 release_accesses ( & mut accesses) ;
189- return Err ( e) ;
200+ return Err ( InteropError :: function_interop_error (
201+ function_info,
202+ Some ( argument_info) ,
203+ e,
204+ ) ) ;
190205 }
191206 } ;
192207 arg_list. push ( val) ;
@@ -200,22 +215,27 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
200215 let value = match <dyn PartialReflect >:: from_script_value (
201216 value,
202217 world. clone ( ) ,
203- arg_info . type_id ( ) ,
218+ argument_info . type_id ( ) ,
204219 ) {
205220 Some ( Ok ( v) ) => v,
206221 Some ( Err ( e) ) => {
207222 // Safety: Same as above
208223 accesses. iter ( ) . for_each ( |( id, _) | {
209224 unsafe { world. release_access ( * id) } ;
210225 } ) ;
211- return Err ( e) ;
226+ return Err ( InteropError :: function_interop_error (
227+ function_info,
228+ Some ( argument_info) ,
229+ e,
230+ ) ) ;
212231 }
213232 None => {
214233 release_accesses ( & mut accesses) ;
215- return Err ( ValueConversionError :: TypeMismatch {
216- expected_type : arg_info. type_path ( ) . into ( ) ,
217- actual_type : None ,
218- }
234+ return Err ( InteropError :: function_interop_error (
235+ function_info,
236+ Some ( argument_info) ,
237+ InteropError :: impossible_conversion ( argument_info. type_id ( ) ) ,
238+ )
219239 . into ( ) ) ;
220240 }
221241 } ;
0 commit comments