   special_path = Path.join(__DIR__, "SpecialCasing.txt")
 
   codes = Enum.reduce File.stream!(special_path), codes, fn(line, acc) ->
-    [ codepoint, lower, title, upper, _comment ] = :binary.split(line, "; ", [:global])
+    [codepoint, lower, title, upper, _comment] = :binary.split(line, "; ", [:global])
     key = to_binary.(codepoint)
     :lists.keystore(key, 1, acc, {key, to_binary.(upper), to_binary.(lower), to_binary.(title)})
   end
 
   # Downcase
 
-  def downcase(string), do: do_downcase(string) |> IO.iodata_to_binary
+  def downcase(string), do: downcase(string, "")
 
   for {codepoint, _upper, lower, _title} <- codes, lower && lower != codepoint do
-    defp do_downcase(unquote(codepoint) <> rest) do
-      unquote(:binary.bin_to_list(lower)) ++ downcase(rest)
-    end
-  end
-
-  defp do_downcase(<< char, rest :: binary >>) do
-    [char|do_downcase(rest)]
-  end
-
-  defp do_downcase(""), do: []
+    defp downcase(unquote(codepoint) <> rest, acc) do
+      downcase(rest, acc <> unquote(lower))
+    end
+  end
+
+  defp downcase(<<char, rest :: binary>>, acc) do
+    downcase(rest, <<acc::binary, char>>)
+  end
+
+  defp downcase("", acc), do: acc
 
   # Upcase
 
-  def upcase(string), do: do_upcase(string) |> IO.iodata_to_binary
+  def upcase(string), do: upcase(string, "")
 
   for {codepoint, upper, _lower, _title} <- codes, upper && upper != codepoint do
-    defp do_upcase(unquote(codepoint) <> rest) do
-      unquote(:binary.bin_to_list(upper)) ++ do_upcase(rest)
-    end
-  end
-
-  defp do_upcase(<< char, rest :: binary >>) do
-    [char|do_upcase(rest)]
-  end
-
-  defp do_upcase(""), do: []
+    defp upcase(unquote(codepoint) <> rest, acc) do
+      upcase(rest, acc <> unquote(upper))
+    end
+  end
+
+  defp upcase(<<char, rest :: binary>>, acc) do
+    upcase(rest, <<acc::binary, char>>)
+  end
+
+  defp upcase("", acc), do: acc
 
   # Titlecase once
 

  data_path = Path.join(__DIR__, "UnicodeData.txt")

  {codes, whitespace} = Enum.reduce File.stream!(data_path), {[], []}, fn(line, {cacc, wacc}) ->
    [ codepoint, _name, _category,
      _class, bidi, _decomposition,
      _numeric_1, _numeric_2, _numeric_3,
      _bidi_mirror, _unicode_1, _iso,
      upper, lower, title ] = :binary.split(line, ";", [:global])

    title = :binary.part(title, 0, byte_size(title) - 1)


  end

  cluster = Enum.reduce File.stream!(cluster_path), HashDict.new, fn(line, dict) ->
    [_full, first, last, class] = Regex.run(regex, line)

    # Skip surrogates
    if first == "D800" and last == "DFFF" do
