A Little Pitfall in Erlang String Handling
I stumbled upon echo.opera.com ā a service that prints out HTTP request headers ā and thought it would be fun to build my own. After implementing echo_rs in Rust, I got the itch to rewrite it in Erlang as a gen_tcp exercise.
Once I had it working, I noticed the layout was broken when displaying raw request data in hexadecimal.

After some debugging I traced the issue to the string:slice function. The approach was to split the raw request data into chunks of 0x10 bytes, convert each chunk to hexadecimal, then decode it as ASCII. The problem: string:slice doesn't strictly respect the requested length.
-define(ELEMENT_PER_LINE, 16).

Since string:slice couldn't do what I needed, the natural fix was to treat the data as binary ā Erlang is natively excellent at binary manipulation. The solution: split on binary boundaries first, then process each chunk.
-spec slice_binary(
binary(),
non_neg_integer(),
non_neg_integer()
) -> {ok, binary()}.
slice_binary(Bin, Start, Len) ->
case Len > byte_size(Bin) - Start of
true ->
<<_:Start/binary, Rest/binary>> = Bin,
{ok, Rest};
false ->
<<_:Start/binary, Rest/binary>> = Bin,
<<Slice:Len/binary, _/binary>> = Rest,
{ok, Slice}
end.
This guarantees we always get exactly the length we asked for.

The full source code is available at echo.