From 381c2da44ceb889084e602ce3429b1caab522e97 Mon Sep 17 00:00:00 2001 From: tk <49250442+tkr-sh@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:27:05 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20feat:=20impl=20From/Into=20Lua?= =?UTF-8?q?=20for=20char?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/conversion.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++ tests/conversion.rs | 26 ++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/conversion.rs b/src/conversion.rs index ad0a7003..97dec5a8 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -655,6 +655,71 @@ impl IntoLua for &Path { } } +impl IntoLua for char { + #[inline] + fn into_lua(self, lua: &Lua) -> Result { + let mut char_bytes = [0; 4]; + self.encode_utf8(&mut char_bytes); + Ok(Value::String(lua.create_string(char_bytes)?)) + } +} + +impl FromLua for char { + #[inline] + fn from_lua(value: Value, _lua: &Lua) -> Result { + let ty = value.type_name(); + match value { + // When integer: reduce it to u8 and try to convert to char + Value::Integer(i) => { + if i <= u8::MAX.into() { + Ok(char::from(i as u8)) + } else { + Err(Error::FromLuaConversionError { + from: ty, + to: Self::type_name(), + message: Some( + "expected int to be a u8 when converting to char. You can also use strings." + .to_string(), + ), + }) + } + } + // When String: first char, and only if there is one char + Value::String(s) => { + let str = s.to_str()?; + let mut str_iter = str.chars(); + let Some(char) = str_iter.next() else { + return Err(Error::FromLuaConversionError { + from: ty, + to: Self::type_name(), + message: Some( + "string must have one char when converting to char. (empty string)".to_string(), + ), + }) + }; + + if let Some(_extra_char) = str_iter.next() { + Err(Error::FromLuaConversionError { + from: ty, + to: Self::type_name(), + message: Some( + "expected lua string to have exactly one char when converting to char" + .to_string(), + ), + }) + } else { + Ok(char) + } + } + _ => Err(Error::FromLuaConversionError { + from: ty, + to: Self::type_name(), + message: Some("expected string or number".to_string()), + }), + } + } +} + #[inline] unsafe fn push_bytes_into_stack(this: T, lua: &RawLua) -> Result<()> where diff --git a/tests/conversion.rs b/tests/conversion.rs index 2cb9b880..e479c6bd 100644 --- a/tests/conversion.rs +++ b/tests/conversion.rs @@ -657,3 +657,29 @@ fn test_either_from_lua() -> Result<()> { Ok(()) } + +#[test] +fn test_char_into_lua() -> Result<()> { + let lua = Lua::new(); + + let v = '🦀'; + let v2 = v.into_lua(&lua)?; + assert_eq!(Some(v.to_string()), v2.as_string_lossy()); + + Ok(()) +} + +#[test] +fn test_char_from_lua() -> Result<()> { + let lua = Lua::new(); + + let f = lua.create_function(|_, s: mlua::String| Ok(s))?; + let s = f.call::("A")?; + assert_eq!(s, 'A'); + + let f = lua.create_function(|_, s: mlua::Integer| Ok(s))?; + let s = f.call::(65)?; + assert_eq!(s, 'A'); + + Ok(()) +} From 45fcb26263804b10a4c1c376d6c3ed6ac9636a6d Mon Sep 17 00:00:00 2001 From: tk <49250442+tkr-sh@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:29:34 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=92=AC=20refactor:=20s/number/integer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversion.rs b/src/conversion.rs index 97dec5a8..d8d1937b 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -714,7 +714,7 @@ impl FromLua for char { _ => Err(Error::FromLuaConversionError { from: ty, to: Self::type_name(), - message: Some("expected string or number".to_string()), + message: Some("expected string or integer".to_string()), }), } } From 7c5d781745ef7d2cccfd612be2dfd84555f3a88d Mon Sep 17 00:00:00 2001 From: tk <49250442+tkr-sh@users.noreply.github.com> Date: Wed, 22 Jan 2025 00:50:37 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=A9=B9=20fix:=20oops?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversion.rs b/src/conversion.rs index d8d1937b..32d71056 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -671,7 +671,7 @@ impl FromLua for char { match value { // When integer: reduce it to u8 and try to convert to char Value::Integer(i) => { - if i <= u8::MAX.into() { + if i <= u8::MAX.into() && i >= 0 { Ok(char::from(i as u8)) } else { Err(Error::FromLuaConversionError { From 76acbb87371235d5cc151b956a74b3dbe78f0cf8 Mon Sep 17 00:00:00 2001 From: tk <49250442+tkr-sh@users.noreply.github.com> Date: Fri, 24 Jan 2025 17:57:33 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=92=85=20style:=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversion.rs b/src/conversion.rs index 32d71056..e24d6c86 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -695,7 +695,7 @@ impl FromLua for char { message: Some( "string must have one char when converting to char. (empty string)".to_string(), ), - }) + }); }; if let Some(_extra_char) = str_iter.next() {