This commit is contained in:
Magnus von Wachenfeldt 2024-02-08 23:24:44 +01:00
parent 8bd06a67ed
commit 8be51c0cf5
Signed by: magnus
GPG Key ID: A469F7D71D09F795
3 changed files with 37 additions and 9 deletions

View File

@ -20,7 +20,9 @@ defmodule Protohackers.PrimeTimeServer do
mode: :binary, mode: :binary,
active: false, active: false,
reuseaddr: true, reuseaddr: true,
exit_on_close: false exit_on_close: false,
packet: :line,
buffer: 1024 * 100
] ]
case :gen_tcp.listen(port, listen_options) do case :gen_tcp.listen(port, listen_options) do
@ -49,21 +51,43 @@ defmodule Protohackers.PrimeTimeServer do
## Helpers ## Helpers
defp handle_connection(socket) do defp handle_connection(socket) do
case recv_until_closed(socket, _buffer = "", _buffered_size = 0) do case parse_json(socket) do
{:ok, data} -> :gen_tcp.send(socket, data) :ok -> :ok
{:error, reason} -> Logger.error("Failed to receive data: #{inspect(reason)}") {:error, reason} -> Logger.error("Failed to receive data: #{inspect(reason)}")
end end
:gen_tcp.close(socket) :gen_tcp.close(socket)
end end
@limit _100_kb = 1024 * 100 defp parse_json(socket) do
defp recv_until_closed(socket, buffer, buffered_size) do
case :gen_tcp.recv(socket, 0, 10_000) do case :gen_tcp.recv(socket, 0, 10_000) do
{:ok, data} when buffered_size + byte_size(data) > @limit -> {:error, :buffer_overflow} {:ok, data} ->
{:ok, data} -> recv_until_closed(socket, [buffer, data], buffered_size + byte_size(data)) case Jason.decode(data) do
{:error, :closed} -> {:ok, buffer} {:ok, %{"method" => "isPrime", "number" => number}} when is_number(number) ->
{:error, reason} -> {:error, reason} Logger.debug("Received valid request for number: #{number}")
response = %{"method" => "isPrime", "prime" => prime?(number)}
:gen_tcp.send(socket, [Jason.encode!(response), ?\n])
parse_json(socket)
other ->
Logger.debug("Received invalid request: #{inspect(other)}")
:gen_tcp.send(socket, "malformed request\n")
{:error, :invalid_request}
end end
{:error, :closed} ->
:ok
{:error, reason} ->
{:error, reason}
end
end
defp prime?(number) when is_float(number), do: false
defp prime?(number) when number <= 1, do: false
defp prime?(number) when number in [2, 3], do: true
defp prime?(number) do
not Enum.any?(2..trunc(:math.sqrt(number)), &(rem(number, &1) == 0))
end end
end end

View File

@ -22,6 +22,7 @@ defmodule Protohackers.MixProject do
# Run "mix help deps" to learn about dependencies. # Run "mix help deps" to learn about dependencies.
defp deps do defp deps do
[ [
{:jason, "~> 1.4"}
# {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
] ]

3
mix.lock Normal file
View File

@ -0,0 +1,3 @@
%{
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
}