Skip to content

Commit

Permalink
impl FromLua/IntoLua for char (#516)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkr-sh authored Jan 28, 2025
1 parent d376cb9 commit 47bc372
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
65 changes: 65 additions & 0 deletions src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,71 @@ impl IntoLua for &Path {
}
}

impl IntoLua for char {
#[inline]
fn into_lua(self, lua: &Lua) -> Result<Value> {
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<Self> {
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() && i >= 0 {
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 integer".to_string()),
}),
}
}
}

#[inline]
unsafe fn push_bytes_into_stack<T>(this: T, lua: &RawLua) -> Result<()>
where
Expand Down
26 changes: 26 additions & 0 deletions tests/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<char>("A")?;
assert_eq!(s, 'A');

let f = lua.create_function(|_, s: mlua::Integer| Ok(s))?;
let s = f.call::<char>(65)?;
assert_eq!(s, 'A');

Ok(())
}

0 comments on commit 47bc372

Please sign in to comment.