From 8f3d3b91b208f18ff09108722e899a4f7b2b9ecb Mon Sep 17 00:00:00 2001 From: Tim Cheeseman Date: Tue, 10 Dec 2024 13:36:13 -0500 Subject: [PATCH] Wrap vref in opaque type to allow exhaustive matching on Value enum outside of crate. Addresses #502 --- src/state/raw.rs | 8 +++++--- src/value.rs | 17 +++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/state/raw.rs b/src/state/raw.rs index 0731f846..9bafd39b 100644 --- a/src/state/raw.rs +++ b/src/state/raw.rs @@ -31,7 +31,7 @@ use crate::util::{ pop_error, push_internal_userdata, push_string, push_table, rawset_field, safe_pcall, safe_xpcall, short_type_name, StackGuard, WrappedFailure, }; -use crate::value::{Nil, Value}; +use crate::value::{Nil, Other, Value}; use super::extra::ExtraData; use super::{Lua, LuaOptions, WeakLua}; @@ -585,7 +585,7 @@ impl RawLua { let protect = !self.unlikely_memory_error(); push_internal_userdata(state, WrappedFailure::Error(*err.clone()), protect)?; } - Value::Other(vref) => self.push_ref(vref), + Value::Other(Other { inner: vref }) => self.push_ref(vref), } Ok(()) } @@ -689,7 +689,9 @@ impl RawLua { _ => { ffi::lua_xpush(state, self.ref_thread(), idx); - Value::Other(self.pop_ref_thread()) + Value::Other(Other { + inner: self.pop_ref_thread(), + }) } } } diff --git a/src/value.rs b/src/value.rs index 6c81ee55..5237697e 100644 --- a/src/value.rs +++ b/src/value.rs @@ -67,8 +67,13 @@ pub enum Value { /// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned. Error(Box), /// Any other value not known to mlua (eg. LuaJIT CData). - #[allow(private_interfaces)] - Other(ValueRef), + Other(Other), +} + +/// Opaque wrapper to allow matching on `Value::Other` variant +#[derive(Clone)] +pub struct Other { + pub(crate) inner: ValueRef, } pub use self::Value::Nil; @@ -140,7 +145,7 @@ impl Value { | Value::Function(Function(vref)) | Value::Thread(Thread(vref, ..)) | Value::UserData(AnyUserData(vref)) - | Value::Other(vref) => vref.to_pointer(), + | Value::Other(Other { inner: vref }) => vref.to_pointer(), #[cfg(feature = "luau")] Value::Buffer(crate::Buffer(vref)) => vref.to_pointer(), _ => ptr::null(), @@ -179,7 +184,7 @@ impl Value { | Value::Function(Function(vref)) | Value::Thread(Thread(vref, ..)) | Value::UserData(AnyUserData(vref)) - | Value::Other(vref) => unsafe { invoke_to_string(vref) }, + | Value::Other(Other { inner: vref }) => unsafe { invoke_to_string(vref) }, #[cfg(feature = "luau")] Value::Buffer(crate::Buffer(vref)) => unsafe { invoke_to_string(vref) }, Value::Error(err) => Ok(err.to_string()), @@ -565,7 +570,7 @@ impl Value { buf @ Value::Buffer(_) => write!(fmt, "buffer: {:?}", buf.to_pointer()), Value::Error(e) if recursive => write!(fmt, "{e:?}"), Value::Error(_) => write!(fmt, "error"), - Value::Other(v) => write!(fmt, "other: {:?}", v.to_pointer()), + Value::Other(Other { inner: v }) => write!(fmt, "other: {:?}", v.to_pointer()), } } } @@ -592,7 +597,7 @@ impl fmt::Debug for Value { #[cfg(feature = "luau")] Value::Buffer(buf) => write!(fmt, "{buf:?}"), Value::Error(e) => write!(fmt, "Error({e:?})"), - Value::Other(v) => write!(fmt, "Other({v:?})"), + Value::Other(v) => write!(fmt, "Other({0:?})", v.inner), } } }