Packages
gnat
0.1.2
1.16.0
1.15.2
1.15.1
1.15.0
1.14.1
1.14.0
1.14.0-rc1
1.14.0-rc0
1.13.1
1.13.0
1.12.1
1.12.0
1.11.1
1.11.0
1.10.2
1.10.2-rc1
1.10.2-rc0
1.10.1
1.10.0
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.7.1
1.7.0
1.6.0
1.5.2
1.5.1
1.5.0
1.4.0
1.3.0
1.3.0-rc0
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.7.0
0.6.1
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
A nats client in pure elixir. Resilience, Performance, Ease-of-Use.
Current section
Files
Jump to
Current section
Files
lib/gnat/parser.ex
defmodule Gnat.Parser do
require Logger
# states: waiting, reading_message
defstruct [
partial: "",
state: :waiting,
]
def new, do: %Gnat.Parser{}
def parse(parser, data) do
data = parser.partial <> data
parser = %{parser | partial: ""}
parse(parser, data, [])
end
def parse(parser, "", parsed), do: {parser, Enum.reverse(parsed)}
def parse(parser, bytes, parsed) do
case :binary.match(bytes, "\r\n") do
{index, 2} ->
{command, "\r\n"<>rest} = String.split_at(bytes, index)
case parse_command(command, rest) do
:partial_message ->
parser = %{parser | partial: bytes}
parse(parser, "", parsed)
{message, rest} ->
parse(parser, rest, [message | parsed])
end
:nomatch ->
parse(%{parser | partial: bytes}, "", parsed)
end
end
defp parse_command(command, body) do
[operation | details] = String.split(command)
operation
|> String.upcase
|> parse_command(details, body)
end
defp parse_command("PING", _, body), do: {:ping, body}
defp parse_command("PONG", _, body), do: {:pong, body}
defp parse_command("MSG", [topic, sidstr, sizestr], body), do: parse_command("MSG", [topic, sidstr, nil, sizestr], body)
defp parse_command("MSG", [topic, sidstr, reply_to, sizestr], body) do
sid = String.to_integer(sidstr)
bytesize = String.to_integer(sizestr)
if byte_size(body) >= (bytesize + 2) do
<< message :: binary-size(bytesize), "\r\n", rest :: binary >> = body
{{:msg, topic, sid, reply_to, message}, rest}
else
:partial_message
end
end
defp parse_command("INFO", options, body) do
{{:info, Poison.Parser.parse!(options, keys: :atoms)}, body}
end
end