Browse Source

Make sure iolist split uses N length

The previous implementation would return "ok"
under certain situations when more data could
be fit into the buffer.

By making "ok" explicitly mean length is 0,
then we can simplify other parts of the codebase
and fix a bug that could cause us to send less
data then desired over the wire.
José Valim 6 years ago
parent
commit
41f3bdc9a9
1 changed files with 4 additions and 9 deletions
  1. 4 9
      src/cow_iolists.erl

+ 4 - 9
src/cow_iolists.erl

@@ -34,7 +34,7 @@ split(0, Rest, Acc) ->
 split(N, [], Acc) ->
 split(N, [], Acc) ->
 	{more, N, Acc};
 	{more, N, Acc};
 split(N, Binary, Acc) when byte_size(Binary) =< N ->
 split(N, Binary, Acc) when byte_size(Binary) =< N ->
-	{ok, lists:reverse([Binary|Acc]), <<>>};
+	{more, N - byte_size(Binary), [Binary|Acc]};
 split(N, Binary, Acc) when is_binary(Binary) ->
 split(N, Binary, Acc) when is_binary(Binary) ->
 	<< Before:N/binary, After/bits >> = Binary,
 	<< Before:N/binary, After/bits >> = Binary,
 	{ok, lists:reverse([Before|Acc]), After};
 	{ok, lists:reverse([Before|Acc]), After};
@@ -48,13 +48,7 @@ split(N, [Char|Tail], Acc) when is_integer(Char) ->
 split(N, [List|Tail], Acc0) ->
 split(N, [List|Tail], Acc0) ->
 	case split(N, List, Acc0) of
 	case split(N, List, Acc0) of
 		{ok, Before, After} ->
 		{ok, Before, After} ->
-			IolistSize = iolist_size(Before),
-			if
-				IolistSize < N ->
-					split(N - IolistSize, [After|Tail], lists:reverse(Before));
-				true ->
-					{ok, Before, [After|Tail]}
-			end;
+			{ok, Before, [After|Tail]};
 		{more, More, Acc} ->
 		{more, More, Acc} ->
 			split(More, Tail, Acc)
 			split(More, Tail, Acc)
 	end.
 	end.
@@ -72,7 +66,8 @@ split_test_() ->
 		{10, ["He", [<<"ll">>], $o, [["!"]]], "Hello!", ""},
 		{10, ["He", [<<"ll">>], $o, [["!"]]], "Hello!", ""},
 		{10, ["Hel"|<<"lo!">>], "Hello!", ""},
 		{10, ["Hel"|<<"lo!">>], "Hello!", ""},
 		{10, [[<<>>|<<>>], [], <<"Hello world!">>], "Hello worl", "d!"},
 		{10, [[<<>>|<<>>], [], <<"Hello world!">>], "Hello worl", "d!"},
-		{10, [[<<"He">>|<<"llo">>], [$\s], <<"world!">>], "Hello worl", "d!"}
+		{10, [[<<"He">>|<<"llo">>], [$\s], <<"world!">>], "Hello worl", "d!"},
+		{10, [[[]|<<"He">>], [[]|<<"llo wor">>]|<<"ld!">>], "Hello worl", "d!"}
 	],
 	],
 	[{iolist_to_binary(V), fun() ->
 	[{iolist_to_binary(V), fun() ->
 		{B, A} = split(N, V),
 		{B, A} = split(N, V),