From 03ab8283429ee5ed57241bc5353e1f9c95b7be21 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Sun, 12 Feb 2023 23:34:21 +0000 Subject: Return evicted value to `Lua::set_app_data` if it's already present. Add "Panics" section to `Lua::*_app_data` docs. --- src/lua.rs | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lua.rs b/src/lua.rs index 55367f5..29639d3 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1,6 +1,5 @@ use std::any::{Any, TypeId}; use std::cell::{Ref, RefCell, RefMut, UnsafeCell}; -use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::fmt; use std::marker::PhantomData; @@ -90,9 +89,9 @@ pub(crate) struct ExtraData { registry_unref_list: Arc>>>, #[cfg(not(feature = "send"))] - app_data: RefCell>>, + app_data: RefCell>>, #[cfg(feature = "send")] - app_data: RefCell>>, + app_data: RefCell>>, safe: bool, libs: StdLib, @@ -573,7 +572,7 @@ impl Lua { registered_userdata: FxHashMap::default(), registered_userdata_mt: FxHashMap::default(), registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))), - app_data: RefCell::new(HashMap::new()), + app_data: RefCell::new(FxHashMap::default()), safe: false, libs: StdLib::NONE, mem_info: None, @@ -2210,6 +2209,10 @@ impl Lua { /// Application data could be accessed at any time by using [`Lua::app_data_ref()`] or [`Lua::app_data_mut()`] /// methods where `T` is the data type. /// + /// # Panics + /// + /// Panics if the app data container is currently borrowed. + /// /// # Examples /// /// ``` @@ -2232,16 +2235,22 @@ impl Lua { /// } /// ``` #[track_caller] - pub fn set_app_data(&self, data: T) { + pub fn set_app_data(&self, data: T) -> Option { let extra = unsafe { &*self.extra.get() }; extra .app_data .try_borrow_mut() .expect("cannot borrow mutably app data container") - .insert(TypeId::of::(), Box::new(data)); + .insert(TypeId::of::(), Box::new(data)) + .and_then(|data| data.downcast::().ok().map(|data| *data)) } /// Gets a reference to an application data object stored by [`Lua::set_app_data()`] of type `T`. + /// + /// # Panics + /// + /// Panics if the app data container is currently mutably borrowed. Multiple immutable reads can be + /// taken out at the same time. #[track_caller] pub fn app_data_ref(&self) -> Option> { let extra = unsafe { &*self.extra.get() }; @@ -2256,18 +2265,28 @@ impl Lua { } /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data()`] of type `T`. + /// + /// # Panics + /// + /// Panics if the app data container is currently borrowed. #[track_caller] pub fn app_data_mut(&self) -> Option> { let extra = unsafe { &*self.extra.get() }; - let mut app_data = extra + let app_data = extra .app_data .try_borrow_mut() .expect("cannot mutably borrow app data container"); - let value = app_data.get_mut(&TypeId::of::())?.downcast_mut::()? as *mut _; - Some(RefMut::map(app_data, |_| unsafe { &mut *value })) + RefMut::filter_map(app_data, |data| { + data.get_mut(&TypeId::of::())?.downcast_mut::() + }) + .ok() } /// Removes an application data of type `T`. + /// + /// # Panics + /// + /// Panics if the app data container is currently borrowed. #[track_caller] pub fn remove_app_data(&self) -> Option { let extra = unsafe { &*self.extra.get() }; @@ -2276,7 +2295,7 @@ impl Lua { .try_borrow_mut() .expect("cannot mutably borrow app data container") .remove(&TypeId::of::()) - .and_then(|data| data.downcast().ok().map(|data: Box| *data)) + .and_then(|data| data.downcast::().ok().map(|data| *data)) } // Uses 2 stack spaces, does not call checkstack -- cgit v1.2.3