Repository: tv-labs/lua (elixir)

Issue:
Encoding artifacts with non ASCII character in source
Hello, first of all thank you for your work, it has been a delight using your library !

**Issue**
Using non ASCII characters in the source string given to `eval!/1` leads to incorrect results  (tested with version `0.0.14` and `0.0.22`).

**Input**
```elixir
Lua.eval!("return 'é'")
```
**Result**
```elixir
{["Ã©"], #Lua<>}
```

**Expected**
```elixir
{["é"], #Lua<>}
```

**Possible fix**
Allowing to pass a `charlist` to `eval!` might solve the problem but I am not sure about the implications.

```elixir
iex> :luerl_new.do_dec(to_charlist("return 'é'"), :luerl_new.init())
{:ok, ["é"], ...}
```

Pull request:
fix: handle Lua with unicode characters
Handles a quirk of Luerl where it double encodes unicode data by always converting binaries to charlists. See https://github.com/rvirding/luerl/issues/197

Closes #63

Patch:
diff --git a/lib/lua.ex b/lib/lua.ex
index f6b274b..aac5f4e 100644
--- a/lib/lua.ex
+++ b/lib/lua.ex
@@ -92,7 +92,7 @@ defmodule Lua do
       end
 
     chunk =
-      case :luerl_comp.string(code, [:return]) do
+      case :luerl_comp.string(String.to_charlist(code), [:return]) do
         {:ok, chunk} -> %Lua.Chunk{instructions: chunk}
         {:error, error, _warnings} -> raise Lua.CompilerException, error
       end
@@ -320,6 +320,10 @@ defmodule Lua do
   def eval!(%__MODULE__{state: state} = lua, script, opts) when is_binary(script) do
     opts = Keyword.validate!(opts, decode: true)
 
+    # Luerl does some weird things with UTF8 encoding
+    # when its a binary see https://github.com/rvirding/luerl/issues/197
+    script = String.to_charlist(script)
+
     func =
       if opts[:decode] do
         &:luerl.do_dec/2
@@ -401,6 +405,8 @@ defmodule Lua do
 
   """
   def parse_chunk(code) do
+    code = String.to_charlist(code)
+
     case :luerl_comp.string(code, [:return]) do
       {:ok, chunk} ->
         {:ok, %Lua.Chunk{instructions: chunk}}


Test patch:
diff --git a/test/unicode_test.exs b/test/unicode_test.exs
new file mode 100644
index 0000000..a329231
--- /dev/null
+++ b/test/unicode_test.exs
@@ -0,0 +1,23 @@
+defmodule Lua.UnicodeTest do
+  use ExUnit.Case, async: true
+
+  import Lua, only: [sigil_LUA: 2]
+
+  test "it can contain unicode" do
+    assert {["é"], _} = Lua.eval!("return 'é'")
+  end
+
+  test "chunks can contain unicode" do
+    {:ok, chunk} = Lua.parse_chunk("return 'é'")
+    assert {["é"], _} = Lua.eval!(chunk)
+  end
+
+  test "sigil lua can contain unicode" do
+    assert {["é"], _} = Lua.eval!(~LUA"return 'é'"c)
+  end
+
+  test "a chunk can be loaded with unicode" do
+    assert {chunk, lua} = Lua.load_chunk!(Lua.new(), "return 'é'")
+    assert {["é"], _} = Lua.eval!(lua, chunk)
+  end
+end