diff --git a/src/conversion.rs b/src/conversion.rs index eb622d5..b74343d 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -71,11 +71,7 @@ impl FromLua for LuaString { fn from_lua(value: Value, lua: &Lua) -> Result { let ty = value.type_name(); lua.coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "string".to_string(), - message: Some("expected string or number".to_string()), - }) + .ok_or_else(|| Error::from_lua_conversion(ty, "string", "expected string or number".to_string())) } unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result { @@ -203,11 +199,7 @@ impl FromLua for Table { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::Table(table) => Ok(table), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "table".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "table", None)), } } } @@ -237,11 +229,7 @@ impl FromLua for Function { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::Function(table) => Ok(table), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "function".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "function", None)), } } } @@ -271,11 +259,7 @@ impl FromLua for Thread { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::Thread(t) => Ok(t), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "thread".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "thread", None)), } } } @@ -305,11 +289,7 @@ impl FromLua for AnyUserData { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::UserData(ud) => Ok(ud), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "userdata".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "userdata", None)), } } } @@ -427,11 +407,11 @@ impl FromLua for LightUserData { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::LightUserData(ud) => Ok(ud), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "lightuserdata".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion( + value.type_name(), + "lightuserdata", + None, + )), } } } @@ -450,11 +430,7 @@ impl FromLua for crate::Vector { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::Vector(v) => Ok(v), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "vector".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "vector", None)), } } } @@ -487,11 +463,7 @@ impl FromLua for crate::Buffer { fn from_lua(value: Value, _: &Lua) -> Result { match value { Value::Buffer(buf) => Ok(buf), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "buffer".to_string(), - message: None, - }), + _ => Err(Error::from_lua_conversion(value.type_name(), "buffer", None)), } } } @@ -524,10 +496,8 @@ impl FromLua for String { let ty = value.type_name(); Ok(lua .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("expected string or number".to_string()), + .ok_or_else(|| { + Error::from_lua_conversion(ty, Self::type_name(), "expected string or number".to_string()) })? .to_str()? .to_owned()) @@ -543,11 +513,7 @@ impl FromLua for String { let bytes = slice::from_raw_parts(data as *const u8, size); return str::from_utf8(bytes) .map(|s| s.to_owned()) - .map_err(|e| Error::FromLuaConversionError { - from: "string", - to: Self::type_name(), - message: Some(e.to_string()), - }); + .map_err(|e| Error::from_lua_conversion("string", Self::type_name(), e.to_string())); } // Fallback to default Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua()) @@ -586,10 +552,8 @@ impl FromLua for Box { let ty = value.type_name(); Ok(lua .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("expected string or number".to_string()), + .ok_or_else(|| { + Error::from_lua_conversion(ty, Self::type_name(), "expected string or number".to_string()) })? .to_str()? .to_owned() @@ -613,21 +577,12 @@ impl FromLua for CString { #[inline] fn from_lua(value: Value, lua: &Lua) -> Result { let ty = value.type_name(); - let string = lua - .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("expected string or number".to_string()), - })?; - + let string = lua.coerce_string(value)?.ok_or_else(|| { + Error::from_lua_conversion(ty, Self::type_name(), "expected string or number".to_string()) + })?; match CStr::from_bytes_with_nul(&string.as_bytes_with_nul()) { Ok(s) => Ok(s.into()), - Err(_) => Err(Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("invalid C-style string".to_string()), - }), + Err(err) => Err(Error::from_lua_conversion(ty, Self::type_name(), err.to_string())), } } } @@ -667,10 +622,8 @@ impl FromLua for BString { Value::Buffer(buf) => Ok(buf.to_vec().into()), _ => Ok((*lua .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("expected string or number".to_string()), + .ok_or_else(|| { + Error::from_lua_conversion(ty, Self::type_name(), "expected string or number".to_string()) })? .as_bytes()) .into()), @@ -721,11 +674,7 @@ impl FromLua for OsString { let bs = BString::from_lua(value, lua)?; Vec::from(bs) .into_os_string() - .map_err(|err| Error::FromLuaConversionError { - from: ty, - to: "OsString".into(), - message: Some(err.to_string()), - }) + .map_err(|err| Error::from_lua_conversion(ty, "OsString", err.to_string())) } } @@ -778,34 +727,25 @@ impl FromLua for char { fn from_lua(value: Value, _lua: &Lua) -> Result { let ty = value.type_name(); match value { - Value::Integer(i) => { - cast(i) - .and_then(char::from_u32) - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "char".to_string(), - message: Some("integer out of range when converting to char".to_string()), - }) - } + Value::Integer(i) => cast(i).and_then(char::from_u32).ok_or_else(|| { + let msg = "integer out of range when converting to char"; + Error::from_lua_conversion(ty, "char", msg.to_string()) + }), Value::String(s) => { let str = s.to_str()?; let mut str_iter = str.chars(); match (str_iter.next(), str_iter.next()) { (Some(char), None) => Ok(char), - _ => Err(Error::FromLuaConversionError { - from: ty, - to: "char".to_string(), - message: Some( - "expected string to have exactly one char when converting to char".to_string(), - ), - }), + _ => { + let msg = "expected string to have exactly one char when converting to char"; + Err(Error::from_lua_conversion(ty, "char", msg.to_string())) + } } } - _ => Err(Error::FromLuaConversionError { - from: ty, - to: Self::type_name(), - message: Some("expected string or integer".to_string()), - }), + _ => { + let msg = "expected string or integer"; + Err(Error::from_lua_conversion(ty, Self::type_name(), msg.to_string())) + } } } } @@ -856,24 +796,14 @@ macro_rules! lua_convert_int { if let Some(i) = lua.coerce_integer(value.clone())? { cast(i) } else { - cast( - lua.coerce_number(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: stringify!($x).to_string(), - message: Some( - "expected number or string coercible to number".to_string(), - ), - })?, - ) + cast(lua.coerce_number(value)?.ok_or_else(|| { + let msg = "expected number or string coercible to number"; + Error::from_lua_conversion(ty, stringify!($x), msg.to_string()) + })?) } } }) - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: stringify!($x).to_string(), - message: Some("out of range".to_owned()), - }) + .ok_or_else(|| Error::from_lua_conversion(ty, stringify!($x), "out of range".to_string())) } unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result { @@ -883,10 +813,8 @@ macro_rules! lua_convert_int { let mut ok = 0; let i = ffi::lua_tointegerx(state, idx, &mut ok); if ok != 0 { - return cast(i).ok_or_else(|| Error::FromLuaConversionError { - from: "integer", - to: stringify!($x).to_string(), - message: Some("out of range".to_owned()), + return cast(i).ok_or_else(|| { + Error::from_lua_conversion("integer", stringify!($x), "out of range".to_string()) }); } } @@ -923,13 +851,10 @@ macro_rules! lua_convert_float { #[inline] fn from_lua(value: Value, lua: &Lua) -> Result { let ty = value.type_name(); - lua.coerce_number(value)? - .map(|n| n as $x) - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: stringify!($x).to_string(), - message: Some("expected number or string coercible to number".to_string()), - }) + lua.coerce_number(value)?.map(|n| n as $x).ok_or_else(|| { + let msg = "expected number or string coercible to number"; + Error::from_lua_conversion(ty, stringify!($x), msg.to_string()) + }) } unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result { @@ -989,18 +914,16 @@ where }, Value::Table(table) => { let vec = table.sequence_values().collect::>>()?; - vec.try_into() - .map_err(|vec: Vec| Error::FromLuaConversionError { - from: "table", - to: Self::type_name(), - message: Some(format!("expected table of length {N}, got {}", vec.len())), - }) + vec.try_into().map_err(|vec: Vec| { + let msg = format!("expected table of length {N}, got {}", vec.len()); + Error::from_lua_conversion("table", Self::type_name(), msg) + }) + } + _ => { + let msg = format!("expected table of length {N}"); + let err = Error::from_lua_conversion(value.type_name(), Self::type_name(), msg.to_string()); + Err(err) } - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }), } } } @@ -1031,11 +954,11 @@ impl FromLua for Vec { fn from_lua(value: Value, _lua: &Lua) -> Result { match value { Value::Table(table) => table.sequence_values().collect(), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }), + _ => Err(Error::from_lua_conversion( + value.type_name(), + Self::type_name(), + "expected table".to_string(), + )), } } } @@ -1050,14 +973,13 @@ impl IntoLua for HashMap FromLua for HashMap { #[inline] fn from_lua(value: Value, _: &Lua) -> Result { - if let Value::Table(table) = value { - table.pairs().collect() - } else { - Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }) + match value { + Value::Table(table) => table.pairs().collect(), + _ => Err(Error::from_lua_conversion( + value.type_name(), + Self::type_name(), + "expected table".to_string(), + )), } } } @@ -1072,14 +994,13 @@ impl IntoLua for BTreeMap { impl FromLua for BTreeMap { #[inline] fn from_lua(value: Value, _: &Lua) -> Result { - if let Value::Table(table) = value { - table.pairs().collect() - } else { - Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }) + match value { + Value::Table(table) => table.pairs().collect(), + _ => Err(Error::from_lua_conversion( + value.type_name(), + Self::type_name(), + "expected table".to_string(), + )), } } } @@ -1099,11 +1020,11 @@ impl FromLua for HashSet match value { Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(), Value::Table(table) => table.pairs::().map(|res| res.map(|(k, _)| k)).collect(), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }), + _ => Err(Error::from_lua_conversion( + value.type_name(), + Self::type_name(), + "expected table".to_string(), + )), } } } @@ -1123,11 +1044,11 @@ impl FromLua for BTreeSet { match value { Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(), Value::Table(table) => table.pairs::().map(|res| res.map(|(k, _)| k)).collect(), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: Self::type_name(), - message: Some("expected table".to_string()), - }), + _ => Err(Error::from_lua_conversion( + value.type_name(), + Self::type_name(), + "expected table".to_string(), + )), } } } @@ -1197,11 +1118,11 @@ impl FromLua for Either { // Try the right type Err(_) => match R::from_lua(value, lua).map(Either::Right) { Ok(r) => Ok(r), - Err(_) => Err(Error::FromLuaConversionError { - from: value_type_name, - to: Self::type_name(), - message: None, - }), + Err(_) => Err(Error::from_lua_conversion( + value_type_name, + Self::type_name(), + None, + )), }, } } @@ -1213,13 +1134,12 @@ impl FromLua for Either { Err(_) => match R::from_stack(idx, lua).map(Either::Right) { Ok(r) => Ok(r), Err(_) => { - let value_type_name = - CStr::from_ptr(ffi::lua_typename(lua.state(), ffi::lua_type(lua.state(), idx))); - Err(Error::FromLuaConversionError { - from: value_type_name.to_str().unwrap(), - to: Self::type_name(), - message: None, - }) + let state = lua.state(); + let from_type_name = CStr::from_ptr(ffi::lua_typename(state, ffi::lua_type(state, idx))) + .to_str() + .unwrap_or("unknown"); + let err = Error::from_lua_conversion(from_type_name, Self::type_name(), None); + Err(err) } }, } diff --git a/src/error.rs b/src/error.rs index 7d20a5a..c5b5e15 100644 --- a/src/error.rs +++ b/src/error.rs @@ -382,6 +382,7 @@ impl Error { } } + #[inline] pub(crate) fn from_lua_conversion( from: &'static str, to: impl ToString, diff --git a/src/state/raw.rs b/src/state/raw.rs index 7e1421a..4b2fa2d 100644 --- a/src/state/raw.rs +++ b/src/state/raw.rs @@ -1219,13 +1219,11 @@ impl RawLua { Ok(type_id) => Ok(type_id), Err(Error::UserDataTypeMismatch) if ffi::lua_type(state, idx) != ffi::LUA_TUSERDATA => { // Report `FromLuaConversionError` instead - // In Luau `luaL_typename` return heap-allocated string that is valid only for - // the `state` lifetime. - // `lua_typename` is used instead to get a truly static string. - let idx_type_name = CStr::from_ptr(ffi::lua_typename(state, ffi::lua_type(state, idx))); - let idx_type_name = idx_type_name.to_str().unwrap(); + let type_name = CStr::from_ptr(ffi::lua_typename(state, ffi::lua_type(state, idx))) + .to_str() + .unwrap_or("unknown"); let message = format!("expected userdata of type '{}'", short_type_name::()); - Err(Error::from_lua_conversion(idx_type_name, "userdata", message)) + Err(Error::from_lua_conversion(type_name, "userdata", message)) } Err(err) => Err(err), } diff --git a/src/string.rs b/src/string.rs index 9f2b4e9..0a1eff9 100644 --- a/src/string.rs +++ b/src/string.rs @@ -307,11 +307,8 @@ impl<'a> TryFrom<&'a LuaString> for BorrowedStr<'a> { #[inline] fn try_from(value: &'a LuaString) -> Result { let BorrowedBytes { buf, borrow, _lua } = BorrowedBytes::from(value); - let buf = str::from_utf8(buf).map_err(|e| Error::FromLuaConversionError { - from: "string", - to: "&str".to_string(), - message: Some(e.to_string()), - })?; + let buf = + str::from_utf8(buf).map_err(|e| Error::from_lua_conversion("string", "&str", e.to_string()))?; Ok(Self { buf, borrow, _lua }) } } diff --git a/src/userdata/ref.rs b/src/userdata/ref.rs index 0661c12..48f67c2 100644 --- a/src/userdata/ref.rs +++ b/src/userdata/ref.rs @@ -446,11 +446,11 @@ impl DerefMut for UserDataRefMutInner { fn try_value_to_userdata(value: Value) -> Result { match value { Value::UserData(ud) => Ok(ud), - _ => Err(Error::FromLuaConversionError { - from: value.type_name(), - to: "userdata".to_string(), - message: Some(format!("expected userdata of type {}", type_name::())), - }), + _ => Err(Error::from_lua_conversion( + value.type_name(), + "userdata", + format!("expected userdata of type {}", type_name::()), + )), } }