1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
use std::cell::{RefCell, Ref, RefMut}; use emacs_module::emacs_value; use crate::{Env, Result, FromLisp, Transfer}; /// A type that represents Lisp values. /// Values of this type can be copied around, but are lifetime-bound to the [`Env`] they come from. /// /// They are also "proxy values" that are only useful when converted to Rust values, or used as /// arguments when calling back into the Lisp runtime. /// /// [`Env`]: struct.Env.html #[derive(Debug, Clone, Copy)] pub struct Value<'e> { pub(crate) raw: emacs_value, pub env: &'e Env, } impl<'e> Value<'e> { /// Constructs a new `Value`. Module code should not call this directly. It is public only for /// some internal macros to use. /// /// # Safety /// /// The raw value must come from the given [`Env`]. /// /// [`Env`]: struct.Env.html #[doc(hidden)] pub unsafe fn new(raw: emacs_value, env: &'e Env) -> Self { Self { raw, env } } /// Constructs a new `Value` and "roots" its underlying raw value (GC-managed) during the /// lifetime of the given [`Env`]. Module code should not call this directly. It is public only /// for some internal macros to use. /// /// # Safety /// /// The raw value must still be alive. This function is needed to protect new values returned /// from Emacs runtime, due to [this issue](https://github.com/ubolonton/emacs-module-rs/issues/2). /// /// [`Env`]: struct.Env.html #[allow(unused_unsafe)] #[doc(hidden)] pub unsafe fn new_protected(raw: emacs_value, env: &'e Env) -> Self { env.protected.borrow_mut().push(raw_call_no_exit!(env, make_global_ref, raw)); Self::new(raw, env) } pub fn is_not_nil(&self) -> bool { let env = self.env; raw_call_no_exit!(env, is_not_nil, self.raw) } // TODO: Decide what we want for PartialEq (==, !=): eq vs. eql vs. equal. #[allow(clippy::should_implement_trait)] pub fn eq(&self, other: Value<'e>) -> bool { let env = self.env; raw_call_no_exit!(env, eq, self.raw, other.raw) } /// Converts this value into a Rust value of the given type. #[inline] pub fn into_rust<T: FromLisp<'e>>(self) -> Result<T> { FromLisp::from_lisp(self) } #[inline] pub fn into_ref<T: 'static>(self) -> Result<Ref<'e, T>> { let container: &RefCell<T> = self.into_rust()?; // TODO: Use .borrow(), we want panics. Ok(container.try_borrow()?) } #[inline] pub fn into_ref_mut<T: 'static>(self) -> Result<RefMut<'e, T>> { let container: &RefCell<T> = self.into_rust()?; // TODO: Use .borrow_mut(), we want panics. Ok(container.try_borrow_mut()?) } /// Returns a mutable reference to the underlying Rust data wrapped by this value. /// /// # Safety /// /// There are several ways this can go wrong: /// /// - Lisp code can pass the same object through 2 different values in an argument list. /// - Rust code earlier in the call chain may have copied this value. /// - Rust code later in the call chain may receive a copy of this value. /// /// In general, it is better to wrap Rust data in `RefCell`, `Mutex`, or `RwLock` guards, before /// moving them to Lisp, and then only access them through these guards (which can be obtained /// back through [`into_rust`]). This method is for squeezing out the last bit of performance in /// very rare situations. /// /// [`into_rust`]: #method.into_rust pub unsafe fn get_mut<T: Transfer>(&mut self) -> Result<&mut T> { self.env.get_raw_pointer(self.raw).map(|r| &mut *r) } }