Fix String.reverse/1 grapheme ordering around invalid utf8 bytes - #15645
Conversation
|
Maybe regression after #11024 |
|
|
||
| defp do_reverse({:error, <<byte, rest::bits>>}, acc), | ||
| do: :unicode.characters_to_binary(acc) <> <<byte>> <> do_reverse(:unicode_util.gc(rest), []) | ||
| do: do_reverse(:unicode_util.gc(rest), []) <> <<byte>> <> :unicode.characters_to_binary(acc) |
There was a problem hiding this comment.
Should we move them to the accumulator instead?
| do: do_reverse(:unicode_util.gc(rest), []) <> <<byte>> <> :unicode.characters_to_binary(acc) | |
| do: do_reverse(:unicode_util.gc(rest), [<<byte>>, acc]) |
There was a problem hiding this comment.
[<<byte>>, acc]variant may produce a nested lists. And also this affects hot path (strings without invalid utf8), because needs rewrite to something like:
defp do_reverse([grapheme | rest], acc),
# extra calls grapheme_to_binary, was: do_reverse(:unicode_util.gc(rest), [grapheme | acc])
do: do_reverse(:unicode_util.gc(rest), [grapheme_to_binary(grapheme) | acc])
defp do_reverse([], acc),
# do: :unicode.characters_to_binary(acc)
do: IO.iodata_to_binary(acc)If this is what you mean, I will do benchmark...
There was a problem hiding this comment.
Nested lists are supported in Unicode characters to binary:
iex> :unicode.characters_to_binary([[?j], ?o, <<?s>>, [[?é]]])
"josé"
But we should probably do this instead anyway:
| do: do_reverse(:unicode_util.gc(rest), []) <> <<byte>> <> :unicode.characters_to_binary(acc) | |
| do: do_reverse(:unicode_util.gc(rest), [<<byte>> | acc]) |
There was a problem hiding this comment.
Im stuck, please help!
on OTP 29
iex> :unicode.characters_to_binary(["dc", [<<255>>, "b", "a"]])
{:error, "dc", [[<<255>>, "b", "a"]]}
There was a problem hiding this comment.
Ah, of course, the operation will fail due to the invalid byte.
|
Shouldn't this function raise |
|
@lukaszsamson Then all functions in String module would have to raise, which would be a BC |
|
String API assumes the inputs have been validated at boundary via |
|
A null byte is actually valid UTF-8 encoding. About invalid encodings, see this section on the module docs: https://elixir.hexdocs.pm/String.html#module-self-synchronization |
|
💚 💙 💜 💛 ❤️ |
Before
After