@@ -12,7 +12,10 @@ use crate::string::String;
1212use crate :: table:: { Table , TablePairs } ;
1313use crate :: traits:: { FromLua , FromLuaMulti , IntoLua , IntoLuaMulti } ;
1414use crate :: types:: { MaybeSend , ValueRef } ;
15- use crate :: util:: { check_stack, get_userdata, push_string, take_userdata, StackGuard } ;
15+ use crate :: util:: {
16+ borrow_userdata_scoped, borrow_userdata_scoped_mut, check_stack, get_userdata, push_string,
17+ take_userdata, StackGuard , TypeIdHints ,
18+ } ;
1619use crate :: value:: Value ;
1720
1821#[ cfg( feature = "async" ) ]
2629
2730// Re-export for convenience
2831pub ( crate ) use cell:: UserDataStorage ;
29- pub use cell :: { UserDataRef , UserDataRefMut } ;
32+ pub use r#ref :: { UserDataRef , UserDataRefMut } ;
3033pub use registry:: UserDataRegistry ;
3134pub ( crate ) use registry:: { RawUserDataRegistry , UserDataProxy } ;
3235
@@ -622,7 +625,10 @@ impl AnyUserData {
622625 /// Checks whether the type of this userdata is `T`.
623626 #[ inline]
624627 pub fn is < T : ' static > ( & self ) -> bool {
625- self . inspect :: < T , _ , _ > ( |_| Ok ( ( ) ) ) . is_ok ( )
628+ let lua = self . 0 . lua . lock ( ) ;
629+ let type_id = lua. get_userdata_ref_type_id ( & self . 0 ) ;
630+ // We do not use wrapped types here, rather prefer to check the "real" type of the userdata
631+ matches ! ( type_id, Ok ( Some ( type_id) ) if type_id == TypeId :: of:: <T >( ) )
626632 }
627633
628634 /// Borrow this userdata immutably if it is of type `T`.
@@ -637,15 +643,19 @@ impl AnyUserData {
637643 /// [`DataTypeMismatch`]: crate::Error::UserDataTypeMismatch
638644 #[ inline]
639645 pub fn borrow < T : ' static > ( & self ) -> Result < UserDataRef < T > > {
640- self . inspect ( |ud| ud. try_borrow_owned ( ) )
646+ let lua = self . 0 . lua . lock ( ) ;
647+ unsafe { UserDataRef :: borrow_from_stack ( & lua, lua. ref_thread ( ) , self . 0 . index ) }
641648 }
642649
643650 /// Borrow this userdata immutably if it is of type `T`, passing the borrowed value
644651 /// to the closure.
645652 ///
646653 /// This method is the only way to borrow scoped userdata (created inside [`Lua::scope`]).
647654 pub fn borrow_scoped < T : ' static , R > ( & self , f : impl FnOnce ( & T ) -> R ) -> Result < R > {
648- self . inspect ( |ud| ud. try_borrow_scoped ( |ud| f ( ud) ) )
655+ let lua = self . 0 . lua . lock ( ) ;
656+ let type_id = lua. get_userdata_ref_type_id ( & self . 0 ) ?;
657+ let type_hints = TypeIdHints :: new :: < T > ( ) ;
658+ unsafe { borrow_userdata_scoped ( lua. ref_thread ( ) , self . 0 . index , type_id, type_hints, f) }
649659 }
650660
651661 /// Borrow this userdata mutably if it is of type `T`.
@@ -660,15 +670,19 @@ impl AnyUserData {
660670 /// [`UserDataTypeMismatch`]: crate::Error::UserDataTypeMismatch
661671 #[ inline]
662672 pub fn borrow_mut < T : ' static > ( & self ) -> Result < UserDataRefMut < T > > {
663- self . inspect ( |ud| ud. try_borrow_owned_mut ( ) )
673+ let lua = self . 0 . lua . lock ( ) ;
674+ unsafe { UserDataRefMut :: borrow_from_stack ( & lua, lua. ref_thread ( ) , self . 0 . index ) }
664675 }
665676
666677 /// Borrow this userdata mutably if it is of type `T`, passing the borrowed value
667678 /// to the closure.
668679 ///
669680 /// This method is the only way to borrow scoped userdata (created inside [`Lua::scope`]).
670681 pub fn borrow_mut_scoped < T : ' static , R > ( & self , f : impl FnOnce ( & mut T ) -> R ) -> Result < R > {
671- self . inspect ( |ud| ud. try_borrow_scoped_mut ( |ud| f ( ud) ) )
682+ let lua = self . 0 . lua . lock ( ) ;
683+ let type_id = lua. get_userdata_ref_type_id ( & self . 0 ) ?;
684+ let type_hints = TypeIdHints :: new :: < T > ( ) ;
685+ unsafe { borrow_userdata_scoped_mut ( lua. ref_thread ( ) , self . 0 . index , type_id, type_hints, f) }
672686 }
673687
674688 /// Takes the value out of this userdata.
@@ -687,9 +701,11 @@ impl AnyUserData {
687701 let type_id = lua. push_userdata_ref ( & self . 0 ) ?;
688702 match type_id {
689703 Some ( type_id) if type_id == TypeId :: of :: < T > ( ) => {
690- // Try to borrow userdata exclusively
691- let _ = ( * get_userdata :: < UserDataStorage < T > > ( state, -1 ) ) . try_borrow_mut ( ) ?;
692- take_userdata :: < UserDataStorage < T > > ( state) . into_inner ( )
704+ if ( * get_userdata :: < UserDataStorage < T > > ( state, -1 ) ) . has_exclusive_access ( ) {
705+ take_userdata :: < UserDataStorage < T > > ( state) . into_inner ( )
706+ } else {
707+ Err ( Error :: UserDataBorrowMutError )
708+ }
693709 }
694710 _ => Err ( Error :: UserDataTypeMismatch ) ,
695711 }
@@ -965,24 +981,6 @@ impl AnyUserData {
965981 } ;
966982 is_serializable ( ) . unwrap_or ( false )
967983 }
968-
969- pub ( crate ) fn inspect < T , F , R > ( & self , func : F ) -> Result < R >
970- where
971- T : ' static ,
972- F : FnOnce ( & UserDataStorage < T > ) -> Result < R > ,
973- {
974- let lua = self . 0 . lua . lock ( ) ;
975- unsafe {
976- let type_id = lua. get_userdata_ref_type_id ( & self . 0 ) ?;
977- match type_id {
978- Some ( type_id) if type_id == TypeId :: of :: < T > ( ) => {
979- let ud = get_userdata :: < UserDataStorage < T > > ( lua. ref_thread ( ) , self . 0 . index ) ;
980- func ( & * ud)
981- }
982- _ => Err ( Error :: UserDataTypeMismatch ) ,
983- }
984- }
985- }
986984}
987985
988986/// Handle to a [`AnyUserData`] metatable.
@@ -1106,6 +1104,7 @@ where
11061104mod cell;
11071105mod lock;
11081106mod object;
1107+ mod r#ref;
11091108mod registry;
11101109mod util;
11111110
0 commit comments