@@ -15,6 +15,10 @@ use crate::interface::GodotScriptImpl;
1515
1616use super :: rust_script_instance:: { GodotScriptObject , RustScriptInstance } ;
1717
18+ /// A call context for a script method call.
19+ ///
20+ /// The call context can be used to perform re-entrant calls into engine APIs. Its lifetime is constrained to the duration of the current
21+ /// function.
1822pub struct Context < ' a , Script : GodotScriptImpl + ?Sized > {
1923 cell : * const GdCell < Box < dyn GodotScriptObject > > ,
2024 data_ptr : * mut Box < dyn GodotScriptObject > ,
@@ -29,24 +33,27 @@ impl<Script: GodotScriptImpl> Debug for Context<'_, Script> {
2933}
3034
3135impl < Script : GodotScriptImpl > Context < ' _ , Script > {
36+ /// Create a scope in which the current mutable ref to [`Self`] is released.
37+ ///
38+ /// A re-entrant scope allows to use engine APIs that call back into the current script.
3239 pub fn reentrant_scope < T : GodotScriptObject + ' static , Args , Return > (
3340 & mut self ,
3441 self_ref : & mut T ,
3542 scope : impl ReentrantScope < Script :: ImplBase , Args , Return > ,
3643 ) -> Return {
37- let known_ptr = unsafe {
38- let any = ( * self . data_ptr ) . as_any_mut ( ) ;
39-
40- any. downcast_mut :: < T > ( ) . unwrap ( ) as * mut T
41- } ;
44+ // SAFETY: the caller guaranteed that the data_ptr is valid for the lifetime of `Self`.
45+ let known_box_ptr = unsafe { & mut * self . data_ptr } ;
46+ let known_ptr = known_box_ptr. as_any_mut ( ) . downcast_mut :: < T > ( ) . unwrap ( ) as * mut T ;
4247
4348 let self_ptr = self_ref as * mut _ ;
4449
4550 if known_ptr != self_ptr {
4651 panic ! ( "unable to create reentrant scope with unrelated self reference!" ) ;
4752 }
4853
54+ // SAFETY: the caller guaranteed that the data_ptr is valid for the lifetime of `Self`.
4955 let current_ref = unsafe { & mut * self . data_ptr } ;
56+ // SAFETY: the caller guaranteed that the cell is valid for the lifetime of `Self`.
5057 let cell = unsafe { & * self . cell } ;
5158 let guard = cell. make_inaccessible ( current_ref) . unwrap ( ) ;
5259
@@ -58,13 +65,20 @@ impl<Script: GodotScriptImpl> Context<'_, Script> {
5865 }
5966}
6067
68+ /// A generic script call context that is not tied to a specific script type.
6169pub struct GenericContext < ' a > {
6270 cell : * const GdCell < Box < dyn GodotScriptObject > > ,
6371 data_ptr : * mut Box < dyn GodotScriptObject > ,
6472 base : ScriptBaseMut < ' a , RustScriptInstance > ,
6573}
6674
6775impl < ' a > GenericContext < ' a > {
76+ /// Create a new script call context.
77+ ///
78+ /// # Safety
79+ /// - cell must be a valid pointer to a [`GdCell`] & not null.
80+ /// - data_ptr must be a valid pointer to the [`Box<dyn GodotScriptObject>`] inside the [`GdCell`].
81+ /// - both `cell` and `data_ptr` must out-live the `base`.
6882 pub ( super ) unsafe fn new (
6983 cell : * const GdCell < Box < dyn GodotScriptObject > > ,
7084 data_ptr : * mut Box < dyn GodotScriptObject > ,
0 commit comments